From 543bd5c0d0ce26ebbc3e30547b0cfad26ac1f04a Mon Sep 17 00:00:00 2001 From: Johannes Ebersold Date: Wed, 19 Nov 2014 13:51:22 +0100 Subject: [PATCH 01/13] ColladaParser::ReadPrimitives: rename "a" to currentPrimitive --- code/ColladaParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index dffb04c3d..693588810 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2105,7 +2105,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer pMesh->mFaceSize.reserve( numPrimitives); pMesh->mFacePosIndices.reserve( indices.size() / numOffsets); - for( size_t a = 0; a < numPrimitives; a++) + for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++) { // determine number of points for this primitive size_t numPoints = 0; @@ -2118,7 +2118,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer numPoints = 3; break; case Prim_Polylist: - numPoints = pVCount[a]; + numPoints = pVCount[currentPrimitive]; break; case Prim_TriFans: case Prim_Polygon: From 70d2c8571bb75359a1e5da2520be09fe675ccb61 Mon Sep 17 00:00:00 2001 From: Johannes Ebersold Date: Wed, 19 Nov 2014 14:04:49 +0100 Subject: [PATCH 02/13] ColladaParser::ReadPrimitives: get rid of "idx" iterator. We will be adding non-sequential access to the indices vector in one of the upcoming commits. --- code/ColladaParser.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 693588810..4a6737d9d 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2093,10 +2093,6 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource); } - - // now assemble vertex data according to those indices - std::vector::const_iterator idx = indices.begin(); - // For continued primitives, the given count does not come all in one

, but only one primitive per

size_t numPrimitives = pNumPrimitives; if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon) @@ -2140,7 +2136,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer ai_assert( numOffsets < 20 && perVertexOffset < 20); size_t vindex[20]; for( size_t offsets = 0; offsets < numOffsets; ++offsets) - vindex[offsets] = *idx++; + vindex[offsets] = indices[currentPrimitive * numOffsets * numPoints + b * numOffsets + offsets]; // extract per-vertex channels using the global per-vertex offset for( std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) From 4ef244f67231a0d220ea64c8ad355d361d7a1776 Mon Sep 17 00:00:00 2001 From: Johannes Ebersold Date: Wed, 19 Nov 2014 14:10:16 +0100 Subject: [PATCH 03/13] Extract function ColladaParser::CopyPrimitive --- code/ColladaParser.cpp | 39 ++++++++++++++++++++++++--------------- code/ColladaParser.h | 5 +++++ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 4a6737d9d..780da154d 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2132,21 +2132,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer // gather that number of vertices for( size_t b = 0; b < numPoints; b++) { - // read all indices for this vertex. Yes, in a hacky local array - ai_assert( numOffsets < 20 && perVertexOffset < 20); - size_t vindex[20]; - for( size_t offsets = 0; offsets < numOffsets; ++offsets) - vindex[offsets] = indices[currentPrimitive * numOffsets * numPoints + b * numOffsets + offsets]; - - // extract per-vertex channels using the global per-vertex offset - for( std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) - ExtractDataObjectFromChannel( *it, vindex[perVertexOffset], pMesh); - // and extract per-index channels using there specified offset - for( std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) - ExtractDataObjectFromChannel( *it, vindex[it->mOffset], pMesh); - - // store the vertex-data index for later assignment of bone vertex weights - pMesh->mFacePosIndices.push_back( vindex[perVertexOffset]); + CopyPrimitive(b, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); } } @@ -2155,6 +2141,29 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer TestClosing( "p"); } +void ColladaParser::CopyPrimitive(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ + // don't overrun the boundaries of the index list + size_t maxIndexRequested = currentPrimitive * numOffsets * numPoints + (currentVertex + 1) * numOffsets - 1; + ai_assert(maxIndexRequested < indices.size()); + + // read all indices for this vertex. Yes, in a hacky local array + ai_assert(numOffsets < 20 && perVertexOffset < 20); + size_t vindex[20]; + + for (size_t offsets = 0; offsets < numOffsets; ++offsets) + vindex[offsets] = indices[currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets + offsets]; + + // extract per-vertex channels using the global per-vertex offset + for (std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) + ExtractDataObjectFromChannel(*it, vindex[perVertexOffset], pMesh); + // and extract per-index channels using there specified offset + for (std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) + ExtractDataObjectFromChannel(*it, vindex[it->mOffset], pMesh); + + // store the vertex-data index for later assignment of bone vertex weights + pMesh->mFacePosIndices.push_back(vindex[perVertexOffset]); +} + // ------------------------------------------------------------------------------------------------ // Extracts a single object from an input channel and stores it in the appropriate mesh data array void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, size_t pLocalIndex, Mesh* pMesh) diff --git a/code/ColladaParser.h b/code/ColladaParser.h index c19a5e100..b93cf9145 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -180,6 +180,11 @@ protected: void ReadPrimitives( Collada::Mesh* pMesh, std::vector& pPerIndexChannels, size_t pNumPrimitives, const std::vector& pVCount, Collada::PrimitiveType pPrimType); + /** Copies the data for a single primitive into the mesh, based on the InputChannels */ + void CopyPrimitive(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, + Collada::Mesh* pMesh, std::vector& pPerIndexChannels, + size_t currentPrimitive, const std::vector& indices); + /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); From 7c4bf383d7cfd75f6bdb4bd7e7e618a5dd4501be Mon Sep 17 00:00:00 2001 From: Johannes Ebersold Date: Wed, 19 Nov 2014 14:16:10 +0100 Subject: [PATCH 04/13] Move vertex copy operation into switch statement. We will be adding special handling for Tristrips in an upcoming commit, which unfortunately doesn't map to a common copy loop as it is. --- code/ColladaParser.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 780da154d..d92e5fc51 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2109,16 +2109,24 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer { case Prim_Lines: numPoints = 2; + for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) + CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; case Prim_Triangles: numPoints = 3; + for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) + CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; case Prim_Polylist: numPoints = pVCount[currentPrimitive]; + for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) + CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; case Prim_TriFans: case Prim_Polygon: numPoints = indices.size() / numOffsets; + for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) + CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; default: // LineStrip and TriStrip not supported due to expected index unmangling @@ -2128,12 +2136,6 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer // store the face size to later reconstruct the face from pMesh->mFaceSize.push_back( numPoints); - - // gather that number of vertices - for( size_t b = 0; b < numPoints; b++) - { - CopyPrimitive(b, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); - } } From 0f40dcca7eca46e4e4c69acc75b3c80d5f91b9dd Mon Sep 17 00:00:00 2001 From: Johannes Ebersold Date: Wed, 19 Nov 2014 14:26:54 +0100 Subject: [PATCH 05/13] Add calculation for nuber of Primitives for TriStrips --- code/ColladaParser.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index d92e5fc51..2cdebef21 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2097,6 +2097,11 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer size_t numPrimitives = pNumPrimitives; if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon) numPrimitives = 1; + // For continued primitives, the given count is actually the number of

