Browse Source

Merge pull request #927 from royshil/obj_color_vertices_support

adding support for per-vertex colors in OBJ files.
Kim Kulling 9 years ago
parent
commit
886cea2933
4 changed files with 63 additions and 4 deletions
  1. 4 0
      code/ObjFileData.h
  2. 11 0
      code/ObjFileImporter.cpp
  3. 44 4
      code/ObjFileParser.cpp
  4. 4 0
      code/ObjFileParser.h

+ 4 - 0
code/ObjFileData.h

@@ -240,6 +240,8 @@ struct Mesh {
     unsigned int m_uiMaterialIndex;
     /// True, if normals are stored.
     bool m_hasNormals;
+    /// True, if vertex colors are stored.
+    bool m_hasVertexColors;
 
     /// Constructor
     explicit Mesh( const std::string &name ) 
@@ -289,6 +291,8 @@ struct Model
     std::vector<aiVector3D> m_Vertices;
     //! vector with all generated normals
     std::vector<aiVector3D> m_Normals;
+    //! vector with all vertex colors
+    std::vector<aiVector3D> m_VertexColors;
     //! Group map
     GroupMap m_Groups;
     //! Group to face id assignment

+ 11 - 0
code/ObjFileImporter.cpp

@@ -416,6 +416,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
     if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals )
         pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
 
+    // Allocate buffer for vertex-color vectors
+    if ( !pModel->m_VertexColors.empty() )
+        pMesh->mColors[0] = new aiColor4D[ pMesh->mNumVertices ];
+
     // Allocate buffer for texture coordinates
     if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] )
     {
@@ -449,6 +453,13 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
                 pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ];
             }
 
+            // Copy all vertex colors
+            if ( !pModel->m_VertexColors.empty())
+            {
+                const aiVector3D color = pModel->m_VertexColors[ vertex ];
+                pMesh->mColors[0][ newIndex ] = aiColor4D(color.x, color.y, color.z, 1.0);
+            }
+
             // Copy all texture coordinates
             if ( !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_pTexturCoords->size())
             {

+ 44 - 4
code/ObjFileParser.cpp

@@ -136,8 +136,14 @@ void ObjFileParser::parseFile()
             {
                 ++m_DataIt;
                 if (*m_DataIt == ' ' || *m_DataIt == '\t') {
-                    // read in vertex definition
-                    getVector3(m_pModel->m_Vertices);
+                    size_t numComponents = getNumComponentsInLine();
+                    if (numComponents == 3) {
+                        // read in vertex definition
+                        getVector3(m_pModel->m_Vertices);
+                    } else if (numComponents == 6) {
+                        // read vertex and vertex-color
+                        getTwoVectors3(m_pModel->m_Vertices, m_pModel->m_VertexColors);
+                    }
                 } else if (*m_DataIt == 't') {
                     // read in texture coordinate ( 2D or 3D )
                                         ++m_DataIt;
@@ -257,8 +263,7 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
     pBuffer[ index ] = '\0';
 }
 
-// -------------------------------------------------------------------
-void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
+size_t ObjFileParser::getNumComponentsInLine() {
     size_t numComponents( 0 );
     const char* tmp( &m_DataIt[0] );
     while( !IsLineEnd( *tmp ) ) {
@@ -268,6 +273,12 @@ void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
         SkipToken( tmp );
         ++numComponents;
     }
+    return numComponents;
+}
+
+// -------------------------------------------------------------------
+void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
+    size_t numComponents = getNumComponentsInLine();
     float x, y, z;
     if( 2 == numComponents ) {
         copyNextWord( m_buffer, Buffersize );
@@ -309,6 +320,35 @@ void ObjFileParser::getVector3( std::vector<aiVector3D> &point3d_array ) {
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 
+// -------------------------------------------------------------------
+//  Get values for two 3D vectors on the same line
+void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b ) {
+    float x, y, z;
+    copyNextWord(m_buffer, Buffersize);
+    x = (float) fast_atof(m_buffer);
+
+    copyNextWord(m_buffer, Buffersize);
+    y = (float) fast_atof(m_buffer);
+
+    copyNextWord( m_buffer, Buffersize );
+    z = ( float ) fast_atof( m_buffer );
+
+    point3d_array_a.push_back( aiVector3D( x, y, z ) );
+
+    copyNextWord(m_buffer, Buffersize);
+    x = (float) fast_atof(m_buffer);
+
+    copyNextWord(m_buffer, Buffersize);
+    y = (float) fast_atof(m_buffer);
+
+    copyNextWord( m_buffer, Buffersize );
+    z = ( float ) fast_atof( m_buffer );
+
+    point3d_array_b.push_back( aiVector3D( x, y, z ) );
+
+    m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
+}
+
 // -------------------------------------------------------------------
 //  Get values for a new 2D vector instance
 void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {

+ 4 - 0
code/ObjFileParser.h

@@ -89,6 +89,8 @@ private:
     void getVector( std::vector<aiVector3D> &point3d_array );
     /// Stores the following 3d vector.
     void getVector3( std::vector<aiVector3D> &point3d_array );
+    /// Stores the following two 3d vectors on the line.
+    void getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b );
     /// Stores the following 3d vector.
     void getVector2(std::vector<aiVector2D> &point2d_array);
     /// Stores the following face.
@@ -119,6 +121,8 @@ private:
     bool needsNewMesh( const std::string &rMaterialName );
     /// Error report in token
     void reportErrorTokenInFace();
+    /// Get the number of components in a line.
+    size_t getNumComponentsInLine();
 
 private:
     // Copy and assignment constructor should be private