From b303c4b1ff4a23fa21a9c99e2f2b799483dcd2df Mon Sep 17 00:00:00 2001 From: Anselme Date: Wed, 6 Jan 2016 18:22:28 +0100 Subject: [PATCH] first commit of mesh refactoring --- CMakeLists.txt | 6 +- src/crappymodule.cpp | 12 +- src/forwardmodule.cpp | 22 ++- src/mesh.cpp | 304 +++++++++++++++++++++++++++++++++++++++++ src/mesh.h | 45 +++++- src/meshbuilder.cpp | 201 +-------------------------- src/meshbuilder.h | 15 +- src/parametricmesh.cpp | 18 ++- src/parametricmesh.h | 2 +- src/phongentity.cpp | 166 ---------------------- src/phongentity.h | 63 --------- src/scene.h | 19 ++- src/skyboxmodule.cpp | 1 - 13 files changed, 388 insertions(+), 486 deletions(-) create mode 100644 src/mesh.cpp delete mode 100644 src/phongentity.cpp delete mode 100644 src/phongentity.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 889b1f1..a66a777 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,7 @@ endif(WIN32) set(LIB_SRC_LIST src/framebuffer.cpp - src/meshbuilder.cpp - src/phongentity.cpp + src/meshbuilder.cpp src/phongmaterial.cpp src/crappymodule.cpp src/shader.cpp @@ -30,6 +29,7 @@ set(LIB_SRC_LIST src/posteffectmodule.cpp src/textureblur.cpp src/textureredux.cpp + src/mesh.cpp ) set(LIBRARY_NAME ${PROJECT_NAME}) @@ -45,7 +45,7 @@ if(CMAKE_BUILD_TYPE MATCHES "Debug") set(CPP_DEFINES -DRENDER_DEBUG) endif() -file(GLOB LIBRARY_RES_FILES *.h shaders/*.glsl) +file(GLOB LIBRARY_RES_FILES src/*.h shaders/*.glsl) add_library(${LIBRARY_NAME} STATIC ${LIB_SRC_LIST} ${LIBRARY_RES_FILES}) add_definitions(-std=c++11 ${CPP_DEFINES}) diff --git a/src/crappymodule.cpp b/src/crappymodule.cpp index 93af711..96a9f0d 100644 --- a/src/crappymodule.cpp +++ b/src/crappymodule.cpp @@ -1,11 +1,11 @@ #include "crappymodule.h" #include "shader.h" -#include "phongentity.h" #include "camera.h" #include "mesh.h" #include "sparrowrenderer.h" #include "scene.h" #include "glassert.h" +#include "material.h" #include void CrappyModule::renderGL(Camera* myCamera, Scene* scene) @@ -37,16 +37,16 @@ void CrappyModule::renderGL(Camera* myCamera, Scene* scene) ++i; } - for(SceneIterator* entityIt = scene->getGeometry(); - entityIt->isValid(); entityIt->next()) + for(SceneIterator* geometryIt = scene->getGeometry(); + geometryIt->isValid(); geometryIt->next()) { - PhongEntity* entity = entityIt->getItem(); + GeometryNode* node = geometryIt->getItem(); glMatrixMode(GL_MODELVIEW); - glm::mat4 modelViewMatrix = myCamera->getViewMatrix() * entity->modelMatrix; + glm::mat4 modelViewMatrix = myCamera->getViewMatrix() * node->modelMatrix; glLoadMatrixf(glm::value_ptr(modelViewMatrix)); glMatrixMode(GL_PROJECTION); glLoadMatrixf(glm::value_ptr(myCamera->getProjectionMatrix())); - entity->drawDisplayList(); + node->mesh->draw(); } glAssert(glDisable(GL_LIGHTING)); diff --git a/src/forwardmodule.cpp b/src/forwardmodule.cpp index 6621a51..686f754 100644 --- a/src/forwardmodule.cpp +++ b/src/forwardmodule.cpp @@ -1,6 +1,5 @@ #include "forwardmodule.h" #include "scene.h" -#include "phongentity.h" #include "mesh.h" #include "shader.h" #include "light.h" @@ -84,17 +83,17 @@ void ForwardModule::lightPass(Camera* myCamera, Scene* scene, Light* light) break; } } - for(SceneIterator* entityIt = scene->getGeometry(); - entityIt->isValid(); entityIt->next()) + for(SceneIterator* geometryIt = scene->getGeometry(); + geometryIt->isValid(); geometryIt->next()) { // compute matrix attributes - PhongEntity* entity = entityIt->getItem(); - glm::mat4 modelViewMatrix = myCamera->getViewMatrix() * entity->modelMatrix; + GeometryNode* node = geometryIt->getItem(); + glm::mat4 modelViewMatrix = myCamera->getViewMatrix() * node->modelMatrix; glm::mat4 mvp = myCamera->getProjectionMatrix() * modelViewMatrix; glm::mat4 normalMatrix = glm::transpose(glm::inverse(modelViewMatrix)); if(light != NULL && light->isShadowCaster()) { - glm::mat4 lightMVP = Light::biasMatrix * light->getProjectionMatrix() * light->getViewMatrix() * entity->modelMatrix; + glm::mat4 lightMVP = Light::biasMatrix * light->getProjectionMatrix() * light->getViewMatrix() * node->modelMatrix; shader->bindMat4(shader->getLocation("lightMVP"), lightMVP); } shader->bindMat4(shader->getLocation("viewMatrix"), myCamera->getViewMatrix()); @@ -102,16 +101,11 @@ void ForwardModule::lightPass(Camera* myCamera, Scene* scene, Light* light) shader->bindMat3(shader->getLocation("normalMatrix"), glm::mat3(normalMatrix)); shader->bindMat4(shader->getLocation("MVP"), mvp); // loop over material groups - for(int j=0; jgetMesh()->indiceGroups.size(); ++j) + for(int j=0; jmesh->indiceGroups.size(); ++j) { - Material* mat = entity->getMesh()->indiceGroups[j].material; + Material* mat = node->getMesh()->indiceGroups[j].material; if(mat->getFlags() == geometryFlagList[i]) - { - // bind material attributes - mat->bindAttributes(shader); - // draw geometry - entity->drawGroup(j); - } + node->mesh->draw(shader); } } } diff --git a/src/mesh.cpp b/src/mesh.cpp new file mode 100644 index 0000000..20dd468 --- /dev/null +++ b/src/mesh.cpp @@ -0,0 +1,304 @@ +#include "mesh.h" +#include +#include +#include "glassert.h" +#include "sparrowrenderer.h" + +Mesh::Mesh() : + material(NULL), + vao(0), + nb_buffers(0), + vbo(NULL) +{} + +Mesh::~Mesh() +{ + destroyGL(); +} + +void Mesh::initGL(bool isDynamic) +{ + if(vbo != NULL) + destroyGL(); + + GLenum buffer_type = isDynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; + + // create VAO + glAssert(glGenVertexArrays(1, &vao)); + glAssert(glBindVertexArray(vao)); + + nb_buffers = 2; // positions and indices buffers + if(mesh->hasNormals()) + ++nb_buffers; + if(mesh->hasTexCoords()) + ++nb_buffers; + if(mesh->hasTangents()) + ++nb_buffers; + + // create VBOs + vbo = new GLuint[nb_buffers](); + glAssert(glGenBuffers(nb_buffers, vbo)); + + // init indices vbos + glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDICES_BUFFER])); + glAssert(glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), buffer_type)); + + // init positions vbo + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER])); + glAssert(glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(glm::vec3), positions.data(), buffer_type)); + + if(hasNormals()) + { + // init normals vbo + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER])); + glAssert(glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), normals.data(), buffer_type)); + } + + if(hasNormals()) + { + // init texCoords vbo + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER])); + glAssert(glBufferData(GL_ARRAY_BUFFER, texCoords.size() * sizeof(glm::vec2), texCoords.data(), buffer_type)); + } + + if(hasTangents()) + { + // init tangents vbo + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER])); + glAssert(glBufferData(GL_ARRAY_BUFFER, tangents.size() * sizeof(glm::vec3)*2, tangents.data(), buffer_type)); + } + + // unbind vao + glAssert(glBindVertexArray(0)); +} + +void Mesh::draw(Shader* shader, bool drawNormals, bool drawTexCoord, bool drawTangents) +{ + bool crappy = (shader == NULL); + material.bindAttributes(shader); + glAssert(glBindVertexArray(vao)); + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER])); + if(crappy) + { + glAssert(glEnableClientState(GL_VERTEX_ARRAY)); + glAssert(glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0))); + } + else + { + glAssert(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0))); + glAssert(glEnableVertexAttribArray(0)); + } + if(hasNormals() && drawNormals) + { + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER])); + if(crappy) + { + glAssert(glEnableClientState(GL_NORMAL_ARRAY)); + glAssert(glNormalPointer(GL_FLOAT, 0, BUFFER_OFFSET(0))); + } + else + { + glAssert(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0))); + glAssert(glEnableVertexAttribArray(1)); + } + } + if(hasTexCoords() && drawTexCoord) + { + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER])); + if(crappy) + { + glAssert(glEnableClientState(GL_TEXTURE_COORD_ARRAY)); + glAssert(glTexCoordPointer(2, GL_FLOAT, 0, BUFFER_OFFSET(0))); + } + else + { + glAssert(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), BUFFER_OFFSET(0))); + glAssert(glEnableVertexAttribArray(2)); + } + } + if(hasTangents() && drawTangents && !crappy) + { + glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER])); + glAssert(glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(0))); + glAssert(glEnableVertexAttribArray(3)); + glAssert(glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(sizeof(glm::vec3)))); + glAssert(glEnableVertexAttribArray(4)); + } + glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDICES_BUFFER])); + glAssert(glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, NULL)); + glAssert(glBindVertexArray(0)); + if(crappy) + { + glAssert(glDisableClientState(GL_VERTEX_ARRAY)); + if(hasNormals() && drawNormals) + glAssert(glDisableClientState(GL_NORMAL_ARRAY)); + if(hasTexCoords() && drawTexCoord) + glAssert(glDisableClientState(GL_TEXTURE_COORD_ARRAY)); + } +} + +void Mesh::destroyGL() +{ + if(vbo != NULL) + { + glAssert(glDeleteVertexArrays(1, &vao)); + glAssert(glDeleteBuffers(nb_buffers, vbo)); + delete[] vbo; + vao = 0; + nb_buffers = 0; + vbo = NULL; + } +} + +struct VertexComparator +{ + // c'est plutot crade mais j'ai pas trouve d'autre moyen pour le moment + static Mesh* mesh; + static void setMesh(MeshBuilder* m) {VertexComparator::mesh = m;} + + bool operator() (const int& vertId1, const int& vertId2) const + { + if(mesh->positions[vertId1].x != mesh->positions[vertId2].x) + return (mesh->positions[vertId1].x < mesh->positions[vertId2].x); + if(mesh->positions[vertId1].y != mesh->positions[vertId2].y) + return (mesh->positions[vertId1].y < mesh->positions[vertId2].y); + if(mesh->positions[vertId1].z != mesh->positions[vertId2].z) + return (mesh->positions[vertId1].z < mesh->positions[vertId2].z); + if(mesh->hasTexCoords()) + { + if(mesh->texCoords[vertId1].x != mesh->texCoords[vertId2].x) + return (mesh->texCoords[vertId1].x < mesh->texCoords[vertId2].x); + if(mesh->texCoords[vertId1].y != mesh->texCoords[vertId2].y) + return (mesh->texCoords[vertId1].y < mesh->texCoords[vertId2].y); + } + if(mesh->hasNormals()) + { + if(mesh->normals[vertId1].x != mesh->normals[vertId2].x) + return (mesh->normals[vertId1].x < mesh->normals[vertId2].x); + if(mesh->normals[vertId1].y != mesh->normals[vertId2].y) + return (mesh->normals[vertId1].y < mesh->normals[vertId2].y); + if(mesh->normals[vertId1].z != mesh->normals[vertId2].z) + return (mesh->normals[vertId1].z < mesh->normals[vertId2].z); + } + return false; + } +}; + +Mesh* VertexComparator::mesh = NULL; + +void Mesh::mergeVertices() +{ + std::vector swapped; + std::set vertexSet; + VertexComparator::setMesh(this); + + int swappedOffset = positions.size() - 1; + + for(int i=0; i= positions.size()) + indices[i] = swapped[swappedOffset - indices[i]]; + std::pair::iterator,bool> ret = vertexSet.insert(g.indices[i]); + if(!ret.second) // duplicate found + { + // updating indices references + int toDelete = indices[i]; + swapped.push_back(toDelete); + indices[i] = *(ret.first); + // deleting the duplicate + positions[toDelete] = positions.back(); + positions.pop_back(); + if(hasTexCoords()) + { + texCoords[toDelete] = texCoords.back(); + texCoords.pop_back(); + } + if(hasNormals()) + { + normals[toDelete] = normals.back(); + normals.pop_back(); + } + if(hasTangents()) + { + tangents[indices[i]].tangent += tangents[toDelete].tangent; + tangents[indices[i]].binormal += tangents[toDelete].binormal; + tangents[toDelete] = tangents.back(); + tangents.pop_back(); + } + } + } + for(Tangents &t : tangents) + { + t.tangent = glm::normalize(t.tangent); + t.binormal = glm::normalize(t.binormal); + } +} + +void Mesh::computeNormals() +{ + normals.resize(positions.size()); + for (int i=0; i < indices.size(); i += 3) + { + int v0 = indices[i]; + int v1 = indices[i+1]; + int v2 = indices[i+2]; + glm::vec3 n = glm::cross(positions[v1] - positions[v0], positions[v2] - positions[v0]); + normals[v0] += n; + normals[v1] += n; + normals[v2] += n; + } + for(glm::vec3 &n : normals) + n = glm::normalize(n); +} + +void Mesh::computeTangents() +{ + if(!hasTexCoords()) + return; + tangents = std::vector(positions.size()); + + for (int j=0; j < indices.size(); j += 3) + { + int vertexId0 = indices[j]; + int vertexId1 = indices[j+1]; + int vertexId2 = indices[j+2]; + + const glm::vec3 &v1 = positions[vertexId0]; + const glm::vec3 &v2 = positions[vertexId1]; + const glm::vec3 &v3 = positions[vertexId2]; + + const glm::vec2& w1 = texCoords[vertexId0]; + const glm::vec2& w2 = texCoords[vertexId1]; + const glm::vec2& w3 = texCoords[vertexId2]; + + float x1 = v2.x - v1.x; + float x2 = v3.x - v1.x; + float y1 = v2.y - v1.y; + float y2 = v3.y - v1.y; + float z1 = v2.z - v1.z; + float z2 = v3.z - v1.z; + + float s1 = w2.x - w1.x; + float s2 = w3.x - w1.x; + float t1 = w2.y - w1.y; + float t2 = w3.y - w1.y; + + float r = 1.0f / (s1 * t2 - s2 * t1); + glm::vec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r); + glm::vec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r); + + Tangents& tan1 = tangents[vertexId0]; + Tangents& tan2 = tangents[vertexId1]; + Tangents& tan3 = tangents[vertexId2]; + + tan1.tangent += sdir; + tan2.tangent += sdir; + tan3.tangent += sdir; + + tan1.binormal += tdir; + tan2.binormal += tdir; + tan3.binormal += tdir; + } +} diff --git a/src/mesh.h b/src/mesh.h index 1f6ab6e..5e4b42e 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -1,31 +1,64 @@ #ifndef MESH_H #define MESH_H +#include #include #include #include class Material; +class Shader; struct Mesh { +protected: + + // geometry data + typedef struct { glm::vec3 tangent; glm::vec3 binormal; } Tangents; - typedef struct - { - std::vector indices; - Material* material; - } Group; + Material* material; std::vector positions; std::vector normals; std::vector texCoords; std::vector tangents; - std::vector indiceGroups; + std::vector indices; + + // opengl + + enum { + // required buffers + POSITION_BUFFER, + // optionnal buffers : + NORMAL_BUFFER, TEXCOORD_BUFFER, TANGENT_BUFFER, + // indices buffers + INDICES_BUFFER + }; + + GLuint vao; + int nb_buffers; + GLuint* vbo; + +public: + Mesh(); + ~Mesh(); + + void initGL(bool isDynamic = false); + void draw(Shader* shader = NULL, bool drawNormals = true, bool drawTexCoord = true, bool drawTangents = true); + void destroyGL(); + + // merge same vertices + void mergeVertices(); + bool operator() (const int& vertId1, const int& vertId2) const; + // require positions and indices + void computeNormals(); + // require normals and texCoord + void computeTangents(); bool hasNormals() const { diff --git a/src/meshbuilder.cpp b/src/meshbuilder.cpp index da3f52e..d2ec633 100644 --- a/src/meshbuilder.cpp +++ b/src/meshbuilder.cpp @@ -1,6 +1,4 @@ #include "meshbuilder.h" -#include -#include void MeshBuilder::addPosition(float x, float y, float z) { @@ -54,201 +52,12 @@ void MeshBuilder::addVertex(const glm::vec3 &position, const glm::vec3 &normal, void MeshBuilder::addTriangle(int i1, int i2, int i3) { - indiceGroups[currentGroup].indices.push_back(i1); - indiceGroups[currentGroup].indices.push_back(i2); - indiceGroups[currentGroup].indices.push_back(i3); + indices.push_back(i1); + indices.push_back(i2); + indices.push_back(i3); } -void MeshBuilder::addGroup(Material* myMaterial) +void MeshBuilder::setMaterial(Material* myMaterial) { - Group g; - g.material = myMaterial; - setCurrentGroup(getNbGroups()); - indiceGroups.push_back(g); -} - -void MeshBuilder::setCurrentGroup(int groupId) -{ - currentGroup = groupId; -} - -void MeshBuilder::setCurrentGroupMaterial(Material* myMaterial) -{ - indiceGroups[currentGroup].material = myMaterial; -} - -int MeshBuilder::getNbGroups() -{ - return indiceGroups.size(); -} - -class VertexComparator -{ -public: - // c'est crade mais j'ai pas trouvé d'autre moyen pour le moment - static MeshBuilder* mesh; - static void setMesh(MeshBuilder* m) {VertexComparator::mesh = m;} - - bool operator() (const int& vertId1, const int& vertId2) const - { - if(mesh->positions[vertId1].x != mesh->positions[vertId2].x) - return (mesh->positions[vertId1].x < mesh->positions[vertId2].x); - if(mesh->positions[vertId1].y != mesh->positions[vertId2].y) - return (mesh->positions[vertId1].y < mesh->positions[vertId2].y); - if(mesh->positions[vertId1].z != mesh->positions[vertId2].z) - return (mesh->positions[vertId1].z < mesh->positions[vertId2].z); - if(mesh->hasTexCoords()) - { - if(mesh->texCoords[vertId1].x != mesh->texCoords[vertId2].x) - return (mesh->texCoords[vertId1].x < mesh->texCoords[vertId2].x); - if(mesh->texCoords[vertId1].y != mesh->texCoords[vertId2].y) - return (mesh->texCoords[vertId1].y < mesh->texCoords[vertId2].y); - } - if(mesh->hasNormals()) - { - if(mesh->normals[vertId1].x != mesh->normals[vertId2].x) - return (mesh->normals[vertId1].x < mesh->normals[vertId2].x); - if(mesh->normals[vertId1].y != mesh->normals[vertId2].y) - return (mesh->normals[vertId1].y < mesh->normals[vertId2].y); - if(mesh->normals[vertId1].z != mesh->normals[vertId2].z) - return (mesh->normals[vertId1].z < mesh->normals[vertId2].z); - } - return false; - } -}; - -MeshBuilder* VertexComparator::mesh = NULL; - -void MeshBuilder::mergeVertices() -{ - std::vector swapped; - std::set vertexSet; - VertexComparator::setMesh(this); - - int swappedOffset = positions.size() - 1; - - for(Group &g : indiceGroups) - for(int i=0; i= positions.size()) - g.indices[i] = swapped[swappedOffset - g.indices[i]]; - std::pair::iterator,bool> ret = vertexSet.insert(g.indices[i]); - if(!ret.second) // duplicate found - { - // updating indices references - int toDelete = g.indices[i]; - swapped.push_back(toDelete); - g.indices[i] = *(ret.first); - // deleting the duplicate - positions[toDelete] = positions.back(); - positions.pop_back(); - if(hasTexCoords()) - { - texCoords[toDelete] = texCoords.back(); - texCoords.pop_back(); - } - if(hasNormals()) - { - normals[toDelete] = normals.back(); - normals.pop_back(); - } - if(hasTangents()) - { - tangents[g.indices[i]].tangent += tangents[toDelete].tangent; - tangents[g.indices[i]].binormal += tangents[toDelete].binormal; - tangents[toDelete] = tangents.back(); - tangents.pop_back(); - } - } - } - for(Tangents &t : tangents) - { - t.tangent = glm::normalize(t.tangent); - t.binormal = glm::normalize(t.binormal); - } -} - -void MeshBuilder::computeNormals() -{ - normals.resize(positions.size()); - for(const Group &g : indiceGroups) - for (int i=0; i < g.indices.size(); i += 3) - { - int v0 = g.indices[i]; - int v1 = g.indices[i+1]; - int v2 = g.indices[i+2]; - glm::vec3 n = glm::cross(positions[v1] - positions[v0], positions[v2] - positions[v0]); - normals[v0] += n; - normals[v1] += n; - normals[v2] += n; - } - for(glm::vec3 &n : normals) - n = glm::normalize(n); -} - -void MeshBuilder::computeTangents() -{ - if(!hasTexCoords()) - return; - tangents = std::vector(positions.size()); - - for(const Group &g : indiceGroups) - for (int j=0; j < g.indices.size(); j += 3) - { - int vertexId0 = g.indices[j]; - int vertexId1 = g.indices[j+1]; - int vertexId2 = g.indices[j+2]; - - const glm::vec3 &v1 = positions[vertexId0]; - const glm::vec3 &v2 = positions[vertexId1]; - const glm::vec3 &v3 = positions[vertexId2]; - - const glm::vec2& w1 = texCoords[vertexId0]; - const glm::vec2& w2 = texCoords[vertexId1]; - const glm::vec2& w3 = texCoords[vertexId2]; - - float x1 = v2.x - v1.x; - float x2 = v3.x - v1.x; - float y1 = v2.y - v1.y; - float y2 = v3.y - v1.y; - float z1 = v2.z - v1.z; - float z2 = v3.z - v1.z; - - float s1 = w2.x - w1.x; - float s2 = w3.x - w1.x; - float t1 = w2.y - w1.y; - float t2 = w3.y - w1.y; - - float r = 1.0f / (s1 * t2 - s2 * t1); - glm::vec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - glm::vec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); - - Tangents& tan1 = tangents[vertexId0]; - Tangents& tan2 = tangents[vertexId1]; - Tangents& tan3 = tangents[vertexId2]; - - tan1.tangent += sdir; - tan2.tangent += sdir; - tan3.tangent += sdir; - - tan1.binormal += tdir; - tan2.binormal += tdir; - tan3.binormal += tdir; - } - - // building tangent matrix - /* - for (long a = 0; a < vertexCount; a++) - { - const Vector3D& n = normal[a]; - const Vector3D& t = tan1[a]; - - // Gram-Schmidt orthogonalize - tangent[a] = (t - n * Dot(n, t)).Normalize(); - - // Calculate handedness - tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F; - }*/ + material = myMaterial; } diff --git a/src/meshbuilder.h b/src/meshbuilder.h index 3487b3e..2bdebbf 100644 --- a/src/meshbuilder.h +++ b/src/meshbuilder.h @@ -5,8 +5,6 @@ class MeshBuilder : public Mesh { - int currentGroup; - public: void addTriangle(int i1, int i2, int i3); @@ -21,18 +19,7 @@ public: void addVertex(const glm::vec3 &position, const glm::vec2 &texCoord); void addVertex(const glm::vec3 &position, const glm::vec3 &normal, const glm::vec2 &texCoord); - void addGroup(Material* myMaterial); - void setCurrentGroup(int groupId); - void setCurrentGroupMaterial(Material* myMaterial); - int getNbGroups(); - - // merge same vertices - void mergeVertices(); - bool operator() (const int& vertId1, const int& vertId2) const; - // require positions and indices - void computeNormals(); - // require normals and texCoord - void computeTangents(); + void setMaterial(Material* myMaterial); }; #endif // MESHBUILDER_H diff --git a/src/parametricmesh.cpp b/src/parametricmesh.cpp index 514e7c9..4ce27b2 100644 --- a/src/parametricmesh.cpp +++ b/src/parametricmesh.cpp @@ -8,8 +8,6 @@ Sphere::Sphere(Material* mat, int n) { // icosahedron : - addGroup(mat); - Group* group = &(indiceGroups[0]); // top cap createVertex(0, 1); @@ -37,7 +35,7 @@ Sphere::Sphere(Material* mat, int n) // geodesic subdivisions : for(int i=0; iindices.size()/3; + int nb_triangles = indices.size()/3; for(int j=0; jindices[j*3 + k]; - int idB = group->indices[j*3 + (k+1)%3]; + int idA = indices[j*3 + k]; + int idB = indices[j*3 + (k+1)%3]; int a = idA < idB ? idA : idB; int b = idA > idB ? idA : idB; vid[k] = getEdge(a, b); } for(int k=0; k<3; k++) - addTriangle(group->indices[j*3 + k], vid[k], vid[(k+2)%3]); + addTriangle(indices[j*3 + k], vid[k], vid[(k+2)%3]); addTriangle(vid[0], vid[1], vid[2]); } delete[](edges); - group->indices.erase(group->indices.begin(), group->indices.begin()+nb_triangles*3); + indices.erase(indices.begin(), indices.begin()+nb_triangles*3); } void Sphere::createVertex(float u, float v) @@ -113,7 +111,7 @@ void Sphere::createVertex(float u, float v) GridMesh::GridMesh(Material* mat, int width, int height, bool alternate) { - addGroup(mat); + setMaterial(mat); for(int i=0; i<=width; ++i) { for(int j=0; j<=height; ++j) diff --git a/src/parametricmesh.h b/src/parametricmesh.h index 89e421f..74a599e 100644 --- a/src/parametricmesh.h +++ b/src/parametricmesh.h @@ -22,7 +22,7 @@ private: Edge* edges; int getEdge(int a, int b); void createVertex(float u, float v); - void subdivide(Group* group); + void subdivide(); public: Sphere(Material* mat, int n = 0); }; diff --git a/src/phongentity.cpp b/src/phongentity.cpp deleted file mode 100644 index ac5d563..0000000 --- a/src/phongentity.cpp +++ /dev/null @@ -1,166 +0,0 @@ -#include "phongentity.h" -#include "shader.h" -#include -#include "phongmaterial.h" -#include "mesh.h" -#include -#include "glassert.h" -#include "sparrowrenderer.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -PhongEntity::PhongEntity(Mesh* myMesh) : - mesh(myMesh), - vao(0), - nb_buffers(0), - vbo(NULL), - displayList(0), - modelMatrix() -{} - -void PhongEntity::modernInit(bool isDynamic) -{ - GLenum buffer_type = isDynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; - - // create VAO - glAssert(glGenVertexArrays(1, &vao)); - glAssert(glBindVertexArray(vao)); - - nb_buffers = 1; // positions buffer - if(mesh->hasNormals()) - ++nb_buffers; - if(mesh->hasTexCoords()) - ++nb_buffers; - if(mesh->hasTangents()) - ++nb_buffers; - - nb_buffers += mesh->indiceGroups.size(); - - // create VBOs - vbo = new GLuint[nb_buffers](); - glAssert(glGenBuffers(nb_buffers, vbo)); - - for(int i=0; iindiceGroups.size(); ++i) - { - const Mesh::Group &g = mesh->indiceGroups[i]; - // init indices vbos - glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDICES_BUFFERS + i])); - glAssert(glBufferData(GL_ELEMENT_ARRAY_BUFFER, g.indices.size() * sizeof(GLuint), g.indices.data(), buffer_type)); - } - - // init positions vbo - glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER])); - glAssert(glBufferData(GL_ARRAY_BUFFER, mesh->positions.size() * sizeof(glm::vec3), mesh->positions.data(), buffer_type)); - - if(mesh->hasNormals()) - { - // init normals vbo - glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER])); - glAssert(glBufferData(GL_ARRAY_BUFFER, mesh->normals.size() * sizeof(glm::vec3), mesh->normals.data(), buffer_type)); - } - - if(mesh->hasNormals()) - { - // init texCoords vbo - glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER])); - glAssert(glBufferData(GL_ARRAY_BUFFER, mesh->texCoords.size() * sizeof(glm::vec2), mesh->texCoords.data(), buffer_type)); - } - - if(mesh->hasTangents()) - { - // init tangents vbo - glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER])); - glAssert(glBufferData(GL_ARRAY_BUFFER, mesh->tangents.size() * sizeof(glm::vec3)*2, mesh->tangents.data(), buffer_type)); - } - - // unbind vao - glAssert(glBindVertexArray(0)); -} - -void PhongEntity::crappyInit() -{ - displayList = glAssert(glGenLists(1)); - glAssert(glNewList(displayList, GL_COMPILE)); - for(int i=0; iindiceGroups.size(); ++i) - { - PhongMaterial* mat = (PhongMaterial*)(mesh->indiceGroups[i].material); - mat->bindAttributes(NULL); - glAssert(glBegin(GL_TRIANGLES)); - for(int j=0; jindiceGroups[i].indices.size(); ++j) - { - int vid = mesh->indiceGroups[i].indices[j]; - glNormal3fv(glm::value_ptr(mesh->normals[vid])); - glTexCoord2fv(glm::value_ptr(mesh->texCoords[vid])); - glVertex3fv(glm::value_ptr(mesh->positions[vid])); - } - glAssert(glEnd()); - } - glAssert(glEndList()); -} - -void PhongEntity::initGL(bool isDynamic) -{ - if(SparrowRenderer::isModernOpenGLAvailable()) - modernInit(isDynamic); - else - crappyInit(); -} - -void PhongEntity::destroyGL() -{ - if(SparrowRenderer::isModernOpenGLAvailable()) - { - glAssert(glDeleteVertexArrays(1, &vao)); - glAssert(glDeleteBuffers(nb_buffers, vbo)); - delete[] vbo; - vbo = NULL; - } - else - glAssert(glDeleteLists(displayList, 1)); -} - -void PhongEntity::drawGroup(int groupId, bool drawNormals, bool drawTexCoord, bool drawTangents) -{ - glAssert(glBindVertexArray(vao)); - glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[POSITION_BUFFER])); - glAssert(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0))); - glAssert(glEnableVertexAttribArray(0)); - if(mesh->hasNormals() && drawNormals) - { - glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[NORMAL_BUFFER])); - glAssert(glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), BUFFER_OFFSET(0))); - glAssert(glEnableVertexAttribArray(1)); - } - if(mesh->hasTexCoords() && drawTexCoord) - { - glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TEXCOORD_BUFFER])); - glAssert(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), BUFFER_OFFSET(0))); - glAssert(glEnableVertexAttribArray(2)); - } - if(mesh->hasTangents() && drawTangents) - { - glAssert(glBindBuffer(GL_ARRAY_BUFFER, vbo[TANGENT_BUFFER])); - glAssert(glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(0))); - glAssert(glEnableVertexAttribArray(3)); - glAssert(glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Mesh::Tangents), BUFFER_OFFSET(sizeof(glm::vec3)))); - glAssert(glEnableVertexAttribArray(4)); - } - glAssert(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[INDICES_BUFFERS + groupId])); - glAssert(glDrawElements(GL_TRIANGLES, mesh->indiceGroups[groupId].indices.size(), GL_UNSIGNED_INT, NULL)); -} - -void PhongEntity::drawDisplayList() -{ - glAssert(glCallList(displayList)); -} - -PhongEntity* PhongEntity::clone() -{ - PhongEntity* myClone = new PhongEntity(mesh); - myClone->modelMatrix = modelMatrix; - myClone->displayList = displayList; - myClone->nb_buffers = nb_buffers; - myClone->vao = vao; - myClone->vbo = vbo; - return myClone; -} diff --git a/src/phongentity.h b/src/phongentity.h deleted file mode 100644 index 0c42063..0000000 --- a/src/phongentity.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef PHONGENTITY_H -#define PHONGENTITY_H - -#include -#include -#include - -class Mesh; -class Material; -class Shader; - -class PhongEntity -{ -protected: - Mesh* mesh; - - // modern opengl : - - enum { - // required buffers - POSITION_BUFFER, - // optionnal buffers : - NORMAL_BUFFER, TEXCOORD_BUFFER, TANGENT_BUFFER, - // indices buffers - INDICES_BUFFERS - }; - - GLuint vao; - int nb_buffers; - GLuint* vbo; - - void modernInit(bool isDynamic); - - // old opengl : - - GLuint displayList; - - void crappyInit(); - -public: - /** - * @brief the model matrix is public, so the user can manipulate it in any way he desires. - */ - glm::mat4 modelMatrix; - - PhongEntity(Mesh* myMesh); - - void drawDisplayList(); - void drawGroup(int groupId, bool drawNormals = true, bool drawTexCoord = true, bool drawTangents = true); - - void initGL(bool isDynamic = false); - void destroyGL(); - - Mesh* getMesh() {return mesh;} - - /** - * @brief this method returns a clone of the current entity. - * The same VAO/displayList will be used to render both, so there is no need to call initGL on the clone - */ - PhongEntity* clone(); -}; - -#endif // PHONGENTITY_H diff --git a/src/scene.h b/src/scene.h index c067768..124f389 100644 --- a/src/scene.h +++ b/src/scene.h @@ -5,7 +5,8 @@ #include "camera.h" #include #include "light.h" -#include "phongentity.h" + +class Mesh; // Scene interface : @@ -20,11 +21,17 @@ public: T& getItem() {return operator*();} }; +struct GeometryNode +{ + Mesh* mesh; + glm::mat4 modelMatrix; +}; + class Scene { public: virtual SceneIterator* getLights() = 0; - virtual SceneIterator* getGeometry() = 0; + virtual SceneIterator* getGeometry() = 0; }; // Some basic implementations : @@ -45,16 +52,16 @@ class ArrayScene : public Scene { protected: std::vector lights; - std::vector entities; + std::vector geometry; public: void clearLights() {lights.clear();} - void clearEntities() {entities.clear();} + void clearEntities() {geometry.clear();} void clearScene() {clearLights(); clearEntities();} - void addEntity(PhongEntity* myEntity) {entities.push_back(myEntity);} + void addMesh(GeometryNode* node) {geometry.push_back(node);} void addLight(Light* myLight) {lights.push_back(myLight);} virtual SceneIterator* getLights() {return new ArraySceneIterator(lights);} - virtual SceneIterator* getGeometry() {return new ArraySceneIterator(entities);} + virtual SceneIterator* getGeometry() {return new ArraySceneIterator(geometry);} }; #endif // SCENE_H diff --git a/src/skyboxmodule.cpp b/src/skyboxmodule.cpp index 8a747b6..16fa8c2 100644 --- a/src/skyboxmodule.cpp +++ b/src/skyboxmodule.cpp @@ -2,7 +2,6 @@ #include #include #include "skyboxmodule.h" -#include "phongentity.h" #include "shader.h" #include "texture.h" #include "camera.h"