's inside the parent tag + if ( pPrimType == Prim_TriStrips){ + size_t numberOfVertices = indices.size() / numOffsets; + numPrimitives = numberOfVertices - 2; + } pMesh->mFaceSize.reserve( numPrimitives); pMesh->mFacePosIndices.reserve( indices.size() / numOffsets); From 593484829b6c57c0b8c24a21ec91bed28d23e4aa Mon Sep 17 00:00:00 2001 From: Johannes Ebersold Date: Wed, 19 Nov 2014 14:30:18 +0100 Subject: [PATCH 06/13] Add Function ColladaParser::ReadPrimTriStrips. This does the index mangling for reading tristrips. --- code/ColladaParser.cpp | 20 +++++++++++++++++++- code/ColladaParser.h | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 2cdebef21..5268255eb 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2122,6 +2122,10 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; + case Prim_TriStrips: + numPoints = 3; + ReadPrimTriStrips(numOffsets, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + break; case Prim_Polylist: numPoints = pVCount[currentPrimitive]; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) @@ -2134,7 +2138,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; default: - // LineStrip and TriStrip not supported due to expected index unmangling + // LineStrip is not supported due to expected index unmangling ThrowException( "Unsupported primitive type."); break; } @@ -2171,6 +2175,20 @@ void ColladaParser::CopyPrimitive(size_t currentVertex, size_t numOffsets, size_ pMesh->mFacePosIndices.push_back(vindex[perVertexOffset]); } +void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ + if (currentPrimitive % 2 != 0){ + //odd tristrip triangles need their indices mangled, to preserve winding direction + CopyPrimitive(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyPrimitive(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyPrimitive(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + } + else {//for non tristrips or even tristrip triangles + CopyPrimitive(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyPrimitive(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyPrimitive(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + } +} + // ------------------------------------------------------------------------------------------------ // Extracts a single object from an input channel and stores it in the appropriate mesh data array void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, size_t pLocalIndex, Mesh* pMesh) diff --git a/code/ColladaParser.h b/code/ColladaParser.h index b93cf9145..9f0963345 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -185,6 +185,10 @@ protected: Collada::Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices); + /** Reads one triangle of a tristrip into the mesh */ + void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh, + std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices); + /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); From 72f67ea0cdb4d55c48eea7a9b1bd39527671fae0 Mon Sep 17 00:00:00 2001 From: Johannes Ebersold Date: Wed, 19 Nov 2014 14:32:01 +0100 Subject: [PATCH 07/13] Whitespace changes --- code/ColladaParser.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 5268255eb..b6fd73dfa 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -1868,7 +1868,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh) int attrCount = GetAttribute( "count"); size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount); - // material subgroup + // material subgroup int attrMaterial = TestAttribute( "material"); SubMesh subgroup; if( attrMaterial > -1) @@ -2113,12 +2113,12 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer switch( pPrimType) { case Prim_Lines: - numPoints = 2; + numPoints = 2; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; - case Prim_Triangles: - numPoints = 3; + case Prim_Triangles: + numPoints = 3; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; @@ -2133,7 +2133,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer break; case Prim_TriFans: case Prim_Polygon: - numPoints = indices.size() / numOffsets; + numPoints = indices.size() / numOffsets; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; @@ -2147,7 +2147,6 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer pMesh->mFaceSize.push_back( numPoints); } - // if I ever get my hands on that guy who invented this steaming pile of indirection... TestClosing( "p"); } From e568c2df9dbfe82355d5d61642be7b7a96e1cb89 Mon Sep 17 00:00:00 2001 From: Johannes Ebersold Date: Wed, 19 Nov 2014 14:38:03 +0100 Subject: [PATCH 08/13] ColladaParser::ReadIndexData: don't rely on the specified number of primitives. Especially TriStrips don't specify triangle count upfront, so one needs to sum up the count of triangles read from all

tags in a tristrip collection. --- code/ColladaParser.cpp | 18 ++++++++++++++---- code/ColladaParser.h | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index b6fd73dfa..b199ccc52 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -1867,14 +1867,15 @@ void ColladaParser::ReadIndexData( Mesh* pMesh) // read primitive count from the attribute int attrCount = GetAttribute( "count"); size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount); + // some mesh types (e.g. tristrips) don't specify primitive count upfront, + // so we need to sum up the actual number of primitives while we read the

-tags + size_t actualPrimitives = 0; // material subgroup int attrMaterial = TestAttribute( "material"); SubMesh subgroup; if( attrMaterial > -1) subgroup.mMaterial = mReader->getAttributeValue( attrMaterial); - subgroup.mNumFaces = numPrimitives; - pMesh->mSubMeshes.push_back( subgroup); // distinguish between polys and triangles std::string elementName = mReader->getNodeName(); @@ -1933,7 +1934,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh) if( !mReader->isEmptyElement()) { // now here the actual fun starts - these are the indices to construct the mesh data from - ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, primType); + actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType); } } else { @@ -1948,6 +1949,14 @@ void ColladaParser::ReadIndexData( Mesh* pMesh) break; } } + + // small sanity check + if (primType != Prim_TriFans && primType != Prim_TriStrips) + ai_assert(actualPrimitives == numPrimitives); + + // only when we're done reading all

tags (and thus know the final vertex count) can we commit the submesh + subgroup.mNumFaces = actualPrimitives; + pMesh->mSubMeshes.push_back(subgroup); } // ------------------------------------------------------------------------------------------------ @@ -1995,7 +2004,7 @@ void ColladaParser::ReadInputChannel( std::vector& poChannels) // ------------------------------------------------------------------------------------------------ // Reads a

primitive index list and assembles the mesh data into the given mesh -void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPerIndexChannels, +size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPerIndexChannels, size_t pNumPrimitives, const std::vector& pVCount, PrimitiveType pPrimType) { // determine number of indices coming per vertex @@ -2149,6 +2158,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pPer // if I ever get my hands on that guy who invented this steaming pile of indirection... TestClosing( "p"); + return numPrimitives; } void ColladaParser::CopyPrimitive(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ diff --git a/code/ColladaParser.h b/code/ColladaParser.h index 9f0963345..931f16ca0 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -177,7 +177,7 @@ protected: void ReadInputChannel( std::vector& poChannels); /** Reads a

primitive index list and assembles the mesh data into the given mesh */ - void ReadPrimitives( Collada::Mesh* pMesh, std::vector& pPerIndexChannels, + size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector& pPerIndexChannels, size_t pNumPrimitives, const std::vector& pVCount, Collada::PrimitiveType pPrimType); /** Copies the data for a single primitive into the mesh, based on the InputChannels */ From 13a157ea6650ec29223d8361e0bd4ed0100cdd54 Mon Sep 17 00:00:00 2001 From: Wolfgang Herget Date: Thu, 20 Nov 2014 13:10:15 +0100 Subject: [PATCH 09/13] For Polylists, manually compute the start offset outside CopyPrimitive. --- code/ColladaParser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index b199ccc52..eb40d9d31 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2115,6 +2115,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP pMesh->mFaceSize.reserve( numPrimitives); pMesh->mFacePosIndices.reserve( indices.size() / numOffsets); + size_t polylistStartVertex = 0; for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++) { // determine number of points for this primitive @@ -2138,7 +2139,8 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP case Prim_Polylist: numPoints = pVCount[currentPrimitive]; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) - CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyPrimitive(polylistStartVertex + currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, 0, indices); + polylistStartVertex += numPoints; break; case Prim_TriFans: case Prim_Polygon: From ca3ce4703d229ea394033e96b0295ef651b4349b Mon Sep 17 00:00:00 2001 From: Wolfgang Herget Date: Thu, 20 Nov 2014 13:12:09 +0100 Subject: [PATCH 10/13] Rename ColladaParser::CopyPrimitive to ::CopyVertex. That's a bit closer to what the function actually does. --- code/ColladaParser.cpp | 22 +++++++++++----------- code/ColladaParser.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index eb40d9d31..3d63168b8 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2125,12 +2125,12 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP case Prim_Lines: numPoints = 2; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) - CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; case Prim_Triangles: numPoints = 3; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) - CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; case Prim_TriStrips: numPoints = 3; @@ -2139,14 +2139,14 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP case Prim_Polylist: numPoints = pVCount[currentPrimitive]; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) - CopyPrimitive(polylistStartVertex + currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, 0, indices); + CopyVertex(polylistStartVertex + currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, 0, indices); polylistStartVertex += numPoints; break; case Prim_TriFans: case Prim_Polygon: numPoints = indices.size() / numOffsets; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) - CopyPrimitive(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; default: // LineStrip is not supported due to expected index unmangling @@ -2163,7 +2163,7 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP return numPrimitives; } -void ColladaParser::CopyPrimitive(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ +void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ // don't overrun the boundaries of the index list size_t maxIndexRequested = currentPrimitive * numOffsets * numPoints + (currentVertex + 1) * numOffsets - 1; ai_assert(maxIndexRequested < indices.size()); @@ -2189,14 +2189,14 @@ void ColladaParser::CopyPrimitive(size_t currentVertex, size_t numOffsets, size_ void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ if (currentPrimitive % 2 != 0){ //odd tristrip triangles need their indices mangled, to preserve winding direction - CopyPrimitive(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); - CopyPrimitive(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); - CopyPrimitive(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); } else {//for non tristrips or even tristrip triangles - CopyPrimitive(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); - CopyPrimitive(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); - CopyPrimitive(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); } } diff --git a/code/ColladaParser.h b/code/ColladaParser.h index 931f16ca0..561ff05b3 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -181,7 +181,7 @@ protected: size_t pNumPrimitives, const std::vector& pVCount, Collada::PrimitiveType pPrimType); /** Copies the data for a single primitive into the mesh, based on the InputChannels */ - void CopyPrimitive(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, + void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Collada::Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices); From 8dead93504362b4b975d69bf1741a5e1356f98dd Mon Sep 17 00:00:00 2001 From: Wolfgang Herget Date: Thu, 20 Nov 2014 16:42:41 +0100 Subject: [PATCH 11/13] ColladaParser: don't arbitrarily limit number of per-vertex attributes. --- code/ColladaParser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 3d63168b8..dc44d826f 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2168,9 +2168,9 @@ void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t n size_t maxIndexRequested = currentPrimitive * numOffsets * numPoints + (currentVertex + 1) * numOffsets - 1; ai_assert(maxIndexRequested < indices.size()); - // read all indices for this vertex. Yes, in a hacky local array - ai_assert(numOffsets < 20 && perVertexOffset < 20); - size_t vindex[20]; + // copy the indices pertaining to this vertex + std::vector vindex; + vindex.reserve(numOffsets); for (size_t offsets = 0; offsets < numOffsets; ++offsets) vindex[offsets] = indices[currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets + offsets]; From c08a5581ddabac0a78fb02d81c4ed4e549775ef6 Mon Sep 17 00:00:00 2001 From: Wolfgang Herget Date: Thu, 20 Nov 2014 17:53:06 +0100 Subject: [PATCH 12/13] ColladaParser::CopyVertex: don't make a local copy of the vertex' indices. Instead, we address the relevant indices in the main vector directly by adding the input offsets to the per-vertex base offset. --- code/ColladaParser.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index dc44d826f..9e68c9332 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -2164,26 +2164,22 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP } void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ + // calculate the base offset of the vertex whose attributes we ant to copy + size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets; + // don't overrun the boundaries of the index list - size_t maxIndexRequested = currentPrimitive * numOffsets * numPoints + (currentVertex + 1) * numOffsets - 1; + size_t maxIndexRequested = baseOffset + numOffsets - 1; ai_assert(maxIndexRequested < indices.size()); - // copy the indices pertaining to this vertex - std::vector vindex; - vindex.reserve(numOffsets); - - for (size_t offsets = 0; offsets < numOffsets; ++offsets) - vindex[offsets] = indices[currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets + offsets]; - // extract per-vertex channels using the global per-vertex offset for (std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) - ExtractDataObjectFromChannel(*it, vindex[perVertexOffset], pMesh); + ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh); // and extract per-index channels using there specified offset for (std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) - ExtractDataObjectFromChannel(*it, vindex[it->mOffset], pMesh); + ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh); // store the vertex-data index for later assignment of bone vertex weights - pMesh->mFacePosIndices.push_back(vindex[perVertexOffset]); + pMesh->mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]); } void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ From 926b7e98cc0abb09b5519cab840025aca92b82cc Mon Sep 17 00:00:00 2001 From: Wolfgang Herget Date: Mon, 1 Dec 2014 18:08:21 +0100 Subject: [PATCH 13/13] Tristripped version of cube.dae generated using openscenegraph. Command line used: OSG_OPTIMIZER="TRISTRIP_GEOMETRY" osgconv cube.dae cube_tristrips.dae --- test/models/Collada/cube_tristrips.dae | 167 +++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 test/models/Collada/cube_tristrips.dae diff --git a/test/models/Collada/cube_tristrips.dae b/test/models/Collada/cube_tristrips.dae new file mode 100644 index 000000000..83909045a --- /dev/null +++ b/test/models/Collada/cube_tristrips.dae @@ -0,0 +1,167 @@ + + + + + 2014-12-01T18:05:27Z + 2014-12-01T18:05:27Z + + Z_UP + + + + + + 1 0 0 90 + + 0.838671 0.205746 -0.504282 -427.749 0 0.925901 0.377766 333.855 0.544639 -0.316822 0.776526 655.017 0 0 0 1 + + + + 1 0 0 -500 0 1 0 1000 0 0 1 400 0 0 0 1 + + + + 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 + + + + + + + + + + 0.838671 0.205746 -0.504282 -427.749 0 0.925901 0.377766 333.855 0.544639 -0.316822 0.776526 655.017 0 0 0 1 + + + + 1 0 0 3 0 1 0 4 0 0 1 10 0 0 0 1 + + + + + + + + + + + + 37.8493 + 1 + 1 + 1000 + + + + + + + + + 37.8501 + 1 + 1 + 1000 + + + + + + + + + + + 1 1 1 + 1 + 0 + 0 + + + + + + + + 1 1 1 + 1 + 0 + 0 + + + + + + + + + -50 50 50 -50 50 50 -50 50 50 50 50 50 50 50 50 50 50 50 -50 -50 50 -50 -50 50 -50 -50 50 50 -50 50 50 -50 50 50 -50 50 -50 50 -50 -50 50 -50 -50 50 -50 50 50 -50 50 50 -50 50 50 -50 -50 -50 -50 -50 -50 -50 -50 -50 -50 50 -50 -50 50 -50 -50 50 -50 -50 + + + + + + + + + + 0 0 1 0 1 0 -1 0 0 0 0 1 0 1 0 1 0 0 0 0 1 0 -1 0 -1 0 0 0 0 1 0 -1 0 1 0 0 0 1 0 -1 0 0 0 0 -1 0 1 0 1 0 0 0 0 -1 0 -1 0 -1 0 0 0 0 -1 0 -1 0 1 0 0 0 0 -1 + + + + + + + + + + + + + + +

6 6 9 9 0 0 3 3

+

12 12 1 1 15 15 4 4

+

14 14 17 17 20 20 23 23

+

5 5 11 11 16 16 22 22

+

13 13 19 19 2 2 8 8

+

21 21 10 10 18 18 7 7

+ + + + + + + + + + + + + + + + 0 0 0 1 + + + 0 0 0 1 + + + 0.137255 0.403922 0.870588 1 + + + 0.5 0.5 0.5 1 + + + 16 + + + + + + + + + +