//----------------------------------------------------------------------------- // Copyright (c) 2007 dhpoware. All Rights Reserved. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #ifndef _OBJMODEL_H #define _OBJMODEL_H #include #include #include //----------------------------------------------------------------------------- // Alias|Wavefront OBJ file loader. // // This OBJ file loader contains the following restrictions: // 1. Group information is ignored. Faces are grouped based on the material // that each face uses. // 2. Object information is ignored. This loader will merge everything into a // single object. // 3. The MTL file must be located in the same directory as the OBJ file. If // it isn't then the MTL file will fail to load and a default material is // used instead. // 4. This loader triangulates all polygonal faces during importing. //----------------------------------------------------------------------------- namespace Engine { class OBJModel { public: struct Material { float ambient[4]; float diffuse[4]; float specular[4]; float shininess; // [0 = min shininess, 1 = max shininess] float alpha; // [0 = fully transparent, 1 = fully opaque] std::string name; std::string colorMapFilename; std::string bumpMapFilename; }; struct Vertex { float position[3]; float texCoord[2]; float normal[3]; float tangent[4]; float bitangent[3]; }; struct Mesh { int startIndex; int triangleCount; const Material *pMaterial; }; OBJModel(); ~OBJModel(); void destroy(); bool import(const char *pszFilename, bool rebuildNormals = false); void normalize(float scaleTo = 1.0f, bool center = true); void reverseWinding(); // Getter methods. void getCenter(float &x, float &y, float &z) const; float getWidth() const; float getHeight() const; float getLength() const; float getRadius() const; const int *getIndexBuffer() const; int getIndexSize() const; const Material &getMaterial(int i) const; const Mesh &getMesh(int i) const; int getNumberOfIndices() const; int getNumberOfMaterials() const; int getNumberOfMeshes() const; int getNumberOfTriangles() const; int getNumberOfVertices() const; const std::string &getPath() const; const Vertex &getVertex(int i) const; const Vertex *getVertexBuffer() const; int getVertexSize() const; bool hasNormals() const; bool hasPositions() const; bool hasTangents() const; bool hasTextureCoords() const; private: void addTrianglePos(int index, int material, int v0, int v1, int v2); void addTrianglePosNormal(int index, int material, int v0, int v1, int v2, int vn0, int vn1, int vn2); void addTrianglePosTexCoord(int index, int material, int v0, int v1, int v2, int vt0, int vt1, int vt2); void addTrianglePosTexCoordNormal(int index, int material, int v0, int v1, int v2, int vt0, int vt1, int vt2, int vn0, int vn1, int vn2); int addVertex(int hash, const Vertex *pVertex); void bounds(float center[3], float &width, float &height, float &length, float &radius) const; void buildMeshes(); void generateNormals(); void generateTangents(); void importGeometryFirstPass(FILE *pFile); void importGeometrySecondPass(FILE *pFile); bool importMaterials(const char *pszFilename); void scale(float scaleFactor, float offset[3]); bool m_hasPositions; bool m_hasTextureCoords; bool m_hasNormals; bool m_hasTangents; int m_numberOfVertexCoords; int m_numberOfTextureCoords; int m_numberOfNormals; int m_numberOfTriangles; int m_numberOfMaterials; int m_numberOfMeshes; float m_center[3]; float m_width; float m_height; float m_length; float m_radius; std::string m_directoryPath; std::vector m_meshes; std::vector m_materials; std::vector m_vertexBuffer; std::vector m_indexBuffer; std::vector m_attributeBuffer; std::vector m_vertexCoords; std::vector m_textureCoords; std::vector m_normals; std::map m_materialCache; std::map > m_vertexCache; }; //----------------------------------------------------------------------------- inline void OBJModel::getCenter(float &x, float &y, float &z) const { x = m_center[0]; y = m_center[1]; z = m_center[2]; } inline float OBJModel::getWidth() const { return m_width; } inline float OBJModel::getHeight() const { return m_height; } inline float OBJModel::getLength() const { return m_length; } inline float OBJModel::getRadius() const { return m_radius; } inline const int *OBJModel::getIndexBuffer() const { return &m_indexBuffer[0]; } inline int OBJModel::getIndexSize() const { return static_cast(sizeof(int)); } inline const OBJModel::Material &OBJModel::getMaterial(int i) const { return m_materials[i]; } inline const OBJModel::Mesh &OBJModel::getMesh(int i) const { return m_meshes[i]; } inline int OBJModel::getNumberOfIndices() const { return m_numberOfTriangles * 3; } inline int OBJModel::getNumberOfMaterials() const { return m_numberOfMaterials; } inline int OBJModel::getNumberOfMeshes() const { return m_numberOfMeshes; } inline int OBJModel::getNumberOfTriangles() const { return m_numberOfTriangles; } inline int OBJModel::getNumberOfVertices() const { return static_cast(m_vertexBuffer.size()); } inline const std::string &OBJModel::getPath() const { return m_directoryPath; } inline const OBJModel::Vertex &OBJModel::getVertex(int i) const { return m_vertexBuffer[i]; } inline const OBJModel::Vertex *OBJModel::getVertexBuffer() const { return &m_vertexBuffer[0]; } inline int OBJModel::getVertexSize() const { return static_cast(sizeof(Vertex)); } inline bool OBJModel::hasNormals() const { return m_hasNormals; } inline bool OBJModel::hasPositions() const { return m_hasPositions; } inline bool OBJModel::hasTangents() const { return m_hasTangents; } inline bool OBJModel::hasTextureCoords() const { return m_hasTextureCoords; } } #endif