From bd382f9e8e00a71e8a66cc318116479748e1bad4 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 25 Feb 2015 23:39:20 +0100 Subject: [PATCH] Cleanup of WaveFrontGeometry --- .../rendering/model/wavefrontgeometry.h | 38 +-- include/openspace/util/constants.h | 5 - src/rendering/model/modelgeometry.cpp | 8 +- src/rendering/model/wavefrontgeometry.cpp | 240 +++++------------- 4 files changed, 85 insertions(+), 206 deletions(-) diff --git a/include/openspace/rendering/model/wavefrontgeometry.h b/include/openspace/rendering/model/wavefrontgeometry.h index 90b1afda9b..f61e3e08eb 100644 --- a/include/openspace/rendering/model/wavefrontgeometry.h +++ b/include/openspace/rendering/model/wavefrontgeometry.h @@ -26,7 +26,6 @@ #define __WAVEFRONTOBJECT_H__ #include -#include namespace openspace { @@ -37,44 +36,31 @@ namespace modelgeometry { class WavefrontGeometry : public ModelGeometry { public: WavefrontGeometry(const ghoul::Dictionary& dictionary); - ~WavefrontGeometry(); bool initialize(RenderableModel* parent) override; void deinitialize() override; void render() override; - typedef struct - { - GLfloat location[4]; - GLfloat tex[2]; - GLfloat normal[3]; - GLfloat padding[7]; - //GLubyte padding[4]; // Pads the struct out to 64 bytes for performance increase - } Vertex; - - std::vector shapes; - std::vector materials; -protected: +private: + struct Vertex { + GLfloat location[4]; + GLfloat tex[2]; + GLfloat normal[3]; + }; + bool loadObj(const std::string& filename); bool loadCachedFile(const std::string& filename); bool saveCachedFile(const std::string& filename); bool loadModel(const std::string& filename); -private: - void createSphere(); - GLuint _vaoID; - GLuint _vBufferID; - GLuint _iBufferID; + GLuint _vbo; + GLuint _ibo; - GLuint _tBufferID; - unsigned int _tsize; - float* _tarray; + std::vector _vertices; + std::vector _indices; - unsigned int _isize; - unsigned int _vsize; - Vertex* _varray; - int* _iarray; + std::vector _shapeCounts; }; } // namespace modelgeometry diff --git a/include/openspace/util/constants.h b/include/openspace/util/constants.h index c82272d426..d82d62fb76 100644 --- a/include/openspace/util/constants.h +++ b/include/openspace/util/constants.h @@ -88,11 +88,6 @@ namespace renderablemodel { const std::string keyGeometry = "Geometry"; } // namespace renderablemodel -namespace modelgeometry { - const std::string keyType = "Type"; - const std::string keyObjFile = "ObjFile"; -} // namespace modelgeometry - namespace renderablestars { const std::string keyFile = "File"; const std::string keyTexture = "Texture"; diff --git a/src/rendering/model/modelgeometry.cpp b/src/rendering/model/modelgeometry.cpp index 860c783517..6fb7946ec1 100644 --- a/src/rendering/model/modelgeometry.cpp +++ b/src/rendering/model/modelgeometry.cpp @@ -28,7 +28,9 @@ #include namespace { -const std::string _loggerCat = "ModelGeometry"; + const std::string _loggerCat = "ModelGeometry"; + + const std::string keyType = "Type"; } namespace openspace { @@ -38,10 +40,10 @@ ModelGeometry* ModelGeometry::createFromDictionary(const ghoul::Dictionary& dict { std::string geometryType; const bool success = dictionary.getValue( - constants::modelgeometry::keyType, geometryType); + keyType, geometryType); if (!success) { LERROR("ModelGeometry did not contain a correct value of the key '" - << constants::modelgeometry::keyType << "'"); + << keyType << "'"); return nullptr; } ghoul::TemplateFactory* factory diff --git a/src/rendering/model/wavefrontgeometry.cpp b/src/rendering/model/wavefrontgeometry.cpp index 8a1cb3ef30..cd2fc292cf 100644 --- a/src/rendering/model/wavefrontgeometry.cpp +++ b/src/rendering/model/wavefrontgeometry.cpp @@ -30,11 +30,15 @@ #include "ghoul/logging/logmanager.h" #include +#include +#include namespace { const std::string _loggerCat = "WavefrontGeometry"; - const int8_t CurrentCacheVersion = 1; + const std::string keyObjFile = "ObjFile"; + + const int8_t CurrentCacheVersion = 2; } namespace openspace { @@ -42,31 +46,25 @@ namespace modelgeometry { WavefrontGeometry::WavefrontGeometry(const ghoul::Dictionary& dictionary) : ModelGeometry() - , _isize(0) - , _vsize(0) - , _varray(nullptr) - , _iarray(nullptr) - , _tarray(nullptr) { using constants::scenegraphnode::keyName; - // The name is passed down from the SceneGraphNode std::string name; bool success = dictionary.getValue(keyName, name); ghoul_assert(success, "Name tag was not present"); std::string file; - success = dictionary.getValue(constants::modelgeometry::keyObjFile, file); + success = dictionary.getValue(keyObjFile, file); if (!success) { - LERROR("SimpleSphereGeometry of '" << name << "' did not provide a key '" - << constants::modelgeometry::keyObjFile << "'"); + LERROR("WaveFrontGeometry of '" << name << "' did not provide a key '" + << keyObjFile << "'"); } - const std::string filename = FileSys.absolutePath(file); + file = FileSys.absolutePath(file); - if (FileSys.fileExists(filename)) - loadObj(filename); + if (FileSys.fileExists(file, true)) + loadObj(file); else - LERROR("Could not load OBJ file '" << filename << "': File not found"); + LERROR("Could not load OBJ file '" << file << "': File not found"); } bool WavefrontGeometry::loadObj(const std::string& filename){ @@ -89,7 +87,6 @@ bool WavefrontGeometry::loadObj(const std::string& filename){ LINFO("Cache for Model'" << filename << "' not found"); } LINFO("Loading OBJ file '" << filename << "'"); - bool success = loadModel(filename); if (!success) return false; @@ -98,92 +95,22 @@ bool WavefrontGeometry::loadObj(const std::string& filename){ success = saveCachedFile(cachedFile); return success; - - - - - //if (shapes[0].mesh.texcoords.size() > 0) { - // for (int k = 0; k < shapes[0].mesh.texcoords.size(); ++k) { - - // } - //} - // - //if (shapes[0].mesh.texcoords.size() > 0) { - // for (size_t k = 0; k < shapes[0].mesh.indices.size() / 3; k++) { - // for (int j = 0; j < 3; j++) { - // int idx = shapes[0].mesh.indices[3 * k + j]; - - // _varray[p].tex[0] = shapes[0].mesh.texcoords[2 * idx + 0]; - // _varray[p].tex[1] = shapes[0].mesh.texcoords[2 * idx + 1]; - // p++; - // } - // } - //} - - - //testing with one triangle - works. - /* - _varray[0].location[0] = 0; - _varray[0].location[1] = 0; - _varray[0].location[2] = 0; - _varray[0].location[3] = 5; - - _varray[0].normal[0] = 1; - _varray[0].normal[1] = 1; - _varray[0].normal[2] = 1; - - _varray[0].tex[0] = 0; - _varray[0].tex[1] = 0; - - _varray[1].location[0] = 1; - _varray[1].location[1] = 0; - _varray[1].location[2] = 0; - _varray[1].location[3] = 5; - - _varray[1].normal[0] = 1; - _varray[1].normal[1] = 1; - _varray[1].normal[2] = 1; - - _varray[1].tex[0] = 1; - _varray[1].tex[1] = 0; - - _varray[2].location[0] = 0; - _varray[2].location[1] = 1; - _varray[2].location[2] = 0; - _varray[2].location[3] = 5; - - _varray[2].normal[0] = 1; - _varray[2].normal[1] = 1; - _varray[2].normal[2] = 1; - - _varray[2].tex[0] = 0; - _varray[2].tex[1] = 1; - - _vsize = 3; - _isize = 3; - - _iarray[0] = 0; - _iarray[1] = 1; - _iarray[2] = 2; - */ } - -WavefrontGeometry::~WavefrontGeometry(){ -} - -bool WavefrontGeometry::initialize(RenderableModel* parent){ +bool WavefrontGeometry::initialize(RenderableModel* parent) { bool success = ModelGeometry::initialize(parent); - createSphere(); + PowerScaledScalar ps = PowerScaledScalar(1.0, 0.0); // will set proper bounding soon. + _parent->setBoundingSphere(ps); - if (_isize == 0) return false; + if (_vertices.empty()) + return false; glGenVertexArrays(1, &_vaoID); - glGenBuffers(1, &_vBufferID); - glGenBuffers(1, &_iBufferID); + glGenBuffers(1, &_vbo); + glGenBuffers(1, &_ibo); glBindVertexArray(_vaoID); - glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glBufferData(GL_ARRAY_BUFFER, _vsize * sizeof(Vertex), _varray, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(Vertex), _vertices.data(), GL_STATIC_DRAW); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); @@ -195,45 +122,30 @@ bool WavefrontGeometry::initialize(RenderableModel* parent){ glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast(offsetof(Vertex, normal))); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _isize * sizeof(int), _iarray, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(int), _indices.data(), GL_STATIC_DRAW); + glBindVertexArray(0); - GLint errorID = glGetError(); - if (errorID != GL_NO_ERROR) { - LERROR("OpenGL error: " << glewGetErrorString(errorID)); - return false; - } return success; } -void WavefrontGeometry::deinitialize(){ - if (_varray) - delete[] _varray; - if (_iarray) - delete[] _iarray; - - glDeleteBuffers(1, &_vBufferID); - glDeleteBuffers(1, &_iBufferID); +void WavefrontGeometry::deinitialize() { + glDeleteBuffers(1, &_vbo); glDeleteVertexArrays(1, &_vaoID); - + glDeleteBuffers(1, &_ibo); } -void WavefrontGeometry::render(){ - // render - glBindVertexArray(_vaoID); // select first VAO - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); - glDrawElements(GL_TRIANGLES, _isize, GL_UNSIGNED_INT, 0); +void WavefrontGeometry::render() { + glBindVertexArray(_vaoID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); + glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); } -void WavefrontGeometry::createSphere(){ - // create the power scaled scalar - PowerScaledScalar ps = PowerScaledScalar(1.0, 0.0); // will set proper bounding soon. - _parent->setBoundingSphere(ps); -} - bool WavefrontGeometry::loadModel(const std::string& filename) { + std::vector shapes; + std::vector materials; std::string err = tinyobj::LoadObj(shapes, materials, filename.c_str(), filename.c_str()); if (!err.empty()) { @@ -241,48 +153,43 @@ bool WavefrontGeometry::loadModel(const std::string& filename) { return false; } - LINFO("Loaded Mesh"); - LINFO("Number of Shapes: " << shapes.size()); - LINFO("Number of Materials: " << materials.size()); - for (int i = 0; i < shapes.size(); ++i) { - LINFO("Shape #" << i << ": " << - "Indices (" << shapes[i].mesh.indices.size() << ") " << - "Positions (" << shapes[i].mesh.positions.size() << ") " << - "Texture (" << shapes[i].mesh.texcoords.size() << ") " << - "Normals (" << shapes[i].mesh.normals.size() << ")"); + if (shapes.size() > 1) { + LWARNING("Loading models with more than one shape is currently untested"); } - _isize = shapes[0].mesh.indices.size(); - _vsize = shapes[0].mesh.indices.size(); // shapes[0].mesh.positions.size() + shapes[0].mesh.positions.size() / 3; - _tsize = shapes[0].mesh.texcoords.size(); + _shapeCounts.resize(shapes.size()); + for (int i = 0; i < shapes.size(); ++i) + _shapeCounts[i] = shapes[i].mesh.indices.size(); + int totalSize = std::accumulate(_shapeCounts.begin(), _shapeCounts.end(), 0); - _varray = new Vertex[_vsize]; - _iarray = new int[_isize]; + _vertices.resize(totalSize); + _indices.resize(totalSize); - //copy indices - for (int f = 0; f < shapes[0].mesh.indices.size(); f++) { - _iarray[f] = f;// shapes[0].mesh.indices[f]; - } - - //shapes[0].mesh.texcoords.resize(2 * _isize); + // We add all shapes of the model into the same vertex array, one after the other + // The _shapeCounts array stores for each shape, how many vertices that shape has int p = 0; - for (auto v : shapes[0].mesh.indices) { - _varray[p].location[0] = shapes[0].mesh.positions[3 * v + 0]; - _varray[p].location[1] = shapes[0].mesh.positions[3 * v + 1]; - _varray[p].location[2] = shapes[0].mesh.positions[3 * v + 2]; - _varray[p].location[3] = 5; + for (int i = 0; i < shapes.size(); ++i) { + for (int index : shapes[i].mesh.indices) { + _vertices[index + p].location[0] = shapes[i].mesh.positions[3 * index + 0]; + _vertices[index + p].location[1] = shapes[i].mesh.positions[3 * index + 1]; + _vertices[index + p].location[2] = shapes[i].mesh.positions[3 * index + 2]; + _vertices[index + p].location[3] = 5; - _varray[p].normal[0] = shapes[0].mesh.normals[3 * v + 0]; - _varray[p].normal[1] = shapes[0].mesh.normals[3 * v + 1]; - _varray[p].normal[2] = shapes[0].mesh.normals[3 * v + 2]; + _vertices[index + p].normal[0] = shapes[i].mesh.normals[3 * index + 0]; + _vertices[index + p].normal[1] = shapes[i].mesh.normals[3 * index + 1]; + _vertices[index + p].normal[2] = shapes[i].mesh.normals[3 * index + 2]; - // Only set the texture coordinates if they don't fall out of the value range - _varray[p].tex[0] = (2 * v + 0) < shapes[0].mesh.texcoords.size() ? shapes[0].mesh.texcoords[2 * v + 0] : 0.f; - _varray[p].tex[1] = (2 * v + 1) < shapes[0].mesh.texcoords.size() ? shapes[0].mesh.texcoords[2 * v + 1] : 0.f; - - p++; + // Only set the texture coordinates if they don't fall out of the value range + _vertices[index + p].tex[0] = (2 * index + 0) < shapes[i].mesh.texcoords.size() ? shapes[0].mesh.texcoords[2 * index + 0] : 0.f; + _vertices[index + p].tex[1] = (2 * index + 1) < shapes[i].mesh.texcoords.size() ? shapes[0].mesh.texcoords[2 * index + 1] : 0.f; + } + std::copy( + shapes[i].mesh.indices.begin(), + shapes[i].mesh.indices.end(), + _indices.begin() + p + ); + p += _shapeCounts[i]; } - p = 0; return true; } @@ -293,15 +200,10 @@ bool WavefrontGeometry::saveCachedFile(const std::string& filename) { fileStream.write(reinterpret_cast(&CurrentCacheVersion), sizeof(int8_t)); - int64_t vSize = _vsize; + int64_t vSize = _vertices.size(); fileStream.write(reinterpret_cast(&vSize), sizeof(int64_t)); - int64_t iSize = _isize; - fileStream.write(reinterpret_cast(&iSize), sizeof(int64_t)); - int64_t tSize = _tsize; - fileStream.write(reinterpret_cast(&tSize), sizeof(int64_t)); - fileStream.write(reinterpret_cast(_varray), sizeof(Vertex) * _vsize); - fileStream.write(reinterpret_cast(_iarray), sizeof(int) * _isize); + fileStream.write(reinterpret_cast(_vertices.data()), sizeof(Vertex) * vSize); return fileStream.good(); } @@ -323,19 +225,13 @@ bool WavefrontGeometry::loadCachedFile(const std::string& filename) { return false; } - int64_t vSize, iSize, tSize; + int64_t vSize, iSize; fileStream.read(reinterpret_cast(&vSize), sizeof(int64_t)); fileStream.read(reinterpret_cast(&iSize), sizeof(int64_t)); - fileStream.read(reinterpret_cast(&tSize), sizeof(int64_t)); - _vsize = vSize; - _isize = iSize; - _tsize = tSize; + + _vertices.resize(vSize); - _varray = new Vertex[vSize]; - _iarray = new int[iSize]; - - fileStream.read(reinterpret_cast(_varray), sizeof(Vertex) * vSize); - fileStream.read(reinterpret_cast(_iarray), sizeof(int) * iSize); + fileStream.read(reinterpret_cast(_vertices.data()), sizeof(Vertex) * vSize); return fileStream.good(); }