Merge pull request #414 from l337r007/collada-tristrips
Collada: tristrip support: helps a lot :-). Thanks for that!pull/427/head
commit
bc0fd00e96
|
@ -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 <p>-tags
|
||||
size_t actualPrimitives = 0;
|
||||
|
||||
// material subgroup
|
||||
// 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 <p> 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<InputChannel>& poChannels)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Reads a <p> primitive index list and assembles the mesh data into the given mesh
|
||||
void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels,
|
||||
size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels,
|
||||
size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType)
|
||||
{
|
||||
// determine number of indices coming per vertex
|
||||
|
@ -2093,70 +2102,98 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
|
|||
acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
|
||||
}
|
||||
|
||||
|
||||
// now assemble vertex data according to those indices
|
||||
std::vector<size_t>::const_iterator idx = indices.begin();
|
||||
|
||||
// For continued primitives, the given count does not come all in one <p>, but only one primitive per <p>
|
||||
size_t numPrimitives = pNumPrimitives;
|
||||
if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon)
|
||||
numPrimitives = 1;
|
||||
// For continued primitives, the given count is actually the number of <p>'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);
|
||||
|
||||
for( size_t a = 0; a < numPrimitives; a++)
|
||||
size_t polylistStartVertex = 0;
|
||||
for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++)
|
||||
{
|
||||
// determine number of points for this primitive
|
||||
size_t numPoints = 0;
|
||||
switch( pPrimType)
|
||||
{
|
||||
case Prim_Lines:
|
||||
numPoints = 2;
|
||||
numPoints = 2;
|
||||
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
|
||||
CopyVertex(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++)
|
||||
CopyVertex(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[a];
|
||||
numPoints = pVCount[currentPrimitive];
|
||||
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
|
||||
CopyVertex(polylistStartVertex + currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, 0, indices);
|
||||
polylistStartVertex += numPoints;
|
||||
break;
|
||||
case Prim_TriFans:
|
||||
case Prim_Polygon:
|
||||
numPoints = indices.size() / numOffsets;
|
||||
numPoints = indices.size() / numOffsets;
|
||||
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
|
||||
CopyVertex(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;
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
// 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] = *idx++;
|
||||
|
||||
// extract per-vertex channels using the global per-vertex offset
|
||||
for( std::vector<InputChannel>::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<InputChannel>::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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if I ever get my hands on that guy who invented this steaming pile of indirection...
|
||||
TestClosing( "p");
|
||||
return numPrimitives;
|
||||
}
|
||||
|
||||
void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& 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 = baseOffset + numOffsets - 1;
|
||||
ai_assert(maxIndexRequested < indices.size());
|
||||
|
||||
// extract per-vertex channels using the global per-vertex offset
|
||||
for (std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
|
||||
ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh);
|
||||
// and extract per-index channels using there specified offset
|
||||
for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
|
||||
ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh);
|
||||
|
||||
// store the vertex-data index for later assignment of bone vertex weights
|
||||
pMesh->mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]);
|
||||
}
|
||||
|
||||
void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices){
|
||||
if (currentPrimitive % 2 != 0){
|
||||
//odd tristrip triangles need their indices mangled, to preserve winding direction
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -177,9 +177,18 @@ protected:
|
|||
void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
|
||||
|
||||
/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
|
||||
void ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
|
||||
size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
|
||||
size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
|
||||
|
||||
/** Copies the data for a single primitive into the mesh, based on the InputChannels */
|
||||
void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
|
||||
Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
|
||||
size_t currentPrimitive, const std::vector<size_t>& indices);
|
||||
|
||||
/** Reads one triangle of a tristrip into the mesh */
|
||||
void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh,
|
||||
std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& 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);
|
||||
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
|
||||
<asset>
|
||||
<contributor/>
|
||||
<created>2014-12-01T18:05:27Z</created>
|
||||
<modified>2014-12-01T18:05:27Z</modified>
|
||||
<unit/>
|
||||
<up_axis>Z_UP</up_axis>
|
||||
</asset>
|
||||
<library_visual_scenes>
|
||||
<visual_scene id="defaultScene">
|
||||
<node id="sceneRoot">
|
||||
<node id="Collada visual scene group">
|
||||
<rotate sid="rotate">1 0 0 90</rotate>
|
||||
<node id="Camera">
|
||||
<matrix sid="Camera_matrix">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</matrix>
|
||||
<instance_camera url="#PerspCamera"/>
|
||||
</node>
|
||||
<node id="Light">
|
||||
<matrix sid="Light_matrix">1 0 0 -500 0 1 0 1000 0 0 1 400 0 0 0 1</matrix>
|
||||
<instance_light url="#light"/>
|
||||
</node>
|
||||
<node id="Box">
|
||||
<matrix sid="Box_matrix">1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1</matrix>
|
||||
<instance_geometry url="#BlueSG">
|
||||
<bind_material>
|
||||
<technique_common>
|
||||
<instance_material symbol="BlueSG_material" target="#material"/>
|
||||
</technique_common>
|
||||
</bind_material>
|
||||
</instance_geometry>
|
||||
</node>
|
||||
<node id="testCamera">
|
||||
<matrix sid="testCamera_matrix">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</matrix>
|
||||
<instance_camera url="#testCameraShape"/>
|
||||
</node>
|
||||
<node id="pointLight1">
|
||||
<matrix sid="pointLight1_matrix">1 0 0 3 0 1 0 4 0 0 1 10 0 0 0 1</matrix>
|
||||
<instance_light url="#pointLightShape1"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</visual_scene>
|
||||
</library_visual_scenes>
|
||||
<library_cameras>
|
||||
<camera id="PerspCamera">
|
||||
<optics>
|
||||
<technique_common>
|
||||
<perspective>
|
||||
<yfov>37.8493</yfov>
|
||||
<aspect_ratio>1</aspect_ratio>
|
||||
<znear>1</znear>
|
||||
<zfar>1000</zfar>
|
||||
</perspective>
|
||||
</technique_common>
|
||||
</optics>
|
||||
</camera>
|
||||
<camera id="testCameraShape">
|
||||
<optics>
|
||||
<technique_common>
|
||||
<perspective>
|
||||
<yfov>37.8501</yfov>
|
||||
<aspect_ratio>1</aspect_ratio>
|
||||
<znear>1</znear>
|
||||
<zfar>1000</zfar>
|
||||
</perspective>
|
||||
</technique_common>
|
||||
</optics>
|
||||
</camera>
|
||||
</library_cameras>
|
||||
<library_lights>
|
||||
<light id="light"/>
|
||||
<light id="light">
|
||||
<technique_common>
|
||||
<point>
|
||||
<color>1 1 1</color>
|
||||
<constant_attenuation>1</constant_attenuation>
|
||||
<linear_attenuation>0</linear_attenuation>
|
||||
<quadratic_attenuation>0</quadratic_attenuation>
|
||||
</point>
|
||||
</technique_common>
|
||||
</light>
|
||||
<light id="pointLightShape1"/>
|
||||
<light id="pointLightShape1">
|
||||
<technique_common>
|
||||
<point>
|
||||
<color>1 1 1</color>
|
||||
<constant_attenuation>1</constant_attenuation>
|
||||
<linear_attenuation>0</linear_attenuation>
|
||||
<quadratic_attenuation>0</quadratic_attenuation>
|
||||
</point>
|
||||
</technique_common>
|
||||
</light>
|
||||
</library_lights>
|
||||
<library_geometries>
|
||||
<geometry id="BlueSG">
|
||||
<mesh>
|
||||
<source id="BlueSG-positions">
|
||||
<float_array id="BlueSG-positions-array" count="72">-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</float_array>
|
||||
<technique_common>
|
||||
<accessor count="24" source="#BlueSG-positions-array" stride="3">
|
||||
<param name="X" type="float"/>
|
||||
<param name="Y" type="float"/>
|
||||
<param name="Z" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<source id="BlueSG-normals">
|
||||
<float_array id="BlueSG-normals-array" count="72">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</float_array>
|
||||
<technique_common>
|
||||
<accessor count="24" source="#BlueSG-normals-array" stride="3">
|
||||
<param name="X" type="float"/>
|
||||
<param name="Y" type="float"/>
|
||||
<param name="Z" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
<vertices id="BlueSG-vertices">
|
||||
<input semantic="POSITION" source="#BlueSG-positions"/>
|
||||
</vertices>
|
||||
<tristrips count="6" material="BlueSG_material">
|
||||
<input offset="0" semantic="VERTEX" source="#BlueSG-vertices" set="0"/>
|
||||
<input offset="1" semantic="NORMAL" source="#BlueSG-normals" set="0"/>
|
||||
<p>6 6 9 9 0 0 3 3</p>
|
||||
<p>12 12 1 1 15 15 4 4</p>
|
||||
<p>14 14 17 17 20 20 23 23</p>
|
||||
<p>5 5 11 11 16 16 22 22</p>
|
||||
<p>13 13 19 19 2 2 8 8</p>
|
||||
<p>21 21 10 10 18 18 7 7</p>
|
||||
</tristrips>
|
||||
</mesh>
|
||||
</geometry>
|
||||
</library_geometries>
|
||||
<library_materials>
|
||||
<material id="material">
|
||||
<instance_effect url="#material_effect"/>
|
||||
</material>
|
||||
</library_materials>
|
||||
<library_effects>
|
||||
<effect id="material_effect">
|
||||
<profile_COMMON>
|
||||
<technique sid="t0">
|
||||
<phong>
|
||||
<emission>
|
||||
<color>0 0 0 1</color>
|
||||
</emission>
|
||||
<ambient>
|
||||
<color>0 0 0 1</color>
|
||||
</ambient>
|
||||
<diffuse>
|
||||
<color>0.137255 0.403922 0.870588 1</color>
|
||||
</diffuse>
|
||||
<specular>
|
||||
<color>0.5 0.5 0.5 1</color>
|
||||
</specular>
|
||||
<shininess>
|
||||
<float>16</float>
|
||||
</shininess>
|
||||
</phong>
|
||||
</technique>
|
||||
</profile_COMMON>
|
||||
</effect>
|
||||
</library_effects>
|
||||
<scene>
|
||||
<instance_visual_scene url="#defaultScene"/>
|
||||
</scene>
|
||||
</COLLADA>
|
Loading…
Reference in New Issue