forked from amazingfate/loongoffice
2581 lines
100 KiB
C++
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: */
|