Files
loongoffice/chart2/source/view/main/GL3DRenderer.cxx
Caolán McNamara cba672f2c5 coverity#1215398 Uninitialized scalar field
Change-Id: I190cafda21a9e5969d8a353b272a0e92b5b65903
2014-09-02 12:14:46 +01:00

2581 lines
100 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <GL/glew.h>
#include "GL3DRenderer.hxx"
#include <vcl/opengl/OpenGLHelper.hxx>
#include <vcl/font.hxx>
#include <vcl/virdev.hxx>
#include <com/sun/star/awt/Size.hpp>
#include <StaticGeometry.h>
#include "glm/gtc/matrix_inverse.hpp"
#include <boost/checked_delete.hpp>
#define DEBUG_FBO 0
using namespace com::sun::star;
namespace chart {
namespace opengl3D {
namespace {
const int CORNER_DIVION_Y = 20;
const int CORNER_DIVION_Z = 20;
GLfloat texCoords[] = {
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f
};
glm::vec4 getColorAsVector(sal_uInt32 nColor)
{
return glm::vec4(((nColor & 0x00FF0000) >> 16) / 255.0f,
((nColor & 0x0000FF00) >> 8) / 255.0f,
(nColor & 0x000000FF) / 255.0f,
(0xFF - (nColor & 0xFF000000)/255.0));
}
}
TextureArrayInfo::TextureArrayInfo():
subTextureNum(0),
textureArrayWidth(0),
textureArrayHeight(0),
textureID(0)
{
}
OpenGL3DRenderer::OpenGL3DRenderer():
m_iWidth(0)
, m_iHeight(0)
, m_3DUBOBuffer(0)
, m_3DActualSizeLight(0)
, m_NormalBuffer(0)
, m_VertexBuffer(0)
, m_CubeVertexBuf(0)
, m_CubeElementBuf(0)
, m_CubeNormalBuf(0)
, m_BoundBox(0)
, m_BoundBoxNormal(0)
, m_TextTexCoordBuf(0)
, m_TextTexCoordBufBatch(0)
, m_RoundBarMesh()
, m_RenderVertexBuf(0)
, m_RenderTexCoordBuf(0)
, m_fViewAngle(30.0f)
, mbPickingMode(false)
, mnPickingFbo(0)
, mnPickingRboDepth(0)
, mnPickingRboColor(0)
, m_BatchModelMatrixBuf(0)
, m_BatchNormalMatrixBuf(0)
, m_BatchColorBuf(0)
, m_Batch3DUBOBuffer(0)
, m_Batch3DActualSizeLight(0)
, m_iLightNum(0)
, m_bHighLighting(false)
, m_uiSelectID(0)
, m_fScrollSpeed(0.0f)
, m_fScrollDistance(0.0f)
, m_fMinCoordX(0.0f)
, m_fMaxCoordX(0.0f)
, m_fCurDistance(0.0f)
, m_ScrollMoveMatrix(glm::mat4(1.0))
, m_bUndrawFlag(false)
{
m_Polygon3DInfo.lineOnly = false;
m_Polygon3DInfo.twoSidesLighting = false;
m_Polygon3DInfo.vertices = NULL;
m_Polygon3DInfo.normals = NULL;
m_Polygon3DInfo.lineWidth = 0.001f;
m_Extrude3DInfo.twoSidesLighting = false;
m_RoundBarMesh.iMeshSizes = 0;
}
OpenGL3DRenderer::~OpenGL3DRenderer()
{
ReleaseShapes();
// delete buffers
glDeleteBuffers(1, &m_CubeVertexBuf);
glDeleteBuffers(1, &m_CubeNormalBuf);
glDeleteBuffers(1, &m_CubeElementBuf);
glDeleteBuffers(1, &m_BoundBox);
glDeleteBuffers(1, &m_BoundBoxNormal);
glDeleteBuffers(1, &m_TextTexCoordBuf);
glDeleteBuffers(1, &m_RenderTexCoordBuf);
glDeleteBuffers(1, &m_RenderVertexBuf);
glDeleteBuffers(1, &m_3DUBOBuffer);
glDeleteBuffers(1, &m_VertexBuffer);
glDeleteBuffers(1, &m_NormalBuffer);
glDeleteBuffers(1, &m_Batch3DUBOBuffer);
glDeleteBuffers(1, &m_3DUBOBuffer);
glDeleteBuffers(1, &m_3DUBOBuffer);
glDeleteBuffers(1, &m_TextTexCoordBufBatch);
glDeleteFramebuffers(1, &mnPickingFbo);
glDeleteRenderbuffers(1, &mnPickingRboDepth);
glDeleteRenderbuffers(1, &mnPickingRboColor);
for (size_t i = 0; i < m_TextInfoBatch.texture.size(); i++)
{
glDeleteTextures(1, &m_TextInfoBatch.texture[i].textureID);
}
m_TextInfoBatch.texture.clear();
}
OpenGL3DRenderer::ShaderResources::ShaderResources()
: m_b330Support(false)
, m_bScrollFlag(false)
, m_3DProID(0)
, m_3DProjectionID(0)
, m_3DViewID(0)
, m_3DModelID(0)
, m_3DNormalMatrixID(0)
, m_3DVertexID(0)
, m_3DNormalID(0)
, m_3DMinCoordXID(0)
, m_3DMaxCoordXID(0)
, m_3DUndrawID(0)
, m_3DMaterialAmbientID(0)
, m_3DMaterialDiffuseID(0)
, m_3DMaterialSpecularID(0)
, m_3DMaterialColorID(0)
, m_3DMaterialTwoSidesID(0)
, m_3DMaterialShininessID(0)
, m_3DLightColorID(0)
, m_3DLightPosID(0)
, m_3DLightPowerID(0)
, m_3DLightNumID(0)
, m_3DLightAmbientID(0)
, m_TextProID(0)
, m_TextMatrixID(0)
, m_TextVertexID(0)
, m_TextTexCoordID(0)
, m_TextTexID(0)
, m_ScreenTextProID(0)
, m_ScreenTextVertexID(0)
, m_ScreenTextTexCoordID(0)
, m_ScreenTextTexID(0)
, m_ScreenTextColorID(0)
, m_CommonProID(0)
, m_2DVertexID(0)
, m_2DColorID(0)
, m_MatrixID(0)
, m_3DBatchProID(0)
, m_3DBatchProjectionID(0)
, m_3DBatchViewID(0)
, m_3DBatchModelID(0)
, m_3DBatchNormalMatrixID(0)
, m_3DBatchVertexID(0)
, m_3DBatchNormalID(0)
, m_3DBatchColorID(0)
, m_3DBatchTransMatrixID(0)
, m_3DBatchMinCoordXID(0)
, m_3DBatchMaxCoordXID(0)
, m_3DBatchUndrawID(0)
, mbTexBatchSupport(false)
, m_BatchTextProID(0)
, m_BatchTextMatrixID(0)
, m_BatchTextVertexID(0)
, m_BatchTextTexCoordID(0)
, m_BatchTextTexID(0)
{
}
OpenGL3DRenderer::ShaderResources::~ShaderResources()
{
glDeleteProgram(m_CommonProID);
glDeleteProgram(m_TextProID);
glDeleteProgram(m_ScreenTextProID);
glDeleteProgram(m_3DProID);
glDeleteProgram(m_3DBatchProID);
glDeleteProgram(m_BatchTextProID);
}
void OpenGL3DRenderer::CheckGLSLVersion()
{
maResources.m_b330Support = GLEW_VERSION_3_3 == 1;
}
void OpenGL3DRenderer::ShaderResources::LoadShaders()
{
CHECK_GL_ERROR();
if (m_b330Support)
{
m_3DProID = OpenGLHelper::LoadShaders("shape3DVertexShader", "shape3DFragmentShader");
m_3DProjectionID = glGetUniformLocation(m_3DProID, "P");
m_3DViewID = glGetUniformLocation(m_3DProID, "V");
m_3DModelID = glGetUniformLocation(m_3DProID, "M");
m_3DNormalMatrixID = glGetUniformLocation(m_3DProID, "normalMatrix");
m_3DVertexID = glGetAttribLocation(m_3DProID, "vertexPositionModelspace");
m_3DNormalID = glGetAttribLocation(m_3DProID, "vertexNormalModelspace");
CHECK_GL_ERROR();
if (m_bScrollFlag)
{
m_3DBatchProID = OpenGLHelper::LoadShaders("shape3DVertexShaderBatchScroll", "shape3DFragmentShaderBatchScroll");
m_3DBatchTransMatrixID = glGetUniformLocation(m_3DBatchProID, "transMatrix");
m_3DBatchMinCoordXID = glGetUniformLocation(m_3DBatchProID, "minCoordX");
m_3DBatchMaxCoordXID = glGetUniformLocation(m_3DBatchProID, "maxCoordX");
m_3DBatchUndrawID = glGetUniformLocation(m_3DBatchProID, "undraw");
}
else
m_3DBatchProID = OpenGLHelper::LoadShaders("shape3DVertexShaderBatch", "shape3DFragmentShaderBatch");
CHECK_GL_ERROR();
m_3DBatchProjectionID = glGetUniformLocation(m_3DBatchProID, "P");
m_3DBatchViewID = glGetUniformLocation(m_3DBatchProID, "V");
m_3DBatchModelID = glGetAttribLocation(m_3DBatchProID, "M");
m_3DBatchNormalMatrixID = glGetAttribLocation(m_3DBatchProID, "normalMatrix");
m_3DBatchVertexID = glGetAttribLocation(m_3DBatchProID, "vertexPositionModelspace");
m_3DBatchNormalID = glGetAttribLocation(m_3DBatchProID, "vertexNormalModelspace");
m_3DBatchColorID = glGetAttribLocation(m_3DBatchProID, "barColor");
#if !defined MACOSX
//check whether the texture array is support
mbTexBatchSupport = GLEW_EXT_texture_array == 1;
#endif
CHECK_GL_ERROR();
if (mbTexBatchSupport)
{
m_BatchTextProID = OpenGLHelper::LoadShaders("textVertexShaderBatch", "textFragmentShaderBatch");
m_BatchTextMatrixID = glGetUniformLocation(m_BatchTextProID, "MVP");
m_BatchTextTexID = glGetUniformLocation(m_BatchTextProID, "texArray");
m_BatchTextVertexID = glGetAttribLocation(m_BatchTextProID, "vPosition");
m_BatchTextTexCoordID = glGetAttribLocation(m_BatchTextProID, "texCoord");
}
mbTexBatchSupport = m_BatchTextProID ? true : false;
CHECK_GL_ERROR();
}
else
{
CHECK_GL_ERROR();
//use 300
m_3DProID = OpenGLHelper::LoadShaders("shape3DVertexShaderV300", "shape3DFragmentShaderV300");
m_3DProjectionID = glGetUniformLocation(m_3DProID, "P");
m_3DViewID = glGetUniformLocation(m_3DProID, "V");
m_3DModelID = glGetUniformLocation(m_3DProID, "M");
m_3DNormalMatrixID = glGetUniformLocation(m_3DProID, "normalMatrix");
m_3DMaterialAmbientID = glGetUniformLocation(m_3DProID, "materialAmbient");
m_3DMaterialDiffuseID = glGetUniformLocation(m_3DProID, "materialDiffuse");
m_3DMaterialSpecularID = glGetUniformLocation(m_3DProID, "materialSpecular");
m_3DMaterialColorID = glGetUniformLocation(m_3DProID, "materialColor");
m_3DMaterialTwoSidesID = glGetUniformLocation(m_3DProID, "twoSidesLighting");
m_3DMaterialShininessID = glGetUniformLocation(m_3DProID, "materialShininess");
m_3DLightColorID = glGetUniformLocation(m_3DProID, "lightColor");
m_3DLightPosID = glGetUniformLocation(m_3DProID, "lightPosWorldspace");
m_3DLightPowerID = glGetUniformLocation(m_3DProID, "lightPower");
m_3DLightNumID = glGetUniformLocation(m_3DProID, "lightNum");
m_3DLightAmbientID = glGetUniformLocation(m_3DProID, "lightAmbient");
m_3DMinCoordXID = glGetUniformLocation(m_3DProID, "minCoordX");
m_3DMaxCoordXID = glGetUniformLocation(m_3DProID, "maxCoordX");
m_3DUndrawID = glGetUniformLocation(m_3DProID, "undraw");
m_3DVertexID = glGetAttribLocation(m_3DProID, "vertexPositionModelspace");
m_3DNormalID = glGetAttribLocation(m_3DProID, "vertexNormalModelspace");
}
CHECK_GL_ERROR();
if (!mbTexBatchSupport)
{
m_TextProID = OpenGLHelper::LoadShaders("textVertexShader", "textFragmentShader");
m_TextMatrixID = glGetUniformLocation(m_TextProID, "MVP");
m_TextVertexID = glGetAttribLocation(m_TextProID, "vPosition");
m_TextTexCoordID = glGetAttribLocation(m_TextProID, "texCoord");
m_TextTexID = glGetUniformLocation(m_TextProID, "TextTex");
}
CHECK_GL_ERROR();
m_ScreenTextProID = OpenGLHelper::LoadShaders("screenTextVertexShader", "screenTextFragmentShader");
m_ScreenTextVertexID = glGetAttribLocation(m_ScreenTextProID, "vPosition");
m_ScreenTextTexCoordID = glGetAttribLocation(m_ScreenTextProID, "texCoord");
m_ScreenTextTexID = glGetUniformLocation(m_ScreenTextProID, "TextTex");
m_ScreenTextColorID = glGetUniformLocation(m_ScreenTextProID, "textColor");
CHECK_GL_ERROR();
m_CommonProID = OpenGLHelper::LoadShaders("commonVertexShader", "commonFragmentShader");
m_MatrixID = glGetUniformLocation(m_CommonProID, "MVP");
m_2DColorID = glGetUniformLocation(m_CommonProID, "vColor");
m_2DVertexID = glGetAttribLocation(m_CommonProID, "vPosition");
CHECK_GL_ERROR();
}
OpenGL3DRenderer::PickingShaderResources::PickingShaderResources()
: m_CommonProID(0)
, m_2DVertexID(0)
, m_2DColorID(0)
, m_MatrixID(0)
, m_ModelID(0)
, m_MinCoordXID(0)
, m_MaxCoordXID(0)
{
}
OpenGL3DRenderer::PickingShaderResources::~PickingShaderResources()
{
glDeleteProgram(m_CommonProID);
}
void OpenGL3DRenderer::PickingShaderResources::LoadShaders()
{
m_CommonProID = OpenGLHelper::LoadShaders("pickingVertexShader", "pickingFragmentShader");
m_MatrixID = glGetUniformLocation(m_CommonProID, "MVP");
m_2DVertexID = glGetAttribLocation(m_CommonProID, "vPosition");
m_2DColorID = glGetUniformLocation(m_CommonProID, "vColor");
m_ModelID = glGetUniformLocation(m_CommonProID, "M");
m_MinCoordXID = glGetUniformLocation(m_CommonProID, "minCoordX");
m_MaxCoordXID = glGetUniformLocation(m_CommonProID, "maxCoordX");
}
void OpenGL3DRenderer::SetCameraInfo(const glm::vec3& pos, const glm::vec3& direction, const glm::vec3& up)
{
m_CameraInfo.cameraPos = pos;
m_CameraInfo.cameraOrg = direction;
m_CameraInfo.cameraUp = up;
}
void OpenGL3DRenderer::init()
{
CHECK_GL_ERROR();
glEnable(GL_CULL_FACE);
CHECK_GL_ERROR();
glCullFace(GL_BACK);
CHECK_GL_ERROR();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// Enable depth test
CHECK_GL_ERROR();
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
CHECK_GL_ERROR();
glDepthFunc(GL_LESS);
CHECK_GL_ERROR();
glEnable(GL_LINE_SMOOTH);
CHECK_GL_ERROR();
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
CHECK_GL_ERROR();
glEnable(GL_BLEND);
CHECK_GL_ERROR();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
CHECK_GL_ERROR();
glEnable(GL_MULTISAMPLE);
CHECK_GL_ERROR();
ClearBuffer();
CHECK_GL_ERROR();
glGenBuffers(1, &m_CubeVertexBuf);
glGenBuffers(1, &m_CubeNormalBuf);
glGenBuffers(1, &m_CubeElementBuf);
glGenBuffers(1, &m_VertexBuffer);
glGenBuffers(1, &m_NormalBuffer);
glGenBuffers(1, &m_BatchModelMatrixBuf);
glGenBuffers(1, &m_BatchNormalMatrixBuf);
glGenBuffers(1, &m_BatchColorBuf);
glGenBuffers(1, &m_TextTexCoordBufBatch);
glGenBuffers(1, &m_BoundBox);
glBindBuffer(GL_ARRAY_BUFFER, m_BoundBox);
glBufferData(GL_ARRAY_BUFFER, sizeof(boundBox), boundBox, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERROR();
glGenBuffers(1, &m_BoundBoxNormal);
glBindBuffer(GL_ARRAY_BUFFER, m_BoundBoxNormal);
glBufferData(GL_ARRAY_BUFFER, sizeof(boundBoxNormal), boundBoxNormal, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERROR();
m_fViewAngle = 30.0f;
m_3DProjection = glm::perspective(m_fViewAngle, (float)m_iWidth / (float)m_iHeight, 0.01f, 6000.0f);
CheckGLSLVersion();
CHECK_GL_ERROR();
maResources.LoadShaders();
maPickingResources.LoadShaders();
glGenBuffers(1, &m_TextTexCoordBuf);
glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &m_RenderTexCoordBuf);
glBindBuffer(GL_ARRAY_BUFFER, m_RenderTexCoordBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(coordReverseVertices), coordReverseVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenBuffers(1, &m_RenderVertexBuf);
glBindBuffer(GL_ARRAY_BUFFER, m_RenderVertexBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertices), squareVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERROR();
OpenGLHelper::createFramebuffer(m_iWidth, m_iHeight, mnPickingFbo, mnPickingRboDepth, mnPickingRboColor);
m_Extrude3DInfo.rounded = false;
CHECK_GL_ERROR();
if (maResources.m_b330Support)
{
Init3DUniformBlock();
InitBatch3DUniformBlock();
}
m_TextInfoBatch.batchNum = 512;
CHECK_GL_ERROR();
glViewport(0, 0, m_iWidth, m_iHeight);
Set3DSenceInfo(0xFFFFFF, true);
m_GlobalScaleMatrix = glm::scale(glm::vec3(0.01f, 0.01f, 0.01f));
}
void OpenGL3DRenderer::SetSize(const Size& rSize)
{
m_iWidth = rSize.Width();
m_iHeight = rSize.Height();
}
void OpenGL3DRenderer::AddVertexData(GLuint vertexBuf)
{
glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
glBufferData(GL_ARRAY_BUFFER, m_Vertices.size() * sizeof(glm::vec3), &m_Vertices[0], GL_STATIC_DRAW);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void OpenGL3DRenderer::AddNormalData(GLuint normalBuf)
{
glBindBuffer(GL_ARRAY_BUFFER, normalBuf);
glBufferData(GL_ARRAY_BUFFER, m_Normals.size() * sizeof(glm::vec3), &m_Normals[0], GL_STATIC_DRAW);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void OpenGL3DRenderer::AddIndexData(GLuint indexBuf)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_Indices.size() * sizeof(unsigned short), &m_Indices[0], GL_STATIC_DRAW);
CHECK_GL_ERROR();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
bool OpenGL3DRenderer::GetSimilarVertexIndex(PackedVertex & packed,
std::map<PackedVertex,unsigned short> & VertexToOutIndex,
unsigned short & result
)
{
std::map<PackedVertex,unsigned short>::iterator it = VertexToOutIndex.find(packed);
if ( it == VertexToOutIndex.end() )
{
return false;
}
else
{
result = it->second;
return true;
}
}
void OpenGL3DRenderer::SetVertex(PackedVertex &packed,
std::map<PackedVertex,unsigned short> &VertexToOutIndex,
std::vector<glm::vec3> &vertex,
std::vector<glm::vec3> &normal,
std::vector<unsigned short> &indices)
{
unsigned short index;
bool found = GetSimilarVertexIndex(packed, VertexToOutIndex, index);
if ( found )
{ // A similar vertex is already in the VBO, use it instead !
indices.push_back( index );
}
else
{ // If not, it needs to be added in the output data.
vertex.push_back(packed.position);
normal.push_back(packed.normal);
size_t newindex = vertex.size() - 1;
indices.push_back( newindex );
VertexToOutIndex[ packed ] = newindex;
}
}
void OpenGL3DRenderer::CreateActualRoundedCube(float fRadius, int iSubDivY, int iSubDivZ, float width, float height, float depth)
{
float topThreshold = depth - 2 * fRadius;
float bottomThreshold = fRadius;
std::vector<glm::vec3> vertices;
std::vector<glm::vec3> normals;
GenerateRoundCornerBar(vertices, normals, fRadius, iSubDivY, iSubDivZ, width, height, depth);
std::map<PackedVertex,unsigned short> VertexToOutIndex;
glm::vec3 actualVerteices[3];
glm::vec3 actualNormals[3];
std::vector<unsigned short> indices[5];
glm::vec3 externSurNormal;
glm::mat4 corrctCoord = glm::translate(glm::vec3(width / 2.0f, height / 2.0f, depth / 2.0f - fRadius));
m_RoundBarMesh.topThreshold = topThreshold;
m_RoundBarMesh.bottomThreshold = bottomThreshold;
m_RoundBarMesh.iMeshStartIndices = m_Vertices.size();
for (int k = 0; k < 5; k++)
{
m_RoundBarMesh.iElementStartIndices[k] = indices[k].size();
}
for (size_t i = 0; i < vertices.size(); i += 3)
{
for (int k = 0; k < 3; k++)
{
actualVerteices[k] = glm::vec3(corrctCoord * glm::vec4(vertices[i + k], 1.0));
actualNormals[k] = normals[i + k];
}
float maxZ = std::max(std::max(actualVerteices[0].z, actualVerteices[1].z), actualVerteices[2].z);
float minZ = std::min(std::min(actualVerteices[0].z, actualVerteices[1].z), actualVerteices[2].z);
int surfaceIndex = (minZ >= topThreshold - 0.001) ? TOP_SURFACE : ((maxZ <= bottomThreshold + 0.001) ? BOTTOM_SURFACE : MIDDLE_SURFACE);
for (int k = 0; k < 3; k++)
{
{
PackedVertex packed = {actualVerteices[k], actualNormals[k]};
SetVertex(packed, VertexToOutIndex, m_Vertices, m_Normals, indices[surfaceIndex]);
}
//add extern
if ((surfaceIndex == TOP_SURFACE) || (surfaceIndex == BOTTOM_SURFACE))
{
actualVerteices[k].z = 0.0f;
externSurNormal = (surfaceIndex == TOP_SURFACE) ? glm::vec3(0.0, 0.0, 1.0) : glm::vec3(0.0, 0.0, -1.0);
int tmpSurfaceIndex = (surfaceIndex == TOP_SURFACE) ? FLAT_TOP_SURFACE : FLAT_BOTTOM_SURFACE;
PackedVertex packed = {actualVerteices[k], externSurNormal};
SetVertex(packed, VertexToOutIndex, m_Vertices, m_Normals, indices[tmpSurfaceIndex]);
}
}
}
//create index below
m_RoundBarMesh.iMeshSizes = m_Vertices.size() - m_RoundBarMesh.iMeshStartIndices;
for (int k = 0; k < 5; k++)
{
m_RoundBarMesh.iElementSizes[k] = indices[k].size() - m_RoundBarMesh.iElementStartIndices[k];
m_RoundBarMesh.iElementStartIndices[k] = m_Indices.size() * sizeof(unsigned short);
for (unsigned int IdxCnt = 0; IdxCnt < indices[k].size(); IdxCnt++)
{
m_Indices.push_back(indices[k][IdxCnt]);
}
indices[k].clear();
}
vertices.clear();
normals.clear();
VertexToOutIndex.clear();
}
int OpenGL3DRenderer::GenerateRoundCornerBar(std::vector<glm::vec3> &vertices, std::vector<glm::vec3> &normals, float fRadius, int iSubDivY, int iSubDivZ, float width, float height, float depth)
{
//float fAddAngleY = 360.0f/float(iSubDivY), fAddAngleZ = 180.0f/float(iSubDivZ);
float fAddAngleY = 360.0f/float(iSubDivY);
float fAddAngleZ = 180.0f/float(iSubDivZ);
float fCurAngleY = 0.0f;
int iStepsY = 1;
const float PI = float(atan(1.0)*4.0);
int iFacesAdded = 0;
float xOffset[] = {(width / 2 - fRadius), -(width / 2 - fRadius), -(width / 2 - fRadius), (width / 2 - fRadius), (width / 2 - fRadius)};
float yOffset[] = {(height / 2 - fRadius), -(height / 2 - fRadius), (height / 2 - fRadius)};
float zOffset[] = {-(depth / 2 - fRadius), -(depth / 2 - fRadius), (depth / 2 - fRadius), (depth / 2 - fRadius), -(depth / 2 - fRadius)};
int iIndices[] = {0, 1, 2, 2, 3, 0};
while(iStepsY <= iSubDivY)
{
float fNextAngleY = fCurAngleY+fAddAngleY;
if ((fCurAngleY < 90.0f) && (fNextAngleY >= 90.0f))
{
fNextAngleY = 90.0f;
}
else if ((fCurAngleY < 180.0f) && (fNextAngleY >= 180.0f))
{
fNextAngleY = 180.0f;
}
else if ((fCurAngleY < 270.0f) && (fNextAngleY >= 270.0f))
{
fNextAngleY = 270.0f;
}
else if ((fCurAngleY < 360.0f) && (fNextAngleY >= 360.0f))
{
fNextAngleY = 360.0f;
}
float fSineY = sin(fCurAngleY/180.0f*PI), fCosY = cos(fCurAngleY/180.0f*PI);
float fNextSineY = sin(fNextAngleY/180.0f*PI), fNextCosY = cos(fNextAngleY/180.0f*PI);
glm::vec3 vDirY(fCosY, 0.0f, -fSineY), vNextDirY(fNextCosY, 0.0f, -fNextSineY);
float fCurAngleZ = 0.0f;
int iStepsZ = 1;
int xzIndex = 0;
if ((fCurAngleY >= 0) && (fCurAngleY < 90.0))
{
xzIndex = 0;
}
else if ((fCurAngleY >= 90) && (fCurAngleY < 180.0))
{
xzIndex = 1;
}
else if ((fCurAngleY >= 180) && (fCurAngleY < 270.0))
{
xzIndex = 2;
}
else if ((fCurAngleY >= 270) && (fCurAngleY < 360.0))
{
xzIndex = 3;
}
while(iStepsZ <= iSubDivZ)
{
int yIndex = 0;
float fNextAngleZ = fCurAngleZ+fAddAngleZ;
float fSineZ = sin(fCurAngleZ/180.0f*PI), fCosZ = cos(fCurAngleZ/180.0f*PI);
float fNextSineZ = sin(fNextAngleZ/180.0f*PI), fNextCosZ = cos(fNextAngleZ/180.0f*PI);
if ((fCurAngleZ < 90.0f) && (fNextAngleZ >= 90.0f))
{
fNextAngleZ = 90.0f;
}
if ((fCurAngleZ >= 0.0f) && (fCurAngleZ < 90.0f))
{
yIndex = 0;
}
else
{
yIndex = 1;
}
glm::vec3 vQuadPoints[] =
{
glm::vec3(vDirY.x*fSineZ*fRadius, fCosZ*fRadius, vDirY.z*fSineZ*fRadius),
glm::vec3(vDirY.x*fNextSineZ*fRadius, fNextCosZ*fRadius, vDirY.z*fNextSineZ*fRadius),
glm::vec3(vNextDirY.x*fNextSineZ*fRadius, fNextCosZ*fRadius, vNextDirY.z*fNextSineZ*fRadius),
glm::vec3(vNextDirY.x*fSineZ*fRadius, fCosZ*fRadius, vNextDirY.z*fSineZ*fRadius)
};
glm::vec3 vActualQuadPoints[] =
{
glm::vec3(vQuadPoints[0].x + xOffset[xzIndex], vQuadPoints[0].y + yOffset[yIndex], vQuadPoints[0].z + zOffset[xzIndex]),
glm::vec3(vQuadPoints[1].x + xOffset[xzIndex], vQuadPoints[1].y + yOffset[yIndex], vQuadPoints[1].z + zOffset[xzIndex]),
glm::vec3(vQuadPoints[2].x + xOffset[xzIndex], vQuadPoints[2].y + yOffset[yIndex], vQuadPoints[2].z + zOffset[xzIndex]),
glm::vec3(vQuadPoints[3].x + xOffset[xzIndex], vQuadPoints[3].y + yOffset[yIndex], vQuadPoints[3].z + zOffset[xzIndex])
};
glm::vec3 vNormals[] =
{
glm::normalize(vQuadPoints[0]),
glm::normalize(vQuadPoints[1]),
glm::normalize(vQuadPoints[2]),
glm::normalize(vQuadPoints[3])
};
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vActualQuadPoints[index]);
normals.push_back(vNormals[index]);
}
iFacesAdded += 2; // Keep count of added faces
if (((fCurAngleY < 90.0) && (fNextAngleY >= 90.0)) ||
((fCurAngleY < 180.0) && (fNextAngleY >= 180.0)) ||
((fCurAngleY < 270.0) && (fNextAngleY >= 270.0)) ||
((fCurAngleY < 360.0) && (fNextAngleY >= 360.0)))
{
glm::vec3 vXZQuadNextPoints[] =
{
glm::vec3(vQuadPoints[3].x + xOffset[xzIndex], vQuadPoints[3].y + yOffset[yIndex], vQuadPoints[3].z + zOffset[xzIndex]),
glm::vec3(vQuadPoints[2].x + xOffset[xzIndex], vQuadPoints[2].y + yOffset[yIndex], vQuadPoints[2].z + zOffset[xzIndex]),
glm::vec3(vQuadPoints[2].x + xOffset[xzIndex + 1], vQuadPoints[2].y + yOffset[yIndex], vQuadPoints[2].z + zOffset[xzIndex + 1]),
glm::vec3(vQuadPoints[3].x + xOffset[xzIndex + 1], vQuadPoints[3].y + yOffset[yIndex], vQuadPoints[3].z + zOffset[xzIndex + 1])
};
glm::vec3 vXZNextNormals[] =
{
glm::normalize(vQuadPoints[3]),
glm::normalize(vQuadPoints[2]),
glm::normalize(vQuadPoints[2]),
glm::normalize(vQuadPoints[3])
};
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vXZQuadNextPoints[index]);
normals.push_back(vXZNextNormals[index]);
}
iFacesAdded += 2;
}
if ((fCurAngleZ < 90.0) && (fNextAngleZ >= 90.0))
{
glm::vec3 vYQuadNextPoints[] =
{
glm::vec3(vQuadPoints[1].x + xOffset[xzIndex], vQuadPoints[1].y + yOffset[yIndex], vQuadPoints[1].z + zOffset[xzIndex]),
glm::vec3(vQuadPoints[1].x + xOffset[xzIndex], vQuadPoints[1].y + yOffset[yIndex + 1], vQuadPoints[1].z + zOffset[xzIndex]),
glm::vec3(vQuadPoints[2].x + xOffset[xzIndex], vQuadPoints[2].y + yOffset[yIndex + 1], vQuadPoints[2].z + zOffset[xzIndex]),
glm::vec3(vQuadPoints[2].x + xOffset[xzIndex], vQuadPoints[2].y + yOffset[yIndex], vQuadPoints[2].z + zOffset[xzIndex])
};
glm::vec3 vYNextNormals[] =
{
glm::normalize(vQuadPoints[1]),
glm::normalize(vQuadPoints[1]),
glm::normalize(vQuadPoints[2]),
glm::normalize(vQuadPoints[2])
};
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vYQuadNextPoints[index]);
normals.push_back(vYNextNormals[index]);
}
iFacesAdded += 2;
}
iStepsZ++;
if ((iStepsZ > iSubDivZ) && (fCurAngleZ < 180.0f))
{
iStepsZ--;
}
fCurAngleZ = fNextAngleZ;
}
iStepsY++;
if ((iStepsY > iSubDivY) && (fCurAngleY < 360.0f))
{
iStepsY--;
}
fCurAngleY = fNextAngleY;
}
//draw the rectangle face
//top surface
glm::vec3 vTopPoints[] =
{
glm::vec3(xOffset[0], height / 2, zOffset[0]),
glm::vec3(xOffset[1], height / 2, zOffset[1]),
glm::vec3(xOffset[2], height / 2, zOffset[2]),
glm::vec3(xOffset[3], height / 2, zOffset[3])
};
glm::vec3 vTopNormal = glm::vec3(0.0f, 1.0f, 0.0f);
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vTopPoints[index]);
normals.push_back(vTopNormal);
}
iFacesAdded += 2;
//bottom surface
glm::vec3 vBottomPoints[] =
{
glm::vec3(xOffset[3], -height / 2, zOffset[3]),
glm::vec3(xOffset[2], -height / 2, zOffset[2]),
glm::vec3(xOffset[1], -height / 2, zOffset[1]),
glm::vec3(xOffset[0], -height / 2, zOffset[0])
};
glm::vec3 vBottomNormal = glm::vec3(0.0f, -1.0f, 0.0f);
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vBottomPoints[index]);
normals.push_back(vBottomNormal);
}
iFacesAdded += 2;
//left surface
glm::vec3 vLeftPoints[] =
{
glm::vec3(-width / 2, yOffset[0], zOffset[0]),
glm::vec3(-width / 2, yOffset[1], zOffset[1]),
glm::vec3(-width / 2, yOffset[1], zOffset[2]),
glm::vec3(-width / 2, yOffset[0], zOffset[3])
};
glm::vec3 vLeftNormal = glm::vec3(-1.0f, 0.0f, 0.0f);
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vLeftPoints[index]);
normals.push_back(vLeftNormal);
}
//right surface
glm::vec3 vRightPoints[] =
{
glm::vec3(width / 2, yOffset[0], zOffset[3]),
glm::vec3(width / 2, yOffset[1], zOffset[2]),
glm::vec3(width / 2, yOffset[1], zOffset[1]),
glm::vec3(width / 2, yOffset[0], zOffset[0])
};
glm::vec3 vRightNormal = glm::vec3(1.0f, 0.0f, 0.0f);
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vRightPoints[index]);
normals.push_back(vRightNormal);
}
iFacesAdded += 2;
//front surface
glm::vec3 vFrontPoints[] =
{
glm::vec3(xOffset[0], yOffset[0], depth / 2),
glm::vec3(xOffset[1], yOffset[0], depth / 2),
glm::vec3(xOffset[2], yOffset[1], depth / 2),
glm::vec3(xOffset[3], yOffset[1], depth / 2)
};
glm::vec3 vFrontNormal = glm::vec3(0.0f, 0.0f, 1.0f);
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vFrontPoints[index]);
normals.push_back(vFrontNormal);
}
//back surface
glm::vec3 vBackPoints[] =
{
glm::vec3(xOffset[0], yOffset[1], -depth / 2),
glm::vec3(xOffset[1], yOffset[1], -depth / 2),
glm::vec3(xOffset[2], yOffset[0], -depth / 2),
glm::vec3(xOffset[3], yOffset[0], -depth / 2)
};
glm::vec3 vBackNormal = glm::vec3(0.0f, 0.0f, -1.0f);
for (int i = 0; i < 6; i++)
{
int index = iIndices[i];
vertices.push_back(vBackPoints[index]);
normals.push_back(vBackNormal);
}
iFacesAdded += 2;
return iFacesAdded;
}
void OpenGL3DRenderer::RenderLine3D(const Polygon3DInfo& polygon)
{
CHECK_GL_ERROR();
glUseProgram(maResources.m_CommonProID);
PosVecf3 trans = {0.0f, 0, 0.0};
PosVecf3 angle = {0.0f, 0.0f, 0.0f};
PosVecf3 scale = {1.0f, 1.0f, 1.0f};
MoveModelf(trans, angle, scale);
m_Model = m_GlobalScaleMatrix * m_Model;
m_3DMVP = m_3DProjection * m_3DView * m_Model;
for (size_t i = 0; i < polygon.verticesList.size(); i++)
{
//move the circle to the pos, and scale using the xScale and Y scale
Vertices3D *pointList = polygon.verticesList[i];
//if line only, using the common shader to render
//fill vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, pointList->size() * sizeof(glm::vec3), &pointList[0][0], GL_STATIC_DRAW);
if(mbPickingMode)
glUniform4fv(maResources.m_2DColorID, 1, &polygon.id[0]);
else
glUniform4fv(maResources.m_2DColorID, 1, &polygon.polygonColor[0]);
glUniformMatrix4fv(maResources.m_MatrixID, 1, GL_FALSE, &m_3DMVP[0][0]);
CHECK_GL_ERROR();
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(maResources.m_2DVertexID);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
CHECK_GL_ERROR();
glVertexAttribPointer(maResources.m_2DVertexID, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
CHECK_GL_ERROR();
glLineWidth(polygon.lineWidth);
CHECK_GL_ERROR();
glDrawArrays(GL_LINE_STRIP, 0, pointList->size());
CHECK_GL_ERROR();
glDisableVertexAttribArray(maResources.m_2DVertexID);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERROR();
}
glUseProgram(0);
CHECK_GL_ERROR();
}
void OpenGL3DRenderer::RenderPolygon3D(const Polygon3DInfo& polygon)
{
CHECK_GL_ERROR();
size_t verticesNum = polygon.verticesList.size();
size_t normalsNum = polygon.normalsList.size();
//check whether the number of vertices and normals are equal
if (m_CameraInfo.cameraPos.z >= 0.0f)
glPolygonOffset(1.0, 1.0);
else
glPolygonOffset(-1.0, -1.0);
CHECK_GL_ERROR();
if (verticesNum != normalsNum)
{
return ;
}
glBindBuffer(GL_UNIFORM_BUFFER, 0);
CHECK_GL_ERROR();
if(mbPickingMode)
{
glUseProgram(maPickingResources.m_CommonProID);
float minCoordX = 0.0f;
float maxCoordX = m_fMinCoordX + m_fMaxCoordX;
glUniform1fv(maPickingResources.m_MinCoordXID, 1, &minCoordX);
glUniform1fv(maPickingResources.m_MaxCoordXID, 1, &maxCoordX);
}
else
{
glUseProgram(maResources.m_3DProID);
glUniformMatrix4fv(maResources.m_3DViewID, 1, GL_FALSE, &m_3DView[0][0]);
glUniformMatrix4fv(maResources.m_3DProjectionID, 1, GL_FALSE, &m_3DProjection[0][0]);
CHECK_GL_ERROR();
if (maResources.m_b330Support)
{
//update ubo
Update3DUniformBlock();
glBindBuffer(GL_UNIFORM_BUFFER, m_3DUBOBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, m_3DActualSizeLight, sizeof(MaterialParameters), &polygon.material);
CHECK_GL_ERROR();
}
else
{
float minCoordX = 0.0f;
float maxCoordX = m_fMinCoordX + m_fMaxCoordX;
glUniform1fv(maResources.m_3DMinCoordXID, 1, &minCoordX);
glUniform1fv(maResources.m_3DMaxCoordXID, 1, &maxCoordX);
glUniform1i(maResources.m_3DUndrawID, m_bUndrawFlag);
CHECK_GL_ERROR();
//update light information
glUniform4fv(maResources.m_3DLightColorID, m_iLightNum, (GLfloat*)m_LightColor);
glUniform4fv(maResources.m_3DLightPosID, m_iLightNum, (GLfloat*)m_PositionWorldspace);
glUniform1fv(maResources.m_3DLightPowerID, m_iLightNum, m_fLightPower);
glUniform1i(maResources.m_3DLightNumID, m_iLightNum);
glUniform4fv(maResources.m_3DLightAmbientID, 1, &m_Ambient[0]);
CHECK_GL_ERROR();
//update meterial information
glUniform4fv(maResources.m_3DMaterialAmbientID, 1, &polygon.material.ambient[0]);
glUniform4fv(maResources.m_3DMaterialDiffuseID, 1, &polygon.material.diffuse[0]);
glUniform4fv(maResources.m_3DMaterialSpecularID, 1, &polygon.material.specular[0]);
glUniform4fv(maResources.m_3DMaterialColorID, 1, &polygon.material.materialColor[0]);
glUniform1i(maResources.m_3DMaterialTwoSidesID, polygon.material.twoSidesLighting);
glUniform1f(maResources.m_3DMaterialShininessID, polygon.material.shininess);
CHECK_GL_ERROR();
}
}
for (size_t i = 0; i < verticesNum; i++)
{
//move the circle to the pos, and scale using the xScale and Y scale
Vertices3D *pointList = polygon.verticesList[i];
Normals3D *normalList = polygon.normalsList[i];
PosVecf3 trans = {0.0f, 0.0f, 0.0};
PosVecf3 angle = {0.0f, 0.0f, 0.0f};
PosVecf3 scale = {1.0f, 1.0f, 1.0f};
MoveModelf(trans, angle, scale);
m_Model = m_GlobalScaleMatrix * m_Model;
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
//render to fbo
//fill vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
glBufferData(GL_ARRAY_BUFFER, pointList->size() * sizeof(glm::vec3), &pointList[0][0], GL_STATIC_DRAW);
CHECK_GL_ERROR();
if(!mbPickingMode)
{
//fill normal buffer
glBindBuffer(GL_ARRAY_BUFFER, m_NormalBuffer);
CHECK_GL_ERROR();
glBufferData(GL_ARRAY_BUFFER, normalList->size() * sizeof(glm::vec3), &normalList[0][0], GL_STATIC_DRAW);
CHECK_GL_ERROR();
glUniformMatrix4fv(maResources.m_3DModelID, 1, GL_FALSE, &m_Model[0][0]);
CHECK_GL_ERROR();
glUniformMatrix3fv(maResources.m_3DNormalMatrixID, 1, GL_FALSE, &normalInverseTranspos[0][0]);
CHECK_GL_ERROR();
}
else
{
glm::mat4 aMVP = m_3DProjection * m_3DView * m_Model;
glUniformMatrix4fv(maPickingResources.m_MatrixID, 1, GL_FALSE, &aMVP[0][0]);
glUniform4fv(maPickingResources.m_2DColorID, 1, &polygon.id[0]);
}
CHECK_GL_ERROR();
GLint maVertexID = mbPickingMode ? maPickingResources.m_2DVertexID : maResources.m_3DVertexID;
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(maVertexID);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
CHECK_GL_ERROR();
glVertexAttribPointer(maVertexID, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
CHECK_GL_ERROR();
if(!mbPickingMode)
{
// 2nd attribute buffer : normals
glEnableVertexAttribArray(maResources.m_3DNormalID);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, m_NormalBuffer);
CHECK_GL_ERROR();
glVertexAttribPointer(maResources.m_3DNormalID, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
}
CHECK_GL_ERROR();
glDrawArrays(GL_POLYGON, 0, pointList->size());
CHECK_GL_ERROR();
glDisableVertexAttribArray(maVertexID);
CHECK_GL_ERROR();
if(!mbPickingMode)
glDisableVertexAttribArray(maResources.m_3DNormalID);
CHECK_GL_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, 0);
CHECK_GL_ERROR();
}
glUseProgram(0);
CHECK_GL_ERROR();
}
namespace {
template< typename T >
struct DeletePointer
{
void operator()(T* p)
{
delete p;
}
};
}
void OpenGL3DRenderer::ReleasePolygonShapes()
{
for (size_t i = 0; i < m_Polygon3DInfoList.size(); i++)
{
Polygon3DInfo &polygon = m_Polygon3DInfoList[i];
std::for_each(polygon.verticesList.begin(),
polygon.verticesList.end(), DeletePointer<Vertices3D>());
std::for_each(polygon.normalsList.begin(),
polygon.normalsList.end(), DeletePointer<Normals3D>());
delete polygon.vertices;
delete polygon.normals;
}
m_Polygon3DInfoList.clear();
}
void OpenGL3DRenderer::RenderPolygon3DObject()
{
glDepthMask(GL_FALSE);
CHECK_GL_ERROR();
for (size_t i = 0; i < m_Polygon3DInfoList.size(); i++)
{
Polygon3DInfo &polygon = m_Polygon3DInfoList[i];
if (polygon.lineOnly || (!polygon.fillStyle))
{
//just use the common shader is ok for lines
RenderLine3D(polygon);
CHECK_GL_ERROR();
}
else
{
RenderPolygon3D(polygon);
}
}
glDepthMask(GL_TRUE);
return;
}
void OpenGL3DRenderer::Set3DSenceInfo(sal_uInt32 nColor, bool twoSidesLighting)
{
m_Polygon3DInfo.material.twoSidesLighting = twoSidesLighting;
if (maResources.m_b330Support)
{
m_LightsInfo.ambient = getColorAsVector(nColor);
m_LightsInfo.lightNum = 0;
}
else
{
m_iLightNum = 0;
m_Ambient = getColorAsVector(nColor);;
}
SetLightInfo(true, 0xFFFFFF, glm::vec4(-1.0, -1.0, 1.0, 0.0));
SetLightInfo(true, 0xFFFFFF, glm::vec4(-1.0, 1.0, 1.0, 0.0));
SetLightInfo(true, 0xFFFFFF, glm::vec4(1.0, -1.0, 1.0, 0.0));
SetLightInfo(true, 0xFFFFFF, glm::vec4(1.0, 1.0, 1.0, 0.0));
}
void OpenGL3DRenderer::SetLightInfo(bool lightOn, sal_uInt32 nColor, const glm::vec4& direction)
{
if (lightOn)
{
if (maResources.m_b330Support)
{
if (m_LightsInfo.lightNum >= MAX_LIGHT_NUM)
{
return;
}
m_LightsInfo.light[m_LightsInfo.lightNum].lightColor = getColorAsVector(nColor);
m_LightsInfo.light[m_LightsInfo.lightNum].positionWorldspace = direction;
m_LightsInfo.light[m_LightsInfo.lightNum].lightPower = 0.3f;
m_LightsInfo.lightNum++;
}
else
{
if (m_iLightNum >= MAX_LIGHT_NUM)
{
return;
}
m_LightColor[m_iLightNum] = getColorAsVector(nColor);
m_PositionWorldspace[m_iLightNum] = direction;
m_fLightPower[m_iLightNum] = 0.3f;
m_iLightNum++;
}
}
}
void OpenGL3DRenderer::AddShapePolygon3DObject(sal_uInt32 nColor, bool lineOnly, sal_uInt32 nLineColor,long fillStyle, sal_uInt32 specular, sal_uInt32 nUniqueId)
{
m_Polygon3DInfo.polygonColor = getColorAsVector(nColor);
m_Polygon3DInfo.id = getColorAsVector(nUniqueId);
m_Polygon3DInfo.material.materialColor = m_Polygon3DInfo.polygonColor;//material color seems to be the same for all parts, so we use the polygon color
//line or Polygon
m_Polygon3DInfo.lineOnly = lineOnly;
// if line only, use line color
if (m_Polygon3DInfo.lineOnly)
{
m_Polygon3DInfo.polygonColor = getColorAsVector(nLineColor);
}
//fillStyle
m_Polygon3DInfo.fillStyle= fillStyle;
//material specular;
m_Polygon3DInfo.material.specular = getColorAsVector(specular);
m_Polygon3DInfo.material.diffuse = glm::vec4(1.0, 1.0, 1.0, 1.0);
m_Polygon3DInfo.material.ambient = glm::vec4(0.2, 0.2, 0.2, 1.0);
m_Polygon3DInfo.material.shininess = 1.0f;
}
void OpenGL3DRenderer::EndAddShapePolygon3DObject()
{
m_Polygon3DInfoList.push_back(m_Polygon3DInfo);
m_Polygon3DInfo.normals = NULL;
m_Polygon3DInfo.vertices = NULL;
// TODO: moggi: memory leak???
m_Polygon3DInfo.verticesList.clear();
m_Polygon3DInfo.normalsList.clear();
}
void OpenGL3DRenderer::AddPolygon3DObjectNormalPoint(float x, float y, float z)
{
if (m_Polygon3DInfo.fillStyle)
{
if (!m_Polygon3DInfo.normals)
{
m_Polygon3DInfo.normals = new Normals3D;
}
m_Polygon3DInfo.normals->push_back(glm::vec3(x, y, z));
}
}
void OpenGL3DRenderer::EndAddPolygon3DObjectNormalPoint()
{
m_Polygon3DInfo.normalsList.push_back(m_Polygon3DInfo.normals);
m_Polygon3DInfo.normals = NULL;
}
void OpenGL3DRenderer::AddPolygon3DObjectPoint(float x, float y, float z)
{
if (!m_Polygon3DInfo.vertices)
{
m_Polygon3DInfo.vertices = new Vertices3D;
}
//float actualX = x - (float)m_iWidth / 2;
//float actualY = y - (float)m_iHeight / 2;
float actualX = x;
float actualY = y;
float actualZ = z;
m_Polygon3DInfo.vertices->push_back(glm::vec3(actualX, actualY, actualZ));
}
void OpenGL3DRenderer::EndAddPolygon3DObjectPoint()
{
m_Polygon3DInfo.verticesList.push_back(m_Polygon3DInfo.vertices);
m_Polygon3DInfo.vertices = NULL;
}
void OpenGL3DRenderer::AddShape3DExtrudeObject(bool roundedCorner, sal_uInt32 nColor, sal_uInt32 specular, const glm::mat4& modelMatrix, sal_uInt32 nUniqueId)
{
m_Extrude3DInfo.id = getColorAsVector(nUniqueId);
m_Extrude3DInfo.orgID = nUniqueId;
glm::vec4 tranform = modelMatrix * glm::vec4(0.0, 0.0, 0.0, 1.0);
glm::vec4 DirX = modelMatrix * glm::vec4(1.0, 0.0, 0.0, 0.0);
glm::vec4 DirY = modelMatrix * glm::vec4(0.0, 1.0, 0.0, 0.0);
glm::vec4 DirZ = modelMatrix * glm::vec4(0.0, 0.0, 1.0, 0.0);
m_Extrude3DInfo.xScale = glm::length(DirX);
m_Extrude3DInfo.yScale = glm::length(DirY);
m_Extrude3DInfo.zScale = glm::length(DirZ);
glm::mat4 transformMatrixInverse = glm::inverse(glm::translate(glm::vec3(tranform)));
glm::mat4 scaleMatrixInverse = glm::inverse(glm::scale(glm::vec3(m_Extrude3DInfo.xScale, m_Extrude3DInfo.yScale, m_Extrude3DInfo.zScale)));
m_Extrude3DInfo.rotation = transformMatrixInverse * modelMatrix * scaleMatrixInverse;
//color
m_Extrude3DInfo.extrudeColor = getColorAsVector(nColor);
m_Extrude3DInfo.material.materialColor = m_Extrude3DInfo.extrudeColor;//material color seems to be the same for all parts, so we use the polygon color
//material specular;
m_Extrude3DInfo.material.specular = getColorAsVector(specular);
m_Extrude3DInfo.material.diffuse = glm::vec4(1.0, 1.0, 1.0, 1.0);
m_Extrude3DInfo.material.ambient = glm::vec4(0.2, 0.2, 0.2, 1.0);
m_Extrude3DInfo.material.shininess = 1.0f;
m_Extrude3DInfo.xTransform = tranform.x;
m_Extrude3DInfo.yTransform = tranform.y;
m_Extrude3DInfo.zTransform = tranform.z;
float width = 1.0f;
float height = m_Extrude3DInfo.yScale / m_Extrude3DInfo.xScale;
float radius = height > 0.2f ? 0.2f : height / 4.0f;
float depth = 1 + 2 * radius;
bool NORoundedCube = (radius > (width / 2)) || (radius > (height / 2)) || (radius > (depth / 2));
if (!NORoundedCube && roundedCorner && (m_RoundBarMesh.iMeshSizes == 0))
{
CreateActualRoundedCube(radius, CORNER_DIVION_Y, CORNER_DIVION_Z, width, height, depth);
AddVertexData(m_CubeVertexBuf);
AddNormalData(m_CubeNormalBuf);
AddIndexData(m_CubeElementBuf);
for (int j = 0; j < 5; j++)
{
m_Extrude3DInfo.startIndex[j] = m_RoundBarMesh.iElementStartIndices[j];
m_Extrude3DInfo.size[j] = m_RoundBarMesh.iElementSizes[j];
}
m_Vertices.clear();
m_Normals.clear();
m_Indices.clear();
m_Extrude3DInfo.rounded = true;
}
m_Batchmaterial = m_Extrude3DInfo.material;
}
void OpenGL3DRenderer::EndAddShape3DExtrudeObject()
{
m_Extrude3DList.push_back(m_Extrude3DInfo);
}
void OpenGL3DRenderer::Init3DUniformBlock()
{
if(mbPickingMode)
return;
GLuint a3DLightBlockIndex = glGetUniformBlockIndex(maResources.m_3DProID, "GlobalLights");
GLuint a3DMaterialBlockIndex = glGetUniformBlockIndex(maResources.m_3DProID, "GlobalMaterialParameters");
if ((GL_INVALID_INDEX == a3DLightBlockIndex) || (GL_INVALID_INDEX == a3DMaterialBlockIndex))
{
return;
}
int nUniformBufferAlignSize = 1;
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &nUniformBufferAlignSize);
GLint nBlockDataSizeLight = 0, nBlockDataSizeMertrial = 0;
glGetActiveUniformBlockiv(maResources.m_3DProID, a3DLightBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSizeLight);
glGetActiveUniformBlockiv(maResources.m_3DProID, a3DMaterialBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSizeMertrial);
CHECK_GL_ERROR();
glGenBuffers(1, &m_3DUBOBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, m_3DUBOBuffer);
CHECK_GL_ERROR();
m_3DActualSizeLight = ((nBlockDataSizeLight / nUniformBufferAlignSize) + std::min(nBlockDataSizeLight % nUniformBufferAlignSize, 1)) * nUniformBufferAlignSize;
// cout << "nBlockDataSizeMertrial = " << nBlockDataSizeMertrial << ", nBlockDataSizeLight = " << nBlockDataSizeLight << ", m_3DActualSizeLight = " << m_3DActualSizeLight << endl;
int dataSize = m_3DActualSizeLight + nBlockDataSizeMertrial;
glBufferData(GL_UNIFORM_BUFFER, dataSize, NULL, GL_DYNAMIC_DRAW);
glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_3DUBOBuffer, 0, nBlockDataSizeLight);
CHECK_GL_ERROR();
glUniformBlockBinding(maResources.m_3DProID, a3DLightBlockIndex, 0);
glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_3DUBOBuffer, ((nBlockDataSizeLight / nUniformBufferAlignSize) + std::min(nBlockDataSizeLight % nUniformBufferAlignSize, 1)) * nUniformBufferAlignSize, nBlockDataSizeMertrial);
glUniformBlockBinding(maResources.m_3DProID, a3DMaterialBlockIndex, 1);
//for the light source uniform, we must calc the offset of each element
CHECK_GL_ERROR();
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void OpenGL3DRenderer::InitBatch3DUniformBlock()
{
if(mbPickingMode)
return;
GLuint a3DLightBlockIndex = glGetUniformBlockIndex(maResources.m_3DBatchProID, "GlobalLights");
GLuint a3DMaterialBlockIndex = glGetUniformBlockIndex(maResources.m_3DBatchProID, "GlobalMaterialParameters");
if ((GL_INVALID_INDEX == a3DLightBlockIndex) || (GL_INVALID_INDEX == a3DMaterialBlockIndex))
{
return;
}
int nUniformBufferAlignSize = 1;
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &nUniformBufferAlignSize);
GLint nBlockDataSizeLight = 0, nBlockDataSizeMertrial = 0;
glGetActiveUniformBlockiv(maResources.m_3DBatchProID, a3DLightBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSizeLight);
glGetActiveUniformBlockiv(maResources.m_3DBatchProID, a3DMaterialBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &nBlockDataSizeMertrial);
CHECK_GL_ERROR();
glGenBuffers(1, &m_Batch3DUBOBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, m_Batch3DUBOBuffer);
CHECK_GL_ERROR();
m_Batch3DActualSizeLight = ((nBlockDataSizeLight / nUniformBufferAlignSize) + std::min(nBlockDataSizeLight % nUniformBufferAlignSize, 1)) * nUniformBufferAlignSize;
// cout << "nBlockDataSizeMertrial = " << nBlockDataSizeMertrial << ", nBlockDataSizeLight = " << nBlockDataSizeLight << ", m_3DActualSizeLight = " << m_3DActualSizeLight << endl;
int dataSize = m_Batch3DActualSizeLight + nBlockDataSizeMertrial;
glBufferData(GL_UNIFORM_BUFFER, dataSize, NULL, GL_DYNAMIC_DRAW);
glBindBufferRange(GL_UNIFORM_BUFFER, 2, m_Batch3DUBOBuffer, 0, nBlockDataSizeLight);
CHECK_GL_ERROR();
glUniformBlockBinding(maResources.m_3DBatchProID, a3DLightBlockIndex, 2);
glBindBufferRange(GL_UNIFORM_BUFFER, 3, m_Batch3DUBOBuffer, ((nBlockDataSizeLight / nUniformBufferAlignSize) + std::min(nBlockDataSizeLight % nUniformBufferAlignSize, 1)) * nUniformBufferAlignSize, nBlockDataSizeMertrial);
glUniformBlockBinding(maResources.m_3DBatchProID, a3DMaterialBlockIndex, 3);
//for the light source uniform, we must calc the offset of each element
CHECK_GL_ERROR();
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void OpenGL3DRenderer::UpdateBatch3DUniformBlock()
{
if(mbPickingMode)
return;
CHECK_GL_ERROR();
glBindBuffer(GL_UNIFORM_BUFFER, m_Batch3DUBOBuffer);
CHECK_GL_ERROR();
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLint), &m_LightsInfo.lightNum);
CHECK_GL_ERROR();
//current std140 alignment: 16
glBufferSubData(GL_UNIFORM_BUFFER, 16, sizeof(glm::vec4), &m_LightsInfo.ambient[0]);
CHECK_GL_ERROR();
//current std140 alignment: 16
glBufferSubData(GL_UNIFORM_BUFFER, 32, sizeof(LightSource) * MAX_LIGHT_NUM, &m_LightsInfo.light);
CHECK_GL_ERROR();
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void OpenGL3DRenderer::Update3DUniformBlock()
{
if(mbPickingMode)
return;
CHECK_GL_ERROR();
glBindBuffer(GL_UNIFORM_BUFFER, m_3DUBOBuffer);
CHECK_GL_ERROR();
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(GLint), &m_LightsInfo.lightNum);
CHECK_GL_ERROR();
//current std140 alignment: 16
glBufferSubData(GL_UNIFORM_BUFFER, 16, sizeof(glm::vec4), &m_LightsInfo.ambient[0]);
CHECK_GL_ERROR();
//current std140 alignment: 16
glBufferSubData(GL_UNIFORM_BUFFER, 32, sizeof(LightSource) * MAX_LIGHT_NUM, &m_LightsInfo.light);
CHECK_GL_ERROR();
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
void OpenGL3DRenderer::RenderExtrudeFlatSurface(const Extrude3DInfo& extrude3D, int surIndex)
{
float xyScale = extrude3D.xScale;
PosVecf3 trans = {extrude3D.xTransform,
extrude3D.yTransform,
extrude3D.zTransform};
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
glm::mat4 flatScale = glm::scale(glm::vec3(xyScale, xyScale, xyScale));
m_Model = m_ScrollMoveMatrix * m_GlobalScaleMatrix * aTranslationMatrix * extrude3D.rotation * flatScale;
if(!mbPickingMode)
{
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
glUniformMatrix4fv(maResources.m_3DModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix3fv(maResources.m_3DNormalMatrixID, 1, GL_FALSE, &normalInverseTranspos[0][0]);
}
else
{
glm::mat4 aMVP = m_3DProjection * m_3DView * m_Model;
glUniformMatrix4fv(maPickingResources.m_ModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix4fv(maPickingResources.m_MatrixID, 1, GL_FALSE, &aMVP[0][0]);
glUniform4fv(maPickingResources.m_2DColorID, 1, &extrude3D.id[0]);
}
glDrawElements(GL_TRIANGLES, extrude3D.size[surIndex], GL_UNSIGNED_SHORT, reinterpret_cast<GLvoid*>(extrude3D.startIndex[surIndex]));
}
void OpenGL3DRenderer::RenderExtrudeBottomSurface(const Extrude3DInfo& extrude3D)
{
float xyScale = extrude3D.xScale;
float zScale = extrude3D.zScale;
float actualZTrans = zScale - m_RoundBarMesh.bottomThreshold * xyScale;
PosVecf3 trans = {extrude3D.xTransform,
extrude3D.yTransform,
extrude3D.zTransform};
//PosVecf3 angle = {0.0f, 0.0f, 0.0f};
if (actualZTrans < 0.0f)
{
// the height of rounded corner is higher than the cube than use the org scale matrix
// yScale /= (float)(1 + BOTTOM_THRESHOLD);
zScale /= (float)(m_RoundBarMesh.bottomThreshold);
PosVecf3 scale = {xyScale, xyScale, zScale};
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
glm::mat4 aScaleMatrix = glm::scale(glm::vec3(scale.x, scale.y, scale.z));
m_Model = aTranslationMatrix * extrude3D.rotation * aScaleMatrix;
}
else
{
glm::mat4 topTrans = glm::translate(glm::vec3(0.0, 0.0, actualZTrans));
glm::mat4 topScale = glm::scale(glm::vec3(xyScale, xyScale, xyScale));
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
m_Model = aTranslationMatrix * extrude3D.rotation * topTrans * topScale;
}
m_Model = m_ScrollMoveMatrix * m_GlobalScaleMatrix * m_Model;
if(!mbPickingMode)
{
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
glUniformMatrix4fv(maResources.m_3DModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix3fv(maResources.m_3DNormalMatrixID, 1, GL_FALSE, &normalInverseTranspos[0][0]);
}
else
{
glm::mat4 aMVP = m_3DProjection * m_3DView * m_Model;
glUniformMatrix4fv(maPickingResources.m_ModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix4fv(maPickingResources.m_MatrixID, 1, GL_FALSE, &aMVP[0][0]);
glUniform4fv(maPickingResources.m_2DColorID, 1, &extrude3D.id[0]);
}
glDrawElements(GL_TRIANGLES, extrude3D.size[BOTTOM_SURFACE], GL_UNSIGNED_SHORT, reinterpret_cast<GLvoid*>(extrude3D.startIndex[BOTTOM_SURFACE]));
}
void OpenGL3DRenderer::RenderExtrudeMiddleSurface(const Extrude3DInfo& extrude3D)
{
float xyScale = extrude3D.xScale;
float zScale = extrude3D.zScale;
float actualZScale = zScale - m_RoundBarMesh.bottomThreshold * xyScale;
PosVecf3 trans = {extrude3D.xTransform,
extrude3D.yTransform,
extrude3D.zTransform};
if (actualZScale < 0.0f)
{
// the height of rounded corner is higher than the cube than use the org scale matrix
// yScale /= (float)(1 + BOTTOM_THRESHOLD);
// PosVecf3 scale = {xzScale, yScale, xzScale};
// MoveModelf(trans, angle, scale);
return ;
}
else
{
glm::mat4 scale = glm::scale(glm::vec3(xyScale, xyScale,actualZScale));
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
m_Model = aTranslationMatrix * extrude3D.rotation * scale;
}
if (extrude3D.reverse)
{
glm::mat4 reverseMatrix = glm::translate(glm::vec3(0.0, 0.0, -1.0));
m_Model = m_Model * reverseMatrix;
}
m_Model = m_ScrollMoveMatrix * m_GlobalScaleMatrix * m_Model;
if(!mbPickingMode)
{
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
glUniformMatrix4fv(maResources.m_3DModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix3fv(maResources.m_3DNormalMatrixID, 1, GL_FALSE, &normalInverseTranspos[0][0]);
}
else
{
glm::mat4 aMVP = m_3DProjection * m_3DView * m_Model;
glUniformMatrix4fv(maPickingResources.m_ModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix4fv(maPickingResources.m_MatrixID, 1, GL_FALSE, &aMVP[0][0]);
glUniform4fv(maPickingResources.m_2DColorID, 1, &extrude3D.id[0]);
}
glDrawElements(GL_TRIANGLES, extrude3D.size[MIDDLE_SURFACE], GL_UNSIGNED_SHORT, reinterpret_cast<GLvoid*>(extrude3D.startIndex[MIDDLE_SURFACE]));
}
void OpenGL3DRenderer::RenderExtrudeTopSurface(const Extrude3DInfo& extrude3D)
{
float xyScale = extrude3D.xScale;
float zScale = extrude3D.zScale;
float actualZTrans = zScale - m_RoundBarMesh.bottomThreshold * xyScale;
PosVecf3 trans = {extrude3D.xTransform,
extrude3D.yTransform,
extrude3D.zTransform};
if (actualZTrans < 0.0f)
{
// the height of rounded corner is higher than the cube than use the org scale matrix
//yScale /= (float)(1 + BOTTOM_THRESHOLD);
zScale /= (float)(m_RoundBarMesh.bottomThreshold);
glm::mat4 orgTrans = glm::translate(glm::vec3(0.0, 0.0, -1.0));
glm::mat4 scale = glm::scale(glm::vec3(xyScale, xyScale, zScale));
//MoveModelf(trans, angle, scale);
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
m_Model = aTranslationMatrix * extrude3D.rotation * scale * orgTrans;
}
else
{
// use different matrices for different parts
glm::mat4 orgTrans = glm::translate(glm::vec3(0.0, 0.0, -1.0));
glm::mat4 topTrans = glm::translate(glm::vec3(0.0, 0.0, actualZTrans));
glm::mat4 topScale = glm::scale(glm::vec3(xyScale, xyScale, xyScale));
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
m_Model = aTranslationMatrix * extrude3D.rotation * topTrans * topScale * orgTrans;
}
m_Model = m_ScrollMoveMatrix * m_GlobalScaleMatrix * m_Model;
if(!mbPickingMode)
{
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
glUniformMatrix4fv(maResources.m_3DModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix3fv(maResources.m_3DNormalMatrixID, 1, GL_FALSE, &normalInverseTranspos[0][0]);
}
else
{
glm::mat4 aMVP = m_3DProjection * m_3DView * m_Model;
glUniformMatrix4fv(maPickingResources.m_ModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix4fv(maPickingResources.m_MatrixID, 1, GL_FALSE, &aMVP[0][0]);
glUniform4fv(maPickingResources.m_2DColorID, 1, &extrude3D.id[0]);
}
glDrawElements(GL_TRIANGLES, extrude3D.size[TOP_SURFACE], GL_UNSIGNED_SHORT, reinterpret_cast<GLvoid*>(extrude3D.startIndex[TOP_SURFACE]));
}
void OpenGL3DRenderer::RenderNonRoundedBar(const Extrude3DInfo& extrude3D)
{
float xScale = extrude3D.xScale;
float yScale = extrude3D.yScale;
float zScale = extrude3D.zScale;
glm::mat4 transformMatrix = glm::translate(glm::vec3(extrude3D.xTransform, extrude3D.yTransform, extrude3D.zTransform));
glm::mat4 scaleMatrix = glm::scale(glm::vec3(xScale, yScale, zScale));
m_Model = transformMatrix * extrude3D.rotation * scaleMatrix;
if (extrude3D.reverse)
{
glm::mat4 reverseMatrix = glm::translate(glm::vec3(0.0, 0.0, -1.0));
m_Model = m_Model * reverseMatrix;
}
m_Model = m_ScrollMoveMatrix * m_GlobalScaleMatrix * m_Model;
if(!mbPickingMode)
{
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
glUniformMatrix4fv(maResources.m_3DModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix3fv(maResources.m_3DNormalMatrixID, 1, GL_FALSE, &normalInverseTranspos[0][0]);
}
else
{
glm::mat4 aMVP = m_3DProjection * m_3DView * m_Model;
glUniformMatrix4fv(maPickingResources.m_ModelID, 1, GL_FALSE, &m_Model[0][0]);
glUniformMatrix4fv(maPickingResources.m_MatrixID, 1, GL_FALSE, &aMVP[0][0]);
glUniform4fv(maPickingResources.m_2DColorID, 1, &extrude3D.id[0]);
}
glDrawArrays(GL_TRIANGLES, 0, 36);
}
void OpenGL3DRenderer::RenderExtrudeSurface(const Extrude3DInfo& extrude3D)
{
RenderExtrudeMiddleSurface(extrude3D);
// check reverse flag to decide whether to render the top middle
if (extrude3D.reverse)
{
RenderExtrudeBottomSurface(extrude3D);
RenderExtrudeFlatSurface(extrude3D, FLAT_TOP_SURFACE);
}
else
{
RenderExtrudeTopSurface(extrude3D);
RenderExtrudeFlatSurface(extrude3D, FLAT_BOTTOM_SURFACE);
}
}
void OpenGL3DRenderer::ReleaseExtrude3DShapes()
{
m_Extrude3DList.clear();
}
void OpenGL3DRenderer::RenderExtrude3DObject()
{
CHECK_GL_ERROR();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
CHECK_GL_ERROR();
if(mbPickingMode)
{
glUseProgram(maPickingResources.m_CommonProID);
glUniform1fv(maPickingResources.m_MinCoordXID, 1, &m_fMinCoordX);
glUniform1fv(maPickingResources.m_MaxCoordXID, 1, &m_fMaxCoordX);
}
else
{
glUseProgram(maResources.m_3DProID);
glUniformMatrix4fv(maResources.m_3DViewID, 1, GL_FALSE, &m_3DView[0][0]);
glUniformMatrix4fv(maResources.m_3DProjectionID, 1, GL_FALSE, &m_3DProjection[0][0]);
CHECK_GL_ERROR();
if (maResources.m_b330Support)
{
//update ubo
Update3DUniformBlock();
CHECK_GL_ERROR();
}
else
{
glUniform1fv(maResources.m_3DMinCoordXID, 1, &m_fMinCoordX);
glUniform1fv(maResources.m_3DMaxCoordXID, 1, &m_fMaxCoordX);
glUniform1i(maResources.m_3DUndrawID, m_bUndrawFlag);
//update light information
glUniform4fv(maResources.m_3DLightColorID, m_iLightNum, (GLfloat*)m_LightColor);
glUniform4fv(maResources.m_3DLightPosID, m_iLightNum, (GLfloat*)m_PositionWorldspace);
glUniform1fv(maResources.m_3DLightPowerID, m_iLightNum, m_fLightPower);
glUniform1i(maResources.m_3DLightNumID, m_iLightNum);
glUniform4fv(maResources.m_3DLightAmbientID, 1, &m_Ambient[0]);
CHECK_GL_ERROR();
}
}
size_t extrude3DNum = m_Extrude3DList.size();
for (size_t i = 0; i < extrude3DNum; i++)
{
Extrude3DInfo extrude3DInfo = m_Extrude3DList[i];
GLuint vertexBuf = extrude3DInfo.rounded ? m_CubeVertexBuf : m_BoundBox;
GLuint normalBuf = extrude3DInfo.rounded ? m_CubeNormalBuf : m_BoundBoxNormal;
if(mbPickingMode)
glUniform4fv(maPickingResources.m_2DColorID, 1, &extrude3DInfo.id[0]);
// 1st attribute buffer : vertices
GLint aVertexID = mbPickingMode ? maPickingResources.m_2DVertexID : maResources.m_3DVertexID;
glEnableVertexAttribArray(aVertexID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
glVertexAttribPointer(aVertexID, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
if(!mbPickingMode)
{
// 2nd attribute buffer : normals
glEnableVertexAttribArray(maResources.m_3DNormalID);
glBindBuffer(GL_ARRAY_BUFFER, normalBuf);
glVertexAttribPointer(maResources.m_3DNormalID, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
}
if(!mbPickingMode)
{
if (maResources.m_b330Support)
{
glBindBuffer(GL_UNIFORM_BUFFER, m_3DUBOBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, m_3DActualSizeLight, sizeof(MaterialParameters), &extrude3DInfo.material);
CHECK_GL_ERROR();
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
else
{
//update meterial information
glUniform4fv(maResources.m_3DMaterialAmbientID, 1, &extrude3DInfo.material.ambient[0]);
glUniform4fv(maResources.m_3DMaterialDiffuseID, 1, &extrude3DInfo.material.diffuse[0]);
glUniform4fv(maResources.m_3DMaterialSpecularID, 1, &extrude3DInfo.material.specular[0]);
glUniform4fv(maResources.m_3DMaterialColorID, 1, &extrude3DInfo.material.materialColor[0]);
glUniform1i(maResources.m_3DMaterialTwoSidesID, extrude3DInfo.material.twoSidesLighting);
glUniform1f(maResources.m_3DMaterialShininessID, extrude3DInfo.material.shininess);
}
}
extrude3DInfo.reverse = 0;
if (extrude3DInfo.rounded)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_CubeElementBuf);
RenderExtrudeSurface(extrude3DInfo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
else
{
RenderNonRoundedBar(extrude3DInfo);
}
glDisableVertexAttribArray(aVertexID);
if(!mbPickingMode)
glDisableVertexAttribArray(maResources.m_3DNormalID);
}
glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisable(GL_CULL_FACE);
}
void OpenGL3DRenderer::CreateScreenTextTexture(
const boost::shared_array<sal_uInt8> &bitmapBuf,
::Size maSizePixels, const glm::vec2& vTopLeft,
const glm::vec2& vBottomRight, glm::vec3 vPos, glm::vec4 vScreenTextColor, sal_uInt32 nUniqueId)
{
long bmpWidth = maSizePixels.Width();
long bmpHeight = maSizePixels.Height();
TextInfo aTextInfo;
aTextInfo.id = getColorAsVector(nUniqueId);
aTextInfo.uniqueId = nUniqueId;
aTextInfo.vertex[0] = vBottomRight.x;
aTextInfo.vertex[1] = vBottomRight.y;
aTextInfo.vertex[2] = 0;
aTextInfo.vertex[3] = vBottomRight.x;
aTextInfo.vertex[4] = vTopLeft.y;
aTextInfo.vertex[5] = 0;
aTextInfo.vertex[6] = vTopLeft.x;
aTextInfo.vertex[7] = vTopLeft.y;
aTextInfo.vertex[8] = 0;
aTextInfo.vertex[9] = vTopLeft.x;
aTextInfo.vertex[10] = vBottomRight.y;
aTextInfo.vertex[11] = 0;
aTextInfo.pos = vPos;
aTextInfo.textColor = vScreenTextColor;
CHECK_GL_ERROR();
glGenTextures(1, &aTextInfo.texture);
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, aTextInfo.texture);
CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
CHECK_GL_ERROR();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bmpWidth, bmpHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapBuf.get());
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, 0);
CHECK_GL_ERROR();
m_ScreenTextInfoList.push_back(aTextInfo);
m_ScreenTexturelist.push_back(aTextInfo.texture);
}
void OpenGL3DRenderer::CreateTextTextureSingle(const boost::shared_array<sal_uInt8> &bitmapBuf,
::Size maSizePixels,
glm::vec3 vTopLeft,glm::vec3 vTopRight,
glm::vec3 vBottomRight, glm::vec3 vBottomLeft,
sal_uInt32 nUniqueId)
{
long bmpWidth = maSizePixels.Width();
long bmpHeight = maSizePixels.Height();
TextInfo aTextInfo;
aTextInfo.id = getColorAsVector(nUniqueId);
aTextInfo.vertex[0] = vBottomRight.x;
aTextInfo.vertex[1] = vBottomRight.y;
aTextInfo.vertex[2] = vBottomRight.z;
aTextInfo.vertex[3] = vTopRight.x;
aTextInfo.vertex[4] = vTopRight.y;
aTextInfo.vertex[5] = vTopRight.z;
aTextInfo.vertex[9] = vBottomLeft.x;
aTextInfo.vertex[10] = vBottomLeft.y;
aTextInfo.vertex[11] = vBottomLeft.z;
aTextInfo.vertex[6] = vTopLeft.x;
aTextInfo.vertex[7] = vTopLeft.y;
aTextInfo.vertex[8] = vTopLeft.z;
CHECK_GL_ERROR();
glGenTextures(1, &aTextInfo.texture);
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, aTextInfo.texture);
CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
CHECK_GL_ERROR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
CHECK_GL_ERROR();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bmpWidth, bmpHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapBuf.get());
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, 0);
CHECK_GL_ERROR();
m_TextInfoList.push_back(aTextInfo);
m_Texturelist.push_back(aTextInfo.texture);
}
void OpenGL3DRenderer::CreateTextTextureBatch(const boost::shared_array<sal_uInt8> &bitmapBuf,
::Size maSizePixels,
glm::vec3 vTopLeft,glm::vec3 vTopRight,
glm::vec3 vBottomRight, glm::vec3 vBottomLeft,
sal_uInt32 nUniqueId)
{
long bmpWidth = maSizePixels.Width();
long bmpHeight = maSizePixels.Height();
glm::vec4 id = getColorAsVector(nUniqueId);
m_TextInfoBatch.idList.push_back(id);
m_TextInfoBatch.vertexList.push_back(glm::vec3(vBottomRight.x, vBottomRight.y, vBottomRight.z));
m_TextInfoBatch.vertexList.push_back(glm::vec3(vTopRight.x, vTopRight.y, vTopRight.z));
m_TextInfoBatch.vertexList.push_back(glm::vec3(vTopLeft.x, vTopLeft.y, vTopLeft.z));
m_TextInfoBatch.vertexList.push_back(glm::vec3(vBottomLeft.x, vBottomLeft.y, vBottomLeft.z));
//find the last vector, which size is small than default batch number;
size_t index = 0;
while ((m_TextInfoBatch.texture.size() > 0) &&
(m_TextInfoBatch.texture[index].subTextureNum >= m_TextInfoBatch.batchNum) &&
(index < m_TextInfoBatch.texture.size() - 1))
{
index++;
}
//if the sub texture number of the last texture array reach the largest, create a new textur array
if ((m_TextInfoBatch.texture.size() == 0) ||
(m_TextInfoBatch.texture[index].subTextureNum >= m_TextInfoBatch.batchNum))
{
TextureArrayInfo textureArray;
glGenTextures(1, &textureArray.textureID);
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D_ARRAY, textureArray.textureID);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
CHECK_GL_ERROR();
textureArray.textureArrayWidth = bmpHeight * 8;
textureArray.textureArrayHeight = bmpHeight;
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGB, textureArray.textureArrayWidth, textureArray.textureArrayHeight,
m_TextInfoBatch.batchNum, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
CHECK_GL_ERROR();
if (m_TextInfoBatch.texture.size() > 0)
{
index++;
}
m_TextInfoBatch.texture.push_back(textureArray);
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
}
glBindTexture(GL_TEXTURE_2D_ARRAY, m_TextInfoBatch.texture[index].textureID);
CHECK_GL_ERROR();
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, m_TextInfoBatch.texture[index].subTextureNum, bmpWidth, bmpHeight, 1, GL_RGB, GL_UNSIGNED_BYTE, bitmapBuf.get());
CHECK_GL_ERROR();
//calc texture coordinate
m_TextInfoBatch.textureCoordList.push_back(glm::vec3((float)bmpWidth / (float)m_TextInfoBatch.texture[index].textureArrayWidth,
0,
m_TextInfoBatch.texture[index].subTextureNum));
m_TextInfoBatch.textureCoordList.push_back(glm::vec3((float)bmpWidth / (float)m_TextInfoBatch.texture[index].textureArrayWidth,
(float)bmpHeight/ (float)m_TextInfoBatch.texture[index].textureArrayHeight,
m_TextInfoBatch.texture[index].subTextureNum));
m_TextInfoBatch.textureCoordList.push_back(glm::vec3(0,
(float)bmpHeight/ (float)m_TextInfoBatch.texture[index].textureArrayHeight,
m_TextInfoBatch.texture[index].subTextureNum));
m_TextInfoBatch.textureCoordList.push_back(glm::vec3(0,
0,
m_TextInfoBatch.texture[index].subTextureNum));
m_TextInfoBatch.texture[index].subTextureNum++;
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
}
void OpenGL3DRenderer::CreateTextTexture(const boost::shared_array<sal_uInt8> &bitmapBuf,
::Size maSizePixels,
const glm::vec3& vTopLeft, const glm::vec3& vTopRight,
const glm::vec3& vBottomRight, const glm::vec3& vBottomLeft,
sal_uInt32 nUniqueId)
{
if (maResources.mbTexBatchSupport)
{
CreateTextTextureBatch(bitmapBuf, maSizePixels, vTopLeft, vTopRight, vBottomRight, vBottomLeft, nUniqueId);
}
else
{
CreateTextTextureSingle(bitmapBuf, maSizePixels, vTopLeft, vTopRight, vBottomRight, vBottomLeft, nUniqueId);
}
}
void OpenGL3DRenderer::ReleaseTextShapes()
{
m_TextInfoList.clear();
}
void OpenGL3DRenderer::ReleaseTextTexture()
{
for (size_t i = 0; i < m_Texturelist.size(); i++)
{
glDeleteTextures(1, &m_Texturelist[i]);
}
m_Texturelist.clear();
}
void OpenGL3DRenderer::ReleaseScreenTextShapes()
{
m_ScreenTextInfoList.clear();
}
void OpenGL3DRenderer::ReleaseScreenTextTexture()
{
for (size_t i = 0; i < m_ScreenTexturelist.size(); i++)
{
glDeleteTextures(1, &m_ScreenTexturelist[i]);
}
m_ScreenTexturelist.clear();
}
void OpenGL3DRenderer::RenderScreenTextShape()
{
glUseProgram(maResources.m_ScreenTextProID);
CHECK_GL_ERROR();
for (size_t i = 0; i < m_ScreenTextInfoList.size(); i++)
{
TextInfo textInfo = m_ScreenTextInfoList[i];
//calc the postition and check whether it can be displayed
float xTrans = 0.0f;
float yTrans = 0.0f;
if (textInfo.uniqueId)
{
glm::vec3 worldPos = glm::vec3(m_ScrollMoveMatrix * m_GlobalScaleMatrix * glm::vec4(textInfo.pos, 1));
if ((worldPos.x < m_fMinCoordX) || (worldPos.x > m_fMaxCoordX))
continue;
glm::vec4 pos = m_3DProjection * m_3DView * glm::vec4(worldPos, 1);
xTrans = pos.x / pos.w;
yTrans = pos.y / pos.w;
for (int j = 0; j < 12; j++)
{
if (j % 3 == 0)
{
textInfo.vertex[j] += xTrans;
}
if (j % 3 == 1)
{
textInfo.vertex[j] += yTrans;
}
}
}
glUniform4fv(maResources.m_ScreenTextColorID, 1, &textInfo.textColor[0]);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
CHECK_GL_ERROR();
glBufferData(GL_ARRAY_BUFFER, sizeof(textInfo.vertex), textInfo.vertex, GL_STATIC_DRAW);
CHECK_GL_ERROR();
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(maResources.m_ScreenTextVertexID);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
glVertexAttribPointer(
maResources.m_ScreenTextVertexID,
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
//tex coord
CHECK_GL_ERROR();
glEnableVertexAttribArray(maResources.m_ScreenTextTexCoordID);
glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBuf);
glVertexAttribPointer(
maResources.m_ScreenTextTexCoordID,
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
//texture
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, textInfo.texture);
CHECK_GL_ERROR();
glUniform1i(maResources.m_ScreenTextTexID, 0);
CHECK_GL_ERROR();
//TODO: moggi: get rid fo GL_QUADS
glDrawArrays(GL_QUADS, 0, 4);
CHECK_GL_ERROR();
}
glDisableVertexAttribArray(maResources.m_ScreenTextTexCoordID);
CHECK_GL_ERROR();
glDisableVertexAttribArray(maResources.m_ScreenTextVertexID);
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
CHECK_GL_ERROR();
}
void OpenGL3DRenderer::ReleaseTextShapesBatch()
{
for (size_t i = 0; i < m_TextInfoBatch.texture.size(); i++)
{
m_TextInfoBatch.texture[i].subTextureNum = 0;
}
m_TextInfoBatch.vertexList.clear();
m_TextInfoBatch.textureCoordList.clear();
m_TextInfoBatch.idList.clear();
}
void OpenGL3DRenderer::RenderTextShapeBatch()
{
glm::mat4 aMVP = m_3DProjection * m_3DView * m_GlobalScaleMatrix;
glUseProgram(maResources.m_BatchTextProID);
CHECK_GL_ERROR();
glUniformMatrix4fv(maResources.m_BatchTextMatrixID, 1, GL_FALSE, &aMVP[0][0]);
glEnableVertexAttribArray(maResources.m_BatchTextVertexID);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
glVertexAttribPointer(
maResources.m_BatchTextVertexID,
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
//tex coord
CHECK_GL_ERROR();
glEnableVertexAttribArray(maResources.m_BatchTextTexCoordID);
glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBufBatch);
CHECK_GL_ERROR();
glVertexAttribPointer(
maResources.m_BatchTextTexCoordID,
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
//use texture array to get the vertex
for (size_t i = 0; i < m_TextInfoBatch.texture.size(); i++)
{
int vertexNum = m_TextInfoBatch.texture[i].subTextureNum;
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
CHECK_GL_ERROR();
glBufferData(GL_ARRAY_BUFFER, 4 * vertexNum * sizeof(glm::vec3), &m_TextInfoBatch.vertexList[4 * i * m_TextInfoBatch.batchNum], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBufBatch);
CHECK_GL_ERROR();
glBufferData(GL_ARRAY_BUFFER, 4 * vertexNum * sizeof(glm::vec3), &m_TextInfoBatch.textureCoordList[4 * i * m_TextInfoBatch.batchNum], GL_STATIC_DRAW);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_TextInfoBatch.texture[i].textureID);
CHECK_GL_ERROR();
glUniform1i(maResources.m_BatchTextTexID, 0);
CHECK_GL_ERROR();
//TODO: moggi: get rid fo GL_QUADS
glDrawArrays(GL_QUADS, 0, 4 * vertexNum);
}
glDisableVertexAttribArray(maResources.m_BatchTextVertexID);
CHECK_GL_ERROR();
glDisableVertexAttribArray(maResources.m_BatchTextTexCoordID);
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
CHECK_GL_ERROR();
glUseProgram(0);
}
void OpenGL3DRenderer::RenderTextShape()
{
CHECK_GL_ERROR();
for (size_t i = 0; i < m_TextInfoList.size(); i++)
{
TextInfo &textInfo = m_TextInfoList[i];
PosVecf3 trans = {0, 0, 0};
PosVecf3 angle = {0.0f, 0.0f, 0.0f};
PosVecf3 scale = {1.0, 1.0, 1.0f};
MoveModelf(trans, angle, scale);
m_Model = m_GlobalScaleMatrix * m_Model;
glm::mat4 aMVP = m_3DProjection * m_3DView * m_Model;
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
CHECK_GL_ERROR();
glBufferData(GL_ARRAY_BUFFER, sizeof(textInfo.vertex), textInfo.vertex, GL_STATIC_DRAW);
CHECK_GL_ERROR();
glUseProgram(maResources.m_TextProID);
CHECK_GL_ERROR();
glUniformMatrix4fv(maResources.m_TextMatrixID, 1, GL_FALSE, &aMVP[0][0]);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(maResources.m_TextVertexID);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
glVertexAttribPointer(
maResources.m_TextVertexID,
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
//tex coord
CHECK_GL_ERROR();
glEnableVertexAttribArray(maResources.m_TextTexCoordID);
glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBuf);
glVertexAttribPointer(
maResources.m_TextTexCoordID,
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
//texture
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, textInfo.texture);
CHECK_GL_ERROR();
glUniform1i(maResources.m_TextTexID, 0);
CHECK_GL_ERROR();
//TODO: moggi: get rid fo GL_QUADS
glDrawArrays(GL_QUADS, 0, 4);
CHECK_GL_ERROR();
glDisableVertexAttribArray(maResources.m_TextTexCoordID);
CHECK_GL_ERROR();
glDisableVertexAttribArray(maResources.m_TextVertexID);
CHECK_GL_ERROR();
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
}
CHECK_GL_ERROR();
}
void OpenGL3DRenderer::CreateSceneBoxView()
{
m_CameraInfo.cameraPos = glm::vec3(m_GlobalScaleMatrix * glm::vec4(m_CameraInfo.cameraPos, 1.0));
m_CameraInfo.cameraOrg = glm::vec3(m_GlobalScaleMatrix * glm::vec4(m_CameraInfo.cameraOrg, 1.0));
m_3DView = glm::lookAt(m_CameraInfo.cameraPos,
m_CameraInfo.cameraOrg,
m_CameraInfo.cameraUp);
}
void OpenGL3DRenderer::ClearBuffer()
{
CHECK_GL_ERROR();
glDisable(GL_DEPTH_TEST);
CHECK_GL_ERROR();
glClearDepth(1.0f);
CHECK_GL_ERROR();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
CHECK_GL_ERROR();
/*
* TODO: moggi: use a shader!!!
glBegin (GL_QUADS);
glColor3f (0.3f, 0.3f, 0.3f);
glVertex3f (-1.0f, -1.0f, -1.0f);
glVertex3f (1.0f, -1.0f, -1.0f);
glColor3f (0.0f, 0.0f, 0.0f);
glVertex3f (1.0f, 1.0f, -1.0f);
glVertex3f (-1.0f, 1.0f, -1.0f);
glEnd ();
*/
glEnable(GL_DEPTH_TEST);
CHECK_GL_ERROR();
}
void OpenGL3DRenderer::ProcessUnrenderedShape(bool bNewScene)
{
glViewport(0, 0, m_iWidth, m_iHeight);
CHECK_GL_ERROR();
ClearBuffer();
CHECK_GL_ERROR();
CreateSceneBoxView();
CHECK_GL_ERROR();
CalcScrollMoveMatrix(bNewScene);
//Polygon
CHECK_GL_ERROR();
RenderPolygon3DObject();
//Shape3DExtrudeObject
if(mbPickingMode)
RenderExtrude3DObject();
else
{
if (maResources.m_b330Support)
{
RenderBatchBars(bNewScene);
}
else
{
RenderExtrude3DObject();
}
}
//render text
if (maResources.mbTexBatchSupport)
{
RenderTextShapeBatch();
}
else
{
RenderTextShape();
}
// render screen text
RenderScreenTextShape();
#if DEBUG_FBO
OUString aFileName = OUString("D://shaderout_") + OUString::number(m_iWidth) + "_" + OUString::number(m_iHeight) + ".png";
OpenGLHelper::renderToFile(m_iWidth, m_iHeight, aFileName);
#endif
}
void OpenGL3DRenderer::MoveModelf(const PosVecf3& trans, const PosVecf3& angle, const PosVecf3& scale)
{
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
glm::mat4 aScaleMatrix = glm::scale(glm::vec3(scale.x, scale.y, scale.z));
glm::mat4 aRotationMatrix = glm::eulerAngleYXZ(angle.y, angle.x, angle.z);
m_Model = aTranslationMatrix * aRotationMatrix * aScaleMatrix;
}
void OpenGL3DRenderer::SetPickingMode(bool bPickingMode)
{
mbPickingMode = bPickingMode;
if(mbPickingMode)
{
glBindFramebuffer(GL_FRAMEBUFFER, mnPickingFbo);
glDisable(GL_MULTISAMPLE);
}
else
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glEnable(GL_MULTISAMPLE);
}
}
sal_uInt32 OpenGL3DRenderer::GetPixelColorFromPoint(long nX, long nY)
{
static sal_uInt32 nId = 0;
OUString aFileName = OUString("/home/moggi/work/picking_") + OUString::number(nId++) + ".png";
OpenGLHelper::renderToFile(m_iWidth, m_iHeight, aFileName);
boost::scoped_array<sal_uInt8> buf(new sal_uInt8[4]);
glReadPixels(nX, m_iHeight-nY, 1, 1, GL_BGRA, GL_UNSIGNED_BYTE, buf.get());
Color aColor(255-buf[3], buf[2], buf[1], buf[0]);
return aColor.GetColor();
}
void OpenGL3DRenderer::ReleaseBatchBarInfo()
{
for (int i = 0; i < 3; i++)
{
m_BarSurface[i].modelMatrixList.clear();
m_BarSurface[i].normalMatrixList.clear();
m_BarSurface[i].colorList.clear();
m_BarSurface[i].mapId2Color.clear();
}
}
void OpenGL3DRenderer::ReleaseShapes()
{
ReleasePolygonShapes();
ReleaseExtrude3DShapes();
ReleaseTextShapes();
//ReleaseScreenTextShapes();
ReleaseBatchBarInfo();
ReleaseTextShapesBatch();
}
void OpenGL3DRenderer::GetBatchMiddleInfo(const Extrude3DInfo &extrude3D)
{
float xyScale = extrude3D.xScale;
float zScale = extrude3D.zScale;
float actualZScale = zScale - m_RoundBarMesh.bottomThreshold * xyScale;
PosVecf3 trans = {extrude3D.xTransform,
extrude3D.yTransform,
extrude3D.zTransform};
if (actualZScale < 0.0f)
{
return ;
}
else
{
glm::mat4 scale = glm::scale(glm::vec3(xyScale, xyScale,actualZScale));
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
m_Model = aTranslationMatrix * extrude3D.rotation * scale;
}
m_Model = m_GlobalScaleMatrix * m_Model;
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
m_BarSurface[MIDDLE_SURFACE].modelMatrixList.push_back(m_Model);
m_BarSurface[MIDDLE_SURFACE].normalMatrixList.push_back(normalInverseTranspos);
m_BarSurface[MIDDLE_SURFACE].colorList.push_back(extrude3D.material.materialColor);
m_BarSurface[MIDDLE_SURFACE].mapId2Color[extrude3D.orgID] = m_BarSurface[MIDDLE_SURFACE].colorList.size() - 1;
}
void OpenGL3DRenderer::GetBatchTopAndFlatInfo(const Extrude3DInfo &extrude3D)
{
float xyScale = extrude3D.xScale;
float zScale = extrude3D.zScale;
float actualZTrans = zScale - m_RoundBarMesh.bottomThreshold * xyScale;
PosVecf3 trans = {extrude3D.xTransform,
extrude3D.yTransform,
extrude3D.zTransform};
glm::mat4 orgTrans = glm::translate(glm::vec3(0.0, 0.0, -1.0));
if (actualZTrans < 0.0f)
{
// the height of rounded corner is higher than the cube than use the org scale matrix
//yScale /= (float)(1 + BOTTOM_THRESHOLD);
zScale /= (float)(m_RoundBarMesh.bottomThreshold);
glm::mat4 scale = glm::scale(glm::vec3(xyScale, xyScale, zScale));
//MoveModelf(trans, angle, scale);
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
m_Model = aTranslationMatrix * extrude3D.rotation * scale * orgTrans;
}
else
{
// use different matrices for different parts
glm::mat4 topTrans = glm::translate(glm::vec3(0.0, 0.0, actualZTrans));
glm::mat4 topScale = glm::scale(glm::vec3(xyScale, xyScale, xyScale));
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
m_Model = aTranslationMatrix * extrude3D.rotation * topTrans * topScale * orgTrans;
}
m_Model = m_GlobalScaleMatrix * m_Model;
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
m_BarSurface[TOP_SURFACE].modelMatrixList.push_back(m_Model);
m_BarSurface[TOP_SURFACE].normalMatrixList.push_back(normalInverseTranspos);
m_BarSurface[TOP_SURFACE].colorList.push_back(extrude3D.material.materialColor);
m_BarSurface[TOP_SURFACE].mapId2Color[extrude3D.orgID] = m_BarSurface[TOP_SURFACE].colorList.size() - 1;
glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
glm::mat4 flatScale = glm::scale(glm::vec3(xyScale, xyScale, xyScale));
m_Model = aTranslationMatrix * extrude3D.rotation * flatScale;
m_Model = m_GlobalScaleMatrix * m_Model;
normalMatrix = glm::mat3(m_Model);
normalInverseTranspos = glm::inverseTranspose(normalMatrix);
m_BarSurface[FLAT_BOTTOM_SURFACE].modelMatrixList.push_back(m_Model);
m_BarSurface[FLAT_BOTTOM_SURFACE].normalMatrixList.push_back(normalInverseTranspos);
m_BarSurface[FLAT_BOTTOM_SURFACE].colorList.push_back(extrude3D.material.materialColor);
m_BarSurface[FLAT_BOTTOM_SURFACE].mapId2Color[extrude3D.orgID] = m_BarSurface[FLAT_BOTTOM_SURFACE].colorList.size() - 1;
}
void OpenGL3DRenderer::GetBatchBarsInfo()
{
for (size_t i = 0; i < m_Extrude3DList.size(); i++)
{
Extrude3DInfo &extrude3DInfo = m_Extrude3DList[i];
if (m_Extrude3DInfo.rounded)
{
GetBatchTopAndFlatInfo(extrude3DInfo);
GetBatchMiddleInfo(extrude3DInfo);
}
else
{
glm::mat4 transformMatrix = glm::translate(glm::vec3(extrude3DInfo.xTransform, extrude3DInfo.yTransform, extrude3DInfo.zTransform));
glm::mat4 scaleMatrix = glm::scale(glm::vec3(extrude3DInfo.xScale, extrude3DInfo.yScale, extrude3DInfo.zScale));
m_Model = transformMatrix * extrude3DInfo.rotation * scaleMatrix;
m_Model = m_GlobalScaleMatrix * m_Model;
glm::mat3 normalMatrix(m_Model);
glm::mat3 normalInverseTranspos = glm::inverseTranspose(normalMatrix);
m_BarSurface[0].modelMatrixList.push_back(m_Model);
m_BarSurface[0].normalMatrixList.push_back(normalInverseTranspos);
m_BarSurface[0].colorList.push_back(extrude3DInfo.material.materialColor);
m_BarSurface[0].mapId2Color[extrude3DInfo.orgID] = m_BarSurface[0].colorList.size() - 1;
}
}
}
void OpenGL3DRenderer::SetHighLightBar(BatchBarInfo &barInfo)
{
std::map<sal_uInt32, unsigned int> ::iterator it = barInfo.mapId2Color.find(m_uiSelectID);
if (it != barInfo.mapId2Color.end())
{
unsigned int idx = it->second;
barInfo.selectBarColor = barInfo.colorList[idx];
barInfo.colorList[idx] = glm::vec4(1.0, 1.0, 1.0, 1.0);
}
}
void OpenGL3DRenderer::DisableHighLightBar(BatchBarInfo &barInfo)
{
std::map<sal_uInt32, unsigned int> ::iterator it = barInfo.mapId2Color.find(m_uiSelectID);
if (it != barInfo.mapId2Color.end())
{
unsigned int idx = it->second;
barInfo.colorList[idx] = barInfo.selectBarColor;
}
}
void OpenGL3DRenderer::StartClick(sal_uInt32 &selectID)
{
m_bHighLighting = true;
m_uiSelectID = selectID;
for (unsigned int i = 0; i < 3; i++)
{
SetHighLightBar(m_BarSurface[i]);
}
}
void OpenGL3DRenderer::EndClick()
{
m_bHighLighting = false;
for (unsigned int i = 0; i < 3; i++)
{
DisableHighLightBar(m_BarSurface[i]);
}
}
void OpenGL3DRenderer::SetScroll()
{
maResources.m_bScrollFlag = true;
}
void OpenGL3DRenderer::SetScrollSpeed(float scrollSpeed)
{
m_fScrollSpeed = scrollSpeed;
}
void OpenGL3DRenderer::SetScrollDistance(float scrollDistance)
{
m_fScrollDistance = scrollDistance;
}
void OpenGL3DRenderer::SetSceneEdge(float minCoordX, float maxCoordX)
{
m_fMinCoordX = minCoordX * 0.01;
m_fMaxCoordX = maxCoordX * 0.01;
}
void OpenGL3DRenderer::CalcScrollMoveMatrix(bool bNewScene)
{
if (!maResources.m_bScrollFlag)
return;
if (bNewScene)
m_fCurDistance = -m_fScrollSpeed;
m_fCurDistance += m_fCurDistance >= m_fScrollDistance ? 0.0f : m_fScrollSpeed;
m_ScrollMoveMatrix = glm::translate(glm::vec3(-m_fCurDistance * 0.01, 0.0f, 0.0f));
m_bUndrawFlag = m_fCurDistance >= m_fScrollDistance ? true : false;
}
glm::mat4 OpenGL3DRenderer::GetProjectionMatrix()
{
return m_3DProjection;
}
glm::mat4 OpenGL3DRenderer::GetViewMatrix()
{
return m_3DView;
}
glm::mat4 OpenGL3DRenderer::GetGlobalScaleMatrix()
{
return m_GlobalScaleMatrix;
}
void OpenGL3DRenderer::RenderBatchBars(bool bNewScene)
{
if(bNewScene)
{
GetBatchBarsInfo();
if (m_bHighLighting)
{
for (unsigned int i = 0; i < 3; i++)
{
SetHighLightBar(m_BarSurface[i]);
}
}
}
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glPolygonOffset(0.0f, 0.0f);
glUseProgram(maResources.m_3DBatchProID);
UpdateBatch3DUniformBlock();
glBindBuffer(GL_UNIFORM_BUFFER, m_Batch3DUBOBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, m_Batch3DActualSizeLight, sizeof(MaterialParameters), &m_Batchmaterial);
CHECK_GL_ERROR();
glBindBuffer(GL_UNIFORM_BUFFER, 0);
if (maResources.m_bScrollFlag)
{
glUniform1fv(maResources.m_3DBatchMinCoordXID, 1, &m_fMinCoordX);
glUniform1fv(maResources.m_3DBatchMaxCoordXID, 1, &m_fMaxCoordX);
glUniform1i(maResources.m_3DBatchUndrawID, m_bUndrawFlag);
glUniformMatrix4fv(maResources.m_3DBatchTransMatrixID, 1, GL_FALSE, &m_ScrollMoveMatrix[0][0]);
}
glUniformMatrix4fv(maResources.m_3DBatchViewID, 1, GL_FALSE, &m_3DView[0][0]);
glUniformMatrix4fv(maResources.m_3DBatchProjectionID, 1, GL_FALSE, &m_3DProjection[0][0]);
CHECK_GL_ERROR();
GLuint vertexBuf = m_Extrude3DInfo.rounded ? m_CubeVertexBuf : m_BoundBox;
GLuint normalBuf = m_Extrude3DInfo.rounded ? m_CubeNormalBuf : m_BoundBoxNormal;
//vertex
glEnableVertexAttribArray(maResources.m_3DBatchVertexID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuf);
glVertexAttribPointer(maResources.m_3DBatchVertexID, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
//normal
glEnableVertexAttribArray(maResources.m_3DBatchNormalID);
glBindBuffer(GL_ARRAY_BUFFER, normalBuf);
glVertexAttribPointer(maResources.m_3DBatchNormalID, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
for (unsigned int i = 0; i < 4 ; i++)
{
glEnableVertexAttribArray(maResources.m_3DBatchModelID + i);
glBindBuffer(GL_ARRAY_BUFFER, m_BatchModelMatrixBuf);
glVertexAttribPointer(maResources.m_3DBatchModelID + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), reinterpret_cast<GLvoid*>(sizeof(GLfloat) * i * 4));
glVertexAttribDivisor(maResources.m_3DBatchModelID + i, 1);
}
for (unsigned int i = 0; i < 3 ; i++)
{
glEnableVertexAttribArray(maResources.m_3DBatchNormalMatrixID + i);
glBindBuffer(GL_ARRAY_BUFFER, m_BatchNormalMatrixBuf);
glVertexAttribPointer(maResources.m_3DBatchNormalMatrixID + i, 3, GL_FLOAT, GL_FALSE, sizeof(glm::mat3), reinterpret_cast<GLvoid*>(sizeof(GLfloat) * i * 3));
glVertexAttribDivisor(maResources.m_3DBatchNormalMatrixID + i, 1);
}
glEnableVertexAttribArray(maResources.m_3DBatchColorID);
glBindBuffer(GL_ARRAY_BUFFER, m_BatchColorBuf);
glVertexAttribPointer(maResources.m_3DBatchColorID , 4, GL_FLOAT, GL_FALSE, sizeof(glm::vec4), 0);
glVertexAttribDivisor(maResources.m_3DBatchColorID, 1);
if (m_Extrude3DInfo.rounded)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_CubeElementBuf);
for (int i = 0; i < 2; i++)
{
glBindBuffer(GL_ARRAY_BUFFER, m_BatchModelMatrixBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * m_BarSurface[i].modelMatrixList.size(), &m_BarSurface[i].modelMatrixList[0][0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_BatchNormalMatrixBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat3) * m_BarSurface[i].normalMatrixList.size(), &m_BarSurface[i].normalMatrixList[0][0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_BatchColorBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * m_BarSurface[i].colorList.size(), &m_BarSurface[i].colorList[0], GL_DYNAMIC_DRAW);
glDrawElementsInstancedBaseVertex(GL_TRIANGLES,
m_Extrude3DInfo.size[i],
GL_UNSIGNED_SHORT,
reinterpret_cast<GLvoid*>(m_Extrude3DInfo.startIndex[i]),
m_BarSurface[i].modelMatrixList.size(),
0);
}
}
else
{
glBindBuffer(GL_ARRAY_BUFFER, m_BatchModelMatrixBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * m_BarSurface[0].modelMatrixList.size(), &m_BarSurface[0].modelMatrixList[0][0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_BatchNormalMatrixBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat3) * m_BarSurface[0].normalMatrixList.size(), &m_BarSurface[0].normalMatrixList[0][0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, m_BatchColorBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4) * m_BarSurface[0].colorList.size(), &m_BarSurface[0].colorList[0], GL_DYNAMIC_DRAW);
glDrawArraysInstanced(GL_TRIANGLES, 0, 36, m_BarSurface[0].modelMatrixList.size());
}
glDisableVertexAttribArray(maResources.m_3DBatchVertexID);
glDisableVertexAttribArray(maResources.m_3DBatchNormalID);
glDisableVertexAttribArray(maResources.m_3DBatchColorID);
glVertexAttribDivisor(maResources.m_3DBatchColorID, 0);
for (unsigned int i = 0; i < 4 ; i++)
{
glDisableVertexAttribArray(maResources.m_3DBatchModelID + i);
glVertexAttribDivisor(maResources.m_3DBatchModelID + i, 0);
}
for (unsigned int i = 0; i < 3 ; i++)
{
glDisableVertexAttribArray(maResources.m_3DBatchNormalMatrixID + i);
glVertexAttribDivisor(maResources.m_3DBatchNormalMatrixID + i, 0);
}
glUseProgram(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisable(GL_CULL_FACE);
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */