- Bugfix: ColladaLoader node rotation was miscalculated
- ColladaLoader now supports more primitive types - ColladaLoader now honours the up-vector specification - moved Collada temporary structures to separate Helper header - fast_atof_move() now also eats localized numbers with comma separator (e.g. 0,3210) correctly git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@251 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
edc8eda808
commit
85a487f6b8
|
@ -0,0 +1,172 @@
|
|||
/** Helper structures for the Collada loader */
|
||||
|
||||
/*
|
||||
Open Asset Import Library (ASSIMP)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006-2008, ASSIMP Development Team
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms,
|
||||
with or without modification, are permitted provided that the
|
||||
following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of the ASSIMP team, nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of the ASSIMP Development Team.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef AI_COLLADAHELPER_H_INC
|
||||
#define AI_COLLADAHELPER_H_INC
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
namespace Collada
|
||||
{
|
||||
|
||||
/** Transformation types that can be applied to a node */
|
||||
enum TransformType
|
||||
{
|
||||
TF_LOOKAT,
|
||||
TF_ROTATE,
|
||||
TF_TRANSLATE,
|
||||
TF_SCALE,
|
||||
TF_SKEW,
|
||||
TF_MATRIX
|
||||
};
|
||||
|
||||
/** Contains all data for one of the different transformation types */
|
||||
struct Transform
|
||||
{
|
||||
TransformType mType;
|
||||
float f[16]; ///< Interpretation of data depends on the type of the transformation
|
||||
};
|
||||
|
||||
/** A node in a scene hierarchy */
|
||||
struct Node
|
||||
{
|
||||
std::string mName;
|
||||
std::string mID;
|
||||
Node* mParent;
|
||||
std::vector<Node*> mChildren;
|
||||
|
||||
/** Operations in order to calculate the resulting transformation to parent. */
|
||||
std::vector<Transform> mTransforms;
|
||||
|
||||
std::vector<std::string> mMeshes; ///< Meshes at this node
|
||||
|
||||
Node() { mParent = NULL; }
|
||||
~Node() { for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) delete *it; }
|
||||
};
|
||||
|
||||
/** Data source array */
|
||||
struct Data
|
||||
{
|
||||
std::vector<float> mValues;
|
||||
};
|
||||
|
||||
/** Accessor to a data array */
|
||||
struct Accessor
|
||||
{
|
||||
size_t mCount; // in number of objects
|
||||
size_t mOffset; // in number of values
|
||||
size_t mStride; // Stride in number of values
|
||||
std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
|
||||
size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
|
||||
// For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
|
||||
std::string mSource; // URL of the source array
|
||||
mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
|
||||
|
||||
Accessor()
|
||||
{
|
||||
mCount = 0; mOffset = 0; mStride = 0; mData = NULL;
|
||||
mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/** A single face in a mesh */
|
||||
struct Face
|
||||
{
|
||||
std::vector<size_t> mIndices;
|
||||
};
|
||||
|
||||
/** Different types of input data to a vertex or face */
|
||||
enum InputType
|
||||
{
|
||||
IT_Invalid,
|
||||
IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
|
||||
IT_Position,
|
||||
IT_Normal,
|
||||
IT_Texcoord,
|
||||
IT_Color
|
||||
};
|
||||
|
||||
/** An input channel for mesh data, referring to a single accessor */
|
||||
struct InputChannel
|
||||
{
|
||||
InputType mType; // Type of the data
|
||||
size_t mIndex; // Optional index, if multiple sets of the same data type are given
|
||||
size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
|
||||
std::string mAccessor; // ID of the accessor where to read the actual values from.
|
||||
mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
|
||||
|
||||
InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
|
||||
};
|
||||
|
||||
/** Contains data for a single mesh */
|
||||
struct Mesh
|
||||
{
|
||||
std::string mVertexID; // just to check if there's some sophisticated addressing involved... which we don't support, and therefore should warn about.
|
||||
std::vector<InputChannel> mPerVertexData; // Vertex data addressed by vertex indices
|
||||
|
||||
// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
|
||||
std::vector<aiVector3D> mPositions;
|
||||
std::vector<aiVector3D> mNormals;
|
||||
std::vector<aiVector2D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
|
||||
|
||||
// Faces. Stored are only the number of vertices for each face. 1 == point, 2 == line, 3 == triangle, 4+ == poly
|
||||
std::vector<size_t> mFaceSize;
|
||||
};
|
||||
|
||||
/** Which type of primitives the ReadPrimitives() function is going to read */
|
||||
enum PrimitiveType
|
||||
{
|
||||
Prim_Invalid,
|
||||
Prim_Lines,
|
||||
Prim_LineStrip,
|
||||
Prim_Triangles,
|
||||
Prim_TriStrips,
|
||||
Prim_TriFans,
|
||||
Prim_Polylist,
|
||||
Prim_Polygon
|
||||
};
|
||||
|
||||
} // end of namespace Collada
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // AI_COLLADAHELPER_H_INC
|
|
@ -90,6 +90,21 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
|||
// build the node hierarchy from it
|
||||
pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode);
|
||||
|
||||
// Convert to Z_UP, if different orientation
|
||||
if( parser.mUpDirection == ColladaParser::UP_X)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
0, -1, 0, 0,
|
||||
0, 0, -1, 0,
|
||||
1, 0, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
else if( parser.mUpDirection == ColladaParser::UP_Y)
|
||||
pScene->mRootNode->mTransformation *= aiMatrix4x4(
|
||||
1, 0, 0, 0,
|
||||
0, 0, -1, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 0, 1);
|
||||
|
||||
|
||||
// store all meshes
|
||||
StoreSceneMeshes( pScene);
|
||||
|
||||
|
@ -113,7 +128,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Recursively constructs a scene node for the given parser node and returns it.
|
||||
aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const ColladaParser::Node* pNode)
|
||||
aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode)
|
||||
{
|
||||
// create a node for it
|
||||
aiNode* node = new aiNode( pNode->mName);
|
||||
|
@ -138,7 +153,7 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Builds meshes for the given node and references them
|
||||
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const ColladaParser::Node* pNode, aiNode* pTarget)
|
||||
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget)
|
||||
{
|
||||
// accumulated mesh references by this node
|
||||
std::vector<size_t> newMeshRefs;
|
||||
|
@ -163,7 +178,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
|
|||
{
|
||||
// else we have to add the mesh to the collection and store its newly assigned index at the node
|
||||
aiMesh* dstMesh = new aiMesh;
|
||||
const ColladaParser::Mesh* srcMesh = srcMeshIt->second;
|
||||
const Collada::Mesh* srcMesh = srcMeshIt->second;
|
||||
|
||||
// copy positions
|
||||
dstMesh->mNumVertices = srcMesh->mPositions.size();
|
||||
|
|
|
@ -83,10 +83,10 @@ protected:
|
|||
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
|
||||
|
||||
/** Recursively constructs a scene node for the given parser node and returns it. */
|
||||
aiNode* BuildHierarchy( const ColladaParser& pParser, const ColladaParser::Node* pNode);
|
||||
aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
|
||||
|
||||
/** Builds meshes for the given node and references them */
|
||||
void BuildMeshesForNode( const ColladaParser& pParser, const ColladaParser::Node* pNode, aiNode* pTarget);
|
||||
void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget);
|
||||
|
||||
/** Stores all meshes in the given scene */
|
||||
void StoreSceneMeshes( aiScene* pScene);
|
||||
|
|
|
@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "ParsingUtils.h"
|
||||
|
||||
using namespace Assimp;
|
||||
using namespace Assimp::Collada;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
|
@ -253,7 +254,8 @@ void ColladaParser::ReadMesh( Mesh* pMesh)
|
|||
// read per-vertex mesh data
|
||||
ReadVertexData( pMesh);
|
||||
}
|
||||
else if( IsElement( "polylist") || IsElement( "triangles"))
|
||||
else if( IsElement( "triangles") || IsElement( "lines") || IsElement( "linestrips")
|
||||
|| IsElement( "polygons") || IsElement( "polylist") || IsElement( "trifans") || IsElement( "tristrips"))
|
||||
{
|
||||
// read per-index mesh data and faces setup
|
||||
ReadIndexData( pMesh);
|
||||
|
@ -438,7 +440,23 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
|
|||
|
||||
// distinguish between polys and triangles
|
||||
std::string elementName = mReader->getNodeName();
|
||||
bool isPolylist = IsElement( "polylist");
|
||||
PrimitiveType primType = Prim_Invalid;
|
||||
if( IsElement( "lines"))
|
||||
primType = Prim_Lines;
|
||||
else if( IsElement( "linestrips"))
|
||||
primType = Prim_LineStrip;
|
||||
else if( IsElement( "polygons"))
|
||||
primType = Prim_Polygon;
|
||||
else if( IsElement( "polylist"))
|
||||
primType = Prim_Polylist;
|
||||
else if( IsElement( "triangles"))
|
||||
primType = Prim_Triangles;
|
||||
else if( IsElement( "trifans"))
|
||||
primType = Prim_TriFans;
|
||||
else if( IsElement( "tristrips"))
|
||||
primType = Prim_TriStrips;
|
||||
|
||||
assert( primType != Prim_Invalid);
|
||||
|
||||
// also a number of <input> elements, but in addition a <p> primitive collection and propably index counts for all primitives
|
||||
while( mReader->read())
|
||||
|
@ -469,7 +487,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
|
|||
else if( IsElement( "p"))
|
||||
{
|
||||
// now here the actual fun starts - these are the indices to construct the mesh data from
|
||||
ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, isPolylist);
|
||||
ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, primType);
|
||||
} else
|
||||
{
|
||||
ThrowException( "Unexpected sub element in tag \"vertices\".");
|
||||
|
@ -519,7 +537,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 pNumPrimitives, const std::vector<size_t>& pVCount, bool pIsPolylist)
|
||||
size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType)
|
||||
{
|
||||
// determine number of indices coming per vertex
|
||||
// find the offset index for all per-vertex channels
|
||||
|
@ -534,32 +552,52 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
|
|||
|
||||
// determine the expected number of indices
|
||||
size_t expectedPointCount = 0;
|
||||
if( pIsPolylist)
|
||||
switch( pPrimType)
|
||||
{
|
||||
BOOST_FOREACH( size_t i, pVCount)
|
||||
expectedPointCount += i;
|
||||
} else
|
||||
{
|
||||
// everything triangles
|
||||
expectedPointCount = 3 * pNumPrimitives;
|
||||
case Prim_Polylist:
|
||||
{
|
||||
BOOST_FOREACH( size_t i, pVCount)
|
||||
expectedPointCount += i;
|
||||
break;
|
||||
}
|
||||
case Prim_Lines:
|
||||
expectedPointCount = 2 * pNumPrimitives;
|
||||
break;
|
||||
case Prim_Triangles:
|
||||
expectedPointCount = 3 * pNumPrimitives;
|
||||
break;
|
||||
default:
|
||||
// other primitive types don't state the index count upfront... we need to guess
|
||||
break;
|
||||
}
|
||||
|
||||
// and read all indices into a temporary array
|
||||
std::vector<size_t> indices( expectedPointCount * numOffsets);
|
||||
std::vector<size_t> indices;
|
||||
if( expectedPointCount > 0)
|
||||
indices.reserve( expectedPointCount * numOffsets);
|
||||
|
||||
const char* content = GetTextContent();
|
||||
BOOST_FOREACH( size_t& value, indices)
|
||||
while( *content != 0)
|
||||
{
|
||||
if( *content == 0)
|
||||
ThrowException( "Expected more values while reading primitive indices.");
|
||||
// read a value in place
|
||||
value = strtol10( content, &content);
|
||||
// read a value
|
||||
unsigned int value = strtol10( content, &content);
|
||||
indices.push_back( size_t( value));
|
||||
// skip whitespace after it
|
||||
SkipSpacesAndLineEnd( &content);
|
||||
}
|
||||
|
||||
// complain if the index count doesn't fit
|
||||
if( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets)
|
||||
ThrowException( "Expected different index count in <p> element.");
|
||||
else if( expectedPointCount == 0 && (indices.size() % numOffsets) != 0)
|
||||
ThrowException( "Expected different index count in <p> element.");
|
||||
|
||||
// find the data for all sources
|
||||
BOOST_FOREACH( InputChannel& input, pMesh->mPerVertexData)
|
||||
{
|
||||
if( input.mResolved)
|
||||
continue;
|
||||
|
||||
// find accessor
|
||||
input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor);
|
||||
// resolve accessor's data pointer as well, if neccessary
|
||||
|
@ -570,6 +608,9 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
|
|||
// and the same for the per-index channels
|
||||
BOOST_FOREACH( InputChannel& input, pPerIndexChannels)
|
||||
{
|
||||
if( input.mResolved)
|
||||
continue;
|
||||
|
||||
// ignore vertex pointer, it doesn't refer to an accessor
|
||||
if( input.mType == IT_Vertex)
|
||||
{
|
||||
|
@ -590,12 +631,28 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
|
|||
|
||||
// now assemble vertex data according to those indices
|
||||
std::vector<size_t>::const_iterator idx = indices.begin();
|
||||
for( size_t a = 0; a < pNumPrimitives; a++)
|
||||
|
||||
// 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( size_t a = 0; a < numPrimitives; a++)
|
||||
{
|
||||
// determine number of points for this primitive
|
||||
size_t numPoints = 3;
|
||||
if( pIsPolylist)
|
||||
numPoints = pVCount[a];
|
||||
size_t numPoints = 0;
|
||||
switch( pPrimType)
|
||||
{
|
||||
case Prim_Lines: numPoints = 2; break;
|
||||
case Prim_Triangles: numPoints = 3; break;
|
||||
case Prim_Polylist: numPoints = pVCount[a]; break;
|
||||
case Prim_TriFans:
|
||||
case Prim_Polygon: numPoints = indices.size() / numOffsets; break;
|
||||
default:
|
||||
// LineStrip and TriStrip 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);
|
||||
|
@ -618,7 +675,7 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
|
|||
}
|
||||
}
|
||||
|
||||
// if I ever get my hands on that guy how invented this steaming pile of indirection...
|
||||
// if I ever get my hands on that guy who invented this steaming pile of indirection...
|
||||
TestClosing( "p");
|
||||
}
|
||||
|
||||
|
@ -979,7 +1036,9 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
|
|||
case TF_ROTATE:
|
||||
{
|
||||
aiMatrix4x4 rot;
|
||||
aiMatrix4x4::Rotation( tf.f[3], aiVector3D( tf.f[0], tf.f[1], tf.f[2]), rot);
|
||||
float angle = tf.f[3] * float( AI_MATH_PI) / 180.0f;
|
||||
aiVector3D axis( tf.f[0], tf.f[1], tf.f[2]);
|
||||
aiMatrix4x4::Rotation( angle, axis, rot);
|
||||
res *= rot;
|
||||
break;
|
||||
}
|
||||
|
@ -1019,7 +1078,7 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Determines the input data type for the given semantic string
|
||||
ColladaParser::InputType ColladaParser::GetTypeForSemantic( const std::string& pSemantic)
|
||||
Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& pSemantic)
|
||||
{
|
||||
if( pSemantic == "POSITION")
|
||||
return IT_Position;
|
||||
|
|
|
@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define AI_COLLADAPARSER_H_INC
|
||||
|
||||
#include "./irrXML/irrXMLWrapper.h"
|
||||
#include "ColladaHelper.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
@ -54,111 +55,6 @@ namespace Assimp
|
|||
class ColladaParser
|
||||
{
|
||||
friend class ColladaLoader;
|
||||
public:
|
||||
/** Transformation types that can be applied to a node */
|
||||
enum TransformType
|
||||
{
|
||||
TF_LOOKAT,
|
||||
TF_ROTATE,
|
||||
TF_TRANSLATE,
|
||||
TF_SCALE,
|
||||
TF_SKEW,
|
||||
TF_MATRIX
|
||||
};
|
||||
|
||||
/** Contains all data for one of the different transformation types */
|
||||
struct Transform
|
||||
{
|
||||
TransformType mType;
|
||||
float f[16]; ///< Interpretation of data depends on the type of the transformation
|
||||
};
|
||||
|
||||
/** A node in a scene hierarchy */
|
||||
struct Node
|
||||
{
|
||||
std::string mName;
|
||||
std::string mID;
|
||||
Node* mParent;
|
||||
std::vector<Node*> mChildren;
|
||||
|
||||
/** Operations in order to calculate the resulting transformation to parent. */
|
||||
std::vector<Transform> mTransforms;
|
||||
|
||||
std::vector<std::string> mMeshes; ///< Meshes at this node
|
||||
|
||||
Node() { mParent = NULL; }
|
||||
~Node() { for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) delete *it; }
|
||||
};
|
||||
|
||||
/** Data source array */
|
||||
struct Data
|
||||
{
|
||||
std::vector<float> mValues;
|
||||
};
|
||||
|
||||
/** Accessor to a data array */
|
||||
struct Accessor
|
||||
{
|
||||
size_t mCount; // in number of objects
|
||||
size_t mOffset; // in number of values
|
||||
size_t mStride; // Stride in number of values
|
||||
std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
|
||||
size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
|
||||
// For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
|
||||
std::string mSource; // URL of the source array
|
||||
mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
|
||||
|
||||
Accessor()
|
||||
{
|
||||
mCount = 0; mOffset = 0; mStride = 0; mData = NULL;
|
||||
mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/** A single face in a mesh */
|
||||
struct Face
|
||||
{
|
||||
std::vector<size_t> mIndices;
|
||||
};
|
||||
|
||||
/** Different types of input data to a vertex or face */
|
||||
enum InputType
|
||||
{
|
||||
IT_Invalid,
|
||||
IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
|
||||
IT_Position,
|
||||
IT_Normal,
|
||||
IT_Texcoord,
|
||||
IT_Color
|
||||
};
|
||||
|
||||
/** An input channel for mesh data, referring to a single accessor */
|
||||
struct InputChannel
|
||||
{
|
||||
InputType mType; // Type of the data
|
||||
size_t mIndex; // Optional index, if multiple sets of the same data type are given
|
||||
size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
|
||||
std::string mAccessor; // ID of the accessor where to read the actual values from.
|
||||
mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
|
||||
|
||||
InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
|
||||
};
|
||||
|
||||
/** Contains data for a single mesh */
|
||||
struct Mesh
|
||||
{
|
||||
std::string mVertexID; // just to check if there's some sophisticated addressing involved... which we don't support, and therefore should warn about.
|
||||
std::vector<InputChannel> mPerVertexData; // Vertex data addressed by vertex indices
|
||||
|
||||
// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
|
||||
std::vector<aiVector3D> mPositions;
|
||||
std::vector<aiVector3D> mNormals;
|
||||
std::vector<aiVector2D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||||
std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
|
||||
|
||||
// Faces. Stored are only the number of vertices for each face. 1 == point, 2 == line, 3 == triangle, 4+ == poly
|
||||
std::vector<size_t> mFaceSize;
|
||||
};
|
||||
|
||||
protected:
|
||||
/** Constructor from XML file */
|
||||
|
@ -180,7 +76,7 @@ protected:
|
|||
void ReadGeometryLibrary();
|
||||
|
||||
/** Reads a mesh from the geometry library */
|
||||
void ReadMesh( Mesh* pMesh);
|
||||
void ReadMesh( Collada::Mesh* pMesh);
|
||||
|
||||
/** Reads a data array holding a number of floats, and stores it in the global library */
|
||||
void ReadFloatArray();
|
||||
|
@ -191,32 +87,32 @@ protected:
|
|||
void ReadAccessor( const std::string& pID);
|
||||
|
||||
/** Reads input declarations of per-vertex mesh data into the given mesh */
|
||||
void ReadVertexData( Mesh* pMesh);
|
||||
void ReadVertexData( Collada::Mesh* pMesh);
|
||||
|
||||
/** Reads input declarations of per-index mesh data into the given mesh */
|
||||
void ReadIndexData( Mesh* pMesh);
|
||||
void ReadIndexData( Collada::Mesh* pMesh);
|
||||
|
||||
/** Reads a single input channel element and stores it in the given array, if valid */
|
||||
void ReadInputChannel( std::vector<InputChannel>& poChannels);
|
||||
void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
|
||||
|
||||
/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
|
||||
void ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels,
|
||||
size_t pNumPrimitives, const std::vector<size_t>& pVCount, bool pIsPolylist);
|
||||
void ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
|
||||
size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
|
||||
|
||||
/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
|
||||
void ExtractDataObjectFromChannel( const InputChannel& pInput, size_t pLocalIndex, Mesh* pMesh);
|
||||
void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
|
||||
|
||||
/** Reads the library of node hierarchies and scene parts */
|
||||
void ReadSceneLibrary();
|
||||
|
||||
/** Reads a scene node's contents including children and stores it in the given node */
|
||||
void ReadSceneNode( Node* pNode);
|
||||
void ReadSceneNode( Collada::Node* pNode);
|
||||
|
||||
/** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
|
||||
void ReadNodeTransformation( Node* pNode, TransformType pType);
|
||||
void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType);
|
||||
|
||||
/** Reads a mesh reference in a node and adds it to the node's mesh list */
|
||||
void ReadNodeGeometry( Node* pNode);
|
||||
void ReadNodeGeometry( Collada::Node* pNode);
|
||||
|
||||
/** Reads the collada scene */
|
||||
void ReadScene();
|
||||
|
@ -247,10 +143,10 @@ protected:
|
|||
const char* GetTextContent();
|
||||
|
||||
/** Calculates the resulting transformation fromm all the given transform steps */
|
||||
aiMatrix4x4 CalculateResultTransform( const std::vector<Transform>& pTransforms) const;
|
||||
aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
|
||||
|
||||
/** Determines the input data type for the given semantic string */
|
||||
InputType GetTypeForSemantic( const std::string& pSemantic);
|
||||
Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
|
||||
|
||||
/** Finds the item in the given library by its reference, throws if not found */
|
||||
template <typename Type> const Type& ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
|
||||
|
@ -263,23 +159,23 @@ protected:
|
|||
irr::io::IrrXMLReader* mReader;
|
||||
|
||||
/** All data arrays found in the file by ID. Might be referred to by actually everyone. Collada, you are a steaming pile of indirection. */
|
||||
typedef std::map<std::string, Data> DataLibrary;
|
||||
typedef std::map<std::string, Collada::Data> DataLibrary;
|
||||
DataLibrary mDataLibrary;
|
||||
|
||||
/** Same for accessors which define how the data in a data array is accessed. */
|
||||
typedef std::map<std::string, Accessor> AccessorLibrary;
|
||||
typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
|
||||
AccessorLibrary mAccessorLibrary;
|
||||
|
||||
/** Mesh library: mesh by ID */
|
||||
typedef std::map<std::string, Mesh*> MeshLibrary;
|
||||
typedef std::map<std::string, Collada::Mesh*> MeshLibrary;
|
||||
MeshLibrary mMeshLibrary;
|
||||
|
||||
/** node library: root node of the hierarchy part by ID */
|
||||
typedef std::map<std::string, Node*> NodeLibrary;
|
||||
typedef std::map<std::string, Collada::Node*> NodeLibrary;
|
||||
NodeLibrary mNodeLibrary;
|
||||
|
||||
/** Pointer to the root node. Don't delete, it just points to one of the nodes in the node library. */
|
||||
Node* mRootNode;
|
||||
Collada::Node* mRootNode;
|
||||
|
||||
/** Size unit: how large compared to a meter */
|
||||
float mUnitSize;
|
||||
|
|
|
@ -194,7 +194,7 @@ inline const char* fast_atof_move( const char* c, float& out)
|
|||
else if (*c=='+')++c;
|
||||
|
||||
f = (float) strtol10_64 ( c, &c );
|
||||
if (*c == '.')
|
||||
if (*c == '.' || (c[0] == ',' && isdigit( c[1])))
|
||||
{
|
||||
++c;
|
||||
|
||||
|
|
|
@ -1437,6 +1437,10 @@
|
|||
<Filter
|
||||
Name="Collada"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\code\ColladaHelper.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\code\ColladaLoader.cpp"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue