diff --git a/src/viewer/simpleViewer.cpp b/src/viewer/simpleViewer.cpp index 7c92177..7600f96 100644 --- a/src/viewer/simpleViewer.cpp +++ b/src/viewer/simpleViewer.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -54,6 +55,8 @@ namespace const int numVerticesSphere = numColSphere * numRowSphere + 2; const int numTriSphere = numColSphere*(numRowSphere-1)*2 + 2*numColSphere; + const GLuint particleLimit = 1024; + int m_lDirectionLocation; int m_normalMatrixLoc; @@ -221,19 +224,19 @@ void Viewer::draw() // Adjust sun position - float rotAngle = std::fmod(angle_mult * 25 * frame, 360); - sunRotate.rotate(rotAngle, 0, 0, 1); + float rotAngle = std::fmod(angle_mult * 25 * frame, 360); + sunRotate.rotate(rotAngle, 0, 0, 1); //sunRotate.rotate(15, 1, 0, 0); - m_program->setUniformValue(m_lDirLoc, (QMatrix4x4(modelViewMatrix.normalMatrix())*sunRotate * sun)); + m_program->setUniformValue(m_lDirLoc, (QMatrix4x4(modelViewMatrix.normalMatrix())*sunRotate * sun)); - objShader->bind(); + objShader->bind(); - objShader->setUniformValue(o_u_prjMatrix, projectionMatrix); - objShader->setUniformValue(o_u_lDir, (QMatrix4x4(modelViewMatrix.normalMatrix())*sunRotate * sun)); + objShader->setUniformValue(o_u_prjMatrix, projectionMatrix); + objShader->setUniformValue(o_u_lDir, (QMatrix4x4(modelViewMatrix.normalMatrix())*sunRotate * sun)); - m_program->bind(); - selection->transform.setToIdentity(); + m_program->bind(); + selection->transform.setToIdentity(); selection->transform.rotate(rotAngle, 0, 1, 0); // Traverse the Scene in order to draw its components @@ -241,19 +244,61 @@ void Viewer::draw() modelStack.push(modelViewMatrix); root.accept(*this); - drawTool(); - - drawUi(); + drawParticles(); + drawUi(); sunRotate.setToIdentity(); //float rotAngle = (frame * angle_mult) % 360; } +void Viewer::drawTool() { + objShader->bind(); + + // Get projection and camera transformations + QMatrix4x4 modelViewMatrix; + + //camera()->getModelViewMatrix(modelViewMatrix); + + QMatrix4x4 toolboxPos = QMatrix4x4(); + float swingMult = 1; + //scale.translate(QVector3D(0,1.5,0)); + toolboxPos.translate(0.6, -0.25, -1.6); + toolboxPos.rotate(-100, 0, 1, 0); + if(swing.active) { + swingMult = 0.5 + 0.5 * cos(fmin(swing.length, frame - swing.startFrame) * 2 * M_PI / swing.length); + if(frame - swing.startFrame > swing.length) { + swing.active = false; + } + } + toolboxPos.rotate(swingMult * -65, 0, 0, 1); + toolboxPos.scale(0.06); + + objShader->setUniformValue(o_u_mvMatrix, modelViewMatrix * toolboxPos); + objShader->setUniformValue(o_u_nmMatrix, modelViewMatrix.normalMatrix()); + + // Draw the meshes + for (unsigned int i=0; i<_meshesGL.size(); ++i) + { + // Set its material properties + objShader->setUniformValue(o_u_kd, _meshesGL[i].diffuse); + objShader->setUniformValue(o_u_ks, _meshesGL[i].specular); + objShader->setUniformValue(o_u_kn, _meshesGL[i].specularExponent); + objShader->setUniformValue(o_u_ka, _meshesGL[i].alpha); + + // Draw the mesh + glBindVertexArray(_meshesGL[i].vao); + glDrawArrays(GL_TRIANGLES, 0, _meshesGL[i].numVertices); + } +} + void Viewer::drawUi(){ - m_program->bind(); - glCullFace(GL_BACK); glClear(GL_DEPTH_BUFFER_BIT); // make ui always on top + drawTool(); + + m_program->bind(); + glCullFace(GL_BACK); + QMatrix4x4 projectionMatrix; QMatrix4x4 uiViewMatrix; @@ -284,6 +329,35 @@ void Viewer::drawUi(){ } +void Viewer::drawParticles(){ + m_program->bind(); + + QMatrix4x4 projectionMatrix; + QMatrix4x4 modelViewMatrix; + camera()->getProjectionMatrix(projectionMatrix); + camera()->getModelViewMatrix(modelViewMatrix); + + + glBindVertexArray(m_VAOs[VAO_Particle]); + glBindBuffer(GL_ARRAY_BUFFER, VBO_Particle); + glBindBuffer(GL_ARRAY_BUFFER, VBO_Particle_Positions); + glBindBuffer(GL_ARRAY_BUFFER, VBO_Particle_Colors); + + + + glActiveTexture(GL_TEXTURE0); + TexturePrograms[1]->bind(); + + m_program->setUniformValue(m_isSkyLoc, true); + m_program->setUniformValue(m_mvMatrixLocation, modelViewMatrix); + m_program->setUniformValue(m_normalMatrixLoc, modelViewMatrix.normalMatrix()); + m_program->setUniformValue(m_colorLocation, QColor(255, 255, 255, 255)); + m_program->setUniformValue(m_drawTextLoc, false); + m_program->setUniformValue(m_isLightLoc, true); + + glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, particleLimit); +} + void Viewer::mouseMoveEvent(QMouseEvent* e) { //cout << "Viewer::mouseMoveEvent(QMouseEvent* e)" << endl; // Normal QGLViewer behavior. @@ -835,32 +909,8 @@ void Viewer::initGeometries() glVertexAttribPointer(s_vUvLocation, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offsetUV)); glEnableVertexAttribArray(s_vUvLocation); - /*GLsizeiptr offsetVertices = 0; - GLsizeiptr offsetNormals = sizeof(verticesCube); - GLsizeiptr offsetUV = offsetNormals + sizeof(normals); - GLsizeiptr dataSize = offsetUV + sizeof(uvs); - - - glBindVertexArray(m_VAOs[VAO_Cube]); - glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[VBO_Cube]); - glBufferData(GL_ARRAY_BUFFER, dataSize, NULL, GL_STATIC_DRAW); - - glBufferSubData(GL_ARRAY_BUFFER, offsetVertices, sizeof(verticesCube), verticesCube); - glBufferSubData(GL_ARRAY_BUFFER, offsetNormals, sizeof(normals), normals); - glBufferSubData(GL_ARRAY_BUFFER, offsetUV, sizeof(uvs), uvs); - - glVertexAttribPointer(m_vPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(m_vPositionLocation); - - glVertexAttribPointer(m_vNormalLocation, 3, GL_FLOAT, GL_TRUE, 0, BUFFER_OFFSET(sizeof(offsetNormals))); - glEnableVertexAttribArray(m_vNormalLocation); - - glVertexAttribPointer(s_vUvLocation, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(offsetUV))); - glEnableVertexAttribArray(s_vUvLocation);//*/ - // Fill Sphere VBO - GLsizeiptr offsetSphereV = 0; GLsizeiptr offsetSphereN = offsetSphereV + sizeof(sphereVertices); GLsizeiptr sphereDataSize = offsetSphereN + sizeof(sphereNormals); @@ -882,6 +932,69 @@ void Viewer::initGeometries() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Buffers[EBO_Sphere]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(sphereIndices), sphereIndices, GL_STATIC_DRAW); + + + // Fill Particle VBO + //============================================================== + // CODE RÉFÉRENCÉ + // http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/particles-instancing/ + //============================================================== + GLfloat verticesParticle[] = { + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + -0.5f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.0f, + }; + + GLfloat particlePositions[particleLimit][4] = {}; // x, y, z and time, for shader's lifetime calculation + GLubyte particleColors[particleLimit][4] = {}; + + srand((unsigned int) time(NULL)); + for(int i = 0; i < particleLimit; i++){ + double r = rand() / (RAND_MAX); + double g = rand() / (RAND_MAX); + double b = rand() / (RAND_MAX); + particlePositions[i][0] = r*10; + particlePositions[i][1] = g*10; + particlePositions[i][2] = b*10; + particlePositions[i][3] = 0; + particleColors[i][0] = r; + particleColors[i][1] = g; + particleColors[i][2] = b; + particleColors[i][3] = 1; + } + + glBindVertexArray(m_VAOs[VAO_Particle]); + glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[VBO_Particle]); + glBufferData(GL_ARRAY_BUFFER, sizeof(verticesParticle), verticesParticle, GL_STATIC_DRAW); + + // particle position buffer + glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[VBO_Particle_Positions]); + glBufferData(GL_ARRAY_BUFFER, sizeof(particlePositions), NULL, GL_STREAM_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(particlePositions), particlePositions); + + // particle color buffer + glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[VBO_Particle_Colors]); + glBufferData(GL_ARRAY_BUFFER, sizeof(particleColors), NULL, GL_STREAM_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(particleColors), particleColors); + + glVertexAttribPointer(m_vPositionLocation, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(m_vPositionLocation); + + glVertexAttribPointer(m_vNormalLocation, 3, GL_FLOAT, GL_TRUE, 0, BUFFER_OFFSET(offsetNormals)); + glEnableVertexAttribArray(m_vNormalLocation); + + glVertexAttribPointer(s_vUvLocation, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offsetUV)); + glEnableVertexAttribArray(s_vUvLocation);//*/ + + glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0 + glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1 + glVertexAttribDivisor(2, 1); // color : one per quad -> 1 + + //============================================================== + // FIN DE CODE RÉFÉRENCÉ + //============================================================== + } void Viewer::initBuffers(){ @@ -893,46 +1006,6 @@ void Viewer::initBuffers(){ } -void Viewer::drawTool() { - objShader->bind(); - - // Get projection and camera transformations - QMatrix4x4 modelViewMatrix; - - //camera()->getModelViewMatrix(modelViewMatrix); - - QMatrix4x4 toolboxPos = QMatrix4x4(); - float swingMult = 1; - //scale.translate(QVector3D(0,1.5,0)); - toolboxPos.translate(0.6, -0.25, -1.6); - toolboxPos.rotate(-100, 0, 1, 0); - if(swing.active) { - swingMult = 0.5 + 0.5 * cos(fmin(swing.length, frame - swing.startFrame) * 2 * M_PI / swing.length); - if(frame - swing.startFrame > swing.length) { - swing.active = false; - } - } - toolboxPos.rotate(swingMult * -65, 0, 0, 1); - toolboxPos.scale(0.06); - - objShader->setUniformValue(o_u_mvMatrix, modelViewMatrix * toolboxPos); - objShader->setUniformValue(o_u_nmMatrix, modelViewMatrix.normalMatrix()); - - // Draw the meshes - for (unsigned int i=0; i<_meshesGL.size(); ++i) - { - // Set its material properties - objShader->setUniformValue(o_u_kd, _meshesGL[i].diffuse); - objShader->setUniformValue(o_u_ks, _meshesGL[i].specular); - objShader->setUniformValue(o_u_kn, _meshesGL[i].specularExponent); - objShader->setUniformValue(o_u_ka, _meshesGL[i].alpha); - - // Draw the mesh - glBindVertexArray(_meshesGL[i].vao); - glDrawArrays(GL_TRIANGLES, 0, _meshesGL[i].numVertices); - } -} - void Viewer::visit(Cube &s) { m_program->bind(); @@ -1026,7 +1099,6 @@ void Viewer::visit(SceneGroup &s) modelStack.pop(); } - void Viewer::setPhong(bool on) { m_program->bind(); m_program->setUniformValue(m_isPhongLoc, on); diff --git a/src/viewer/simpleViewer.h b/src/viewer/simpleViewer.h index 34590bb..7db481d 100644 --- a/src/viewer/simpleViewer.h +++ b/src/viewer/simpleViewer.h @@ -89,6 +89,7 @@ signals: protected : virtual void draw(); + virtual void drawParticles(); virtual void drawSkybox(); virtual void drawTool(); virtual void init(); @@ -184,8 +185,8 @@ private: QColor* activeColor; int activeShape; - enum VAO_IDs { VAO_Cube, VAO_Sphere, NumVAOs }; - enum Buffer_IDs { VBO_Cube, VBO_Sphere, EBO_Sphere, NumBuffers }; + enum VAO_IDs { VAO_Cube, VAO_Sphere, VAO_Particle, NumVAOs }; + enum Buffer_IDs { VBO_Cube, VBO_Sphere, EBO_Sphere, VBO_Particle, VBO_Particle_Positions, VBO_Particle_Colors, NumBuffers }; enum RenderBuffer_IDs { RenderBuffer_Main, NumRenderBuffers }; GLuint m_VAOs[NumVAOs];