/* -*- 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 #include "GL3DRenderer.hxx" #include #include #include #include #include #include "glm/gtc/matrix_inverse.hpp" #include #include #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, 0.96f, 0.0f, 0.96f, 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_matDiff(glm::mat4(0.0)) { 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(); #if !defined(ANDROID) && !defined(IOS) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif // 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 & VertexToOutIndex, unsigned short & result ) { std::map::iterator it = VertexToOutIndex.find(packed); if ( it == VertexToOutIndex.end() ) { return false; } else { result = it->second; return true; } } void OpenGL3DRenderer::SetVertex(PackedVertex &packed, std::map &VertexToOutIndex, std::vector &vertex, std::vector &normal, std::vector &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 vertices; std::vector normals; GenerateRoundCornerBar(vertices, normals, fRadius, iSubDivY, iSubDivZ, width, height, depth); std::map VertexToOutIndex; glm::vec3 actualVerteices[3]; glm::vec3 actualNormals[3]; std::vector 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 &vertices, std::vector &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, reinterpret_cast(m_LightColor)); glUniform4fv(maResources.m_3DLightPosID, m_iLightNum, reinterpret_cast(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()); std::for_each(polygon.normalsList.begin(), polygon.normalsList.end(), DeletePointer()); 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(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(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(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(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, reinterpret_cast(m_LightColor)); glUniform4fv(maResources.m_3DLightPosID, m_iLightNum, reinterpret_cast(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 &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 &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 &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 &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() { if (mbPickingMode) return; glUseProgram(maResources.m_ScreenTextProID); CHECK_GL_ERROR(); for (size_t i = 0; i < m_ScreenTextInfoList.size(); i++) { TextInfo textInfo = m_ScreenTextInfoList[i]; //calc the position and check whether it can be displayed 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); const float xTrans = pos.x / pos.w; const float 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); m_3DView = m_3DView + m_matDiff; } void OpenGL3DRenderer::AddMatrixDiff(const glm::mat4& aMat) { m_matDiff = m_matDiff + aMat; } void OpenGL3DRenderer::ResetMatrixDiff() { m_matDiff = glm::mat4(0.0); } void OpenGL3DRenderer::ClearBuffer() { CHECK_GL_ERROR(); glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR(); #if defined(IOS) || defined(ANDROID) glClearDepthf(1.0f); #else glClearDepth(1.0f); #endif 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 = "/home/moggi/work/picking_" + OUString::number(nId++) + ".png"; OpenGLHelper::renderToFile(m_iWidth, m_iHeight, aFileName); boost::scoped_array 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 ::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 ::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::GetDiffOfTwoCameras(const glm::vec3& rBeginPos, const glm::vec3& rEndPos, const glm::vec3& rBeginDirection, const glm::vec3& rEndDirection) { glm::mat4 aBegin = glm::lookAt(glm::vec3(m_GlobalScaleMatrix * glm::vec4(rBeginPos, 1.0)), glm::vec3(m_GlobalScaleMatrix * glm::vec4(rBeginDirection, 1.0)), glm::vec3(0, 0, 1)); glm::mat4 aEnd = glm::lookAt(glm::vec3(m_GlobalScaleMatrix * glm::vec4(rEndPos, 1.0)), glm::vec3(m_GlobalScaleMatrix * glm::vec4(rEndDirection, 1.0)), glm::vec3(0, 0, 1)); return aEnd - aBegin; } glm::mat4 OpenGL3DRenderer::GetDiffOfTwoCameras(const glm::vec3& rEndPos, const glm::vec3& rEndDirection) { glm::mat4 aEnd = glm::lookAt(glm::vec3(m_GlobalScaleMatrix * glm::vec4(rEndPos, 1.0)), glm::vec3(m_GlobalScaleMatrix * glm::vec4(rEndDirection, 1.0)),glm::vec3(0, 0, 1)); return aEnd - m_3DView; } 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 (m_BarSurface[0].modelMatrixList.empty()) return; 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(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(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(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: */