- added another boost dependency.

- further work on the collada loader. Should load static geometry correctly now, but still not properly integrated
- added some Collada sample files. The license is hopefully fine with this.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@245 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
ulfjorensen
2008-11-20 17:42:55 +00:00
parent 01ceeeb00b
commit fe3c008301
15 changed files with 2313 additions and 5 deletions

View File

@@ -117,6 +117,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# include <boost/scoped_array.hpp>
# include <boost/format.hpp>
# include <boost/math/common_factor_rt.hpp>
# include <boost/foreach.hpp>
#endif

View File

@@ -72,6 +72,8 @@ ColladaParser::~ColladaParser()
delete mReader;
for( NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it)
delete it->second;
for( MeshLibrary::iterator it = mMeshLibrary.begin(); it != mMeshLibrary.end(); ++it)
delete it->second;
}
// ------------------------------------------------------------------------------------------------
@@ -163,6 +165,9 @@ void ColladaParser::ReadAssetInfo()
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "asset") != 0)
ThrowException( "Expected end of \"asset\" element.");
break;
}
}
@@ -172,9 +177,493 @@ void ColladaParser::ReadAssetInfo()
// Reads the geometry library contents
void ColladaParser::ReadGeometryLibrary()
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "geometry"))
{
// read ID. Another entry which is "optional" by design but obligatory in reality
int indexID = GetAttribute( "id");
std::string id = mReader->getAttributeValue( indexID);
// TODO: (thom) support SIDs
assert( TestAttribute( "sid") == -1);
// a <geometry> always contains a single <mesh> element inside, so we just skip that element in advance
TestOpening( "mesh");
// create a mesh and store it in the library under its ID
Mesh* mesh = new Mesh;
mMeshLibrary[id] = mesh;
// read on from there
ReadMesh( mesh);
// check for the closing tag of the outer <geometry" element, the inner closing of <mesh> has been consumed by ReadMesh()
TestClosing( "geometry");
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "library_geometries") != 0)
ThrowException( "Expected end of \"library_geometries\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a mesh from the geometry library
void ColladaParser::ReadMesh( Mesh* pMesh)
{
// I'm doing a dirty state parsing here because I don't want to open another submethod for it.
// There's a <source> tag defining the name for the accessor inside, and possible a <float_array>
// with it's own ID. This string contains the current source's ID if parsing is inside a <source> element.
std::string presentSourceID;
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "source"))
{
// beginning of a source element - store ID for the inner elements
int attrID = GetAttribute( "id");
presentSourceID = mReader->getAttributeValue( attrID);
}
else if( IsElement( "float_array"))
{
ReadFloatArray();
}
else if( IsElement( "technique_common"))
{
// I don't fucking care for your profiles bullshit
}
else if( IsElement( "accessor"))
{
ReadAccessor( presentSourceID);
}
else if( IsElement( "vertices"))
{
// read per-vertex mesh data
ReadVertexData( pMesh);
}
else if( IsElement( "polylist") || IsElement( "triangles"))
{
// read per-index mesh data and faces setup
ReadIndexData( pMesh);
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "source") == 0)
{
// end of <source> - reset present source ID
presentSourceID.clear();
}
else if( strcmp( mReader->getNodeName(), "technique_common") == 0)
{
// end of another meaningless element - read over it
}
else if( strcmp( mReader->getNodeName(), "mesh") == 0)
{
// end of <mesh> element - we're done here
break;
} else
{
// everything else should be punished
ThrowException( "Expected end of \"mesh\" element.");
}
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a data array holding a number of floats, and stores it in the global library
void ColladaParser::ReadFloatArray()
{
// read attributes
int indexID = GetAttribute( "id");
std::string id = mReader->getAttributeValue( indexID);
int indexCount = GetAttribute( "count");
unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( indexCount);
const char* content = GetTextContent();
// read values and store inside an array in the data library
mDataLibrary[id] = Data();
Data& data = mDataLibrary[id];
data.mValues.reserve( count);
for( unsigned int a = 0; a < count; a++)
{
if( *content == 0)
ThrowException( "Expected more values while reading float_array contents.");
float value;
// read a number
content = fast_atof_move( content, value);
data.mValues.push_back( value);
// skip whitespace after it
SkipSpacesAndLineEnd( &content);
}
// test for closing tag
TestClosing( "float_array");
}
// ------------------------------------------------------------------------------------------------
// Reads an accessor and stores it in the global library
void ColladaParser::ReadAccessor( const std::string& pID)
{
// read accessor attributes
int attrSource = GetAttribute( "source");
const char* source = mReader->getAttributeValue( attrSource);
if( source[0] != '#')
ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\".") % source));
int attrCount = GetAttribute( "count");
unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( attrCount);
int attrOffset = TestAttribute( "offset");
unsigned int offset = 0;
if( attrOffset > -1)
offset = (unsigned int) mReader->getAttributeValueAsInt( attrOffset);
int attrStride = TestAttribute( "stride");
unsigned int stride = 1;
if( attrStride > -1)
stride = (unsigned int) mReader->getAttributeValueAsInt( attrStride);
// store in the library under the given ID
mAccessorLibrary[pID] = Accessor();
Accessor& acc = mAccessorLibrary[pID];
acc.mCount = count;
acc.mOffset = offset;
acc.mStride = stride;
acc.mSource = source+1; // ignore the leading '#'
// and read the components
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "param"))
{
// read data param
int attrName = TestAttribute( "name");
std::string name;
if( attrName > -1)
{
name = mReader->getAttributeValue( attrName);
// analyse for common type components and store it's sub-offset in the corresponding field
if( name == "X") acc.mSubOffset[0] = acc.mParams.size();
else if( name == "Y") acc.mSubOffset[1] = acc.mParams.size();
else if( name == "Z") acc.mSubOffset[2] = acc.mParams.size();
else if( name == "R") acc.mSubOffset[0] = acc.mParams.size();
else if( name == "G") acc.mSubOffset[1] = acc.mParams.size();
else if( name == "B") acc.mSubOffset[2] = acc.mParams.size();
else if( name == "A") acc.mSubOffset[3] = acc.mParams.size();
else if( name == "S") acc.mSubOffset[0] = acc.mParams.size();
else if( name == "T") acc.mSubOffset[1] = acc.mParams.size();
else
DefaultLogger::get()->warn( boost::str( boost::format( "Unknown accessor parameter \"%s\". Ignoring data channel.") % name));
}
acc.mParams.push_back( name);
// skip remaining stuff of this element, if any
SkipElement();
} else
{
ThrowException( "Unexpected sub element in tag \"accessor\".");
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "accessor") != 0)
ThrowException( "Expected end of \"accessor\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads input declarations of per-vertex mesh data into the given mesh
void ColladaParser::ReadVertexData( Mesh* pMesh)
{
// extract the ID of the <vertices> element. Not that we care, but to catch strange referencing schemes we should warn about
int attrID= GetAttribute( "id");
pMesh->mVertexID = mReader->getAttributeValue( attrID);
// a number of <input> elements
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "input"))
{
ReadInputChannel( pMesh->mPerVertexData);
} else
{
ThrowException( "Unexpected sub element in tag \"vertices\".");
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "vertices") != 0)
ThrowException( "Expected end of \"vertices\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads input declarations of per-index mesh data into the given mesh
void ColladaParser::ReadIndexData( Mesh* pMesh)
{
std::vector<size_t> vcount;
std::vector<InputChannel> perIndexData;
// read primitive count from the attribute
int attrCount = GetAttribute( "count");
size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount);
// distinguish between polys and triangles
std::string elementName = mReader->getNodeName();
bool isPolylist = IsElement( "polylist");
// also a number of <input> elements, but in addition a <p> primitive collection and propably index counts for all primitives
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "input"))
{
ReadInputChannel( perIndexData);
}
else if( IsElement( "vcount"))
{
// case <polylist> - specifies the number of indices for each polygon
const char* content = GetTextContent();
vcount.reserve( numPrimitives);
for( unsigned int a = 0; a < numPrimitives; a++)
{
if( *content == 0)
ThrowException( "Expected more values while reading vcount contents.");
// read a number
vcount.push_back( (size_t) strtol10( content, &content));
// skip whitespace after it
SkipSpacesAndLineEnd( &content);
}
TestClosing( "vcount");
}
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);
} else
{
ThrowException( "Unexpected sub element in tag \"vertices\".");
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( mReader->getNodeName() != elementName)
ThrowException( boost::str( boost::format( "Expected end of \"%s\" element.") % elementName));
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a single input channel element and stores it in the given array, if valid
void ColladaParser::ReadInputChannel( std::vector<InputChannel>& poChannels)
{
InputChannel channel;
// read semantic
int attrSemantic = GetAttribute( "semantic");
std::string semantic = mReader->getAttributeValue( attrSemantic);
channel.mType = GetTypeForSemantic( semantic);
// read source
int attrSource = GetAttribute( "source");
const char* source = mReader->getAttributeValue( attrSource);
if( source[0] != '#')
ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\".") % source));
channel.mAccessor = source+1; // skipping the leading #, hopefully the remaining text is the accessor ID only
// read index offset, if per-index <input>
int attrOffset = TestAttribute( "offset");
if( attrOffset > -1)
channel.mOffset = mReader->getAttributeValueAsInt( attrOffset);
// store, if valid type
if( channel.mType != IT_Invalid)
poChannels.push_back( channel);
// skip remaining stuff of this element, if any
SkipElement();
}
// ------------------------------------------------------------------------------------------------
// 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)
{
// determine number of indices coming per vertex
// find the offset index for all per-vertex channels
size_t numOffsets = 1;
size_t perVertexOffset = -1; // invalid value
BOOST_FOREACH( const InputChannel& channel, pPerIndexChannels)
{
numOffsets = std::max( numOffsets, channel.mOffset+1);
if( channel.mType == IT_Vertex)
perVertexOffset = channel.mOffset;
}
// determine the expected number of indices
size_t expectedPointCount = 0;
if( pIsPolylist)
{
BOOST_FOREACH( size_t i, pVCount)
expectedPointCount += i;
} else
{
// everything triangles
expectedPointCount = 3 * pNumPrimitives;
}
// and read all indices into a temporary array
std::vector<size_t> indices( expectedPointCount * numOffsets);
const char* content = GetTextContent();
BOOST_FOREACH( size_t& value, indices)
{
if( *content == 0)
ThrowException( "Expected more values while reading primitive indices.");
// read a value in place
value = strtol10( content, &content);
// skip whitespace after it
SkipSpacesAndLineEnd( &content);
}
// find the data for all sources
BOOST_FOREACH( InputChannel& input, pMesh->mPerVertexData)
{
// find accessor
input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor);
// resolve accessor's data pointer as well, if neccessary
const Accessor* acc = input.mResolved;
if( !acc->mData)
acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
}
// and the same for the per-index channels
BOOST_FOREACH( InputChannel& input, pPerIndexChannels)
{
// ignore vertex pointer, it doesn't refer to an accessor
if( input.mType == IT_Vertex)
{
// warn if the vertex channel does not refer to the <vertices> element in the same mesh
if( input.mAccessor != pMesh->mVertexID)
ThrowException( "Unsupported vertex referencing scheme. I fucking hate Collada.");
continue;
}
// find accessor
input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor);
// resolve accessor's data pointer as well, if neccessary
const Accessor* acc = input.mResolved;
if( !acc->mData)
acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
}
// 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++)
{
// determine number of points for this primitive
size_t numPoints = 3;
if( pIsPolylist)
numPoints = pVCount[a];
// 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 static array
assert( numOffsets < 20);
static 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
BOOST_FOREACH( const InputChannel& input, pMesh->mPerVertexData)
ExtractDataObjectFromChannel( input, vindex[perVertexOffset], pMesh);
// and extract per-index channels using there specified offset
BOOST_FOREACH( const InputChannel& input, pPerIndexChannels)
ExtractDataObjectFromChannel( input, vindex[input.mOffset], pMesh);
}
}
// if I ever get my hands on that guy how invented this steaming pile of indirection...
TestClosing( "p");
}
// ------------------------------------------------------------------------------------------------
// 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)
{
// ignore vertex referrer - we handle them that separate
if( pInput.mType == IT_Vertex)
return;
const Accessor& acc = *pInput.mResolved;
if( pLocalIndex >= acc.mCount)
ThrowException( boost::str( boost::format( "Invalid data index (%d/%d) in primitive specification") % pLocalIndex % acc.mCount));
// get a pointer to the start of the data object referred to by the accessor and the local index
const float* dataObject = &(acc.mData->mValues[0]) + acc.mOffset + pLocalIndex* acc.mStride;
// assemble according to the accessors component sub-offset list. We don't care, yet, what kind of object exactly we're extracting here
float obj[4];
for( size_t c = 0; c < 4; ++c)
obj[c] = dataObject[acc.mSubOffset[c]];
// now we reinterpret it according to the type we're reading here
switch( pInput.mType)
{
case IT_Position: // ignore all position streams except 0 - there can be only one position
if( pInput.mIndex == 0)
pMesh->mPositions.push_back( aiVector3D( obj[0], obj[1], obj[2]));
break;
case IT_Normal: // ignore all normal streams except 0 - there can be only one normal
if( pInput.mIndex == 0)
pMesh->mNormals.push_back( aiVector3D( obj[0], obj[1], obj[2]));
break;
case IT_Texcoord: // up to 4 texture coord sets are fine, ignore the others
if( pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS)
pMesh->mTexCoords[pInput.mIndex].push_back( aiVector2D( obj[0], obj[1]));
break;
case IT_Color: // up to 4 color sets are fine, ignore the others
if( pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS)
pMesh->mColors[pInput.mIndex].push_back( aiColor4D( obj[0], obj[1], obj[2], obj[3]));
break;
}
}
// ------------------------------------------------------------------------------------------------
// Reads the library of node hierarchies and scene parts
void ColladaParser::ReadSceneLibrary()
@@ -214,6 +703,9 @@ void ColladaParser::ReadSceneLibrary()
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "library_visual_scenes") != 0)
ThrowException( "Expected end of \"library_visual_scenes\" element.");
break;
}
}
@@ -371,6 +863,22 @@ void ColladaParser::SkipElement()
}
}
// ------------------------------------------------------------------------------------------------
// Tests for an opening element of the given name, throws an exception if not found
void ColladaParser::TestOpening( const char* pName)
{
// read element start
if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while beginning of \"%s\" element.") % pName));
// whitespace in front is ok, just read again if found
if( mReader->getNodeType() == irr::io::EXN_TEXT)
if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while reading beginning of \"%s\" element.") % pName));
if( mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp( mReader->getNodeName(), pName) != 0)
ThrowException( boost::str( boost::format( "Expected start of \"%s\" element.") % pName));
}
// ------------------------------------------------------------------------------------------------
// Tests for the closing tag of the given element, throws an exception if not found
void ColladaParser::TestClosing( const char* pName)
@@ -378,6 +886,11 @@ void ColladaParser::TestClosing( const char* pName)
// read closing tag
if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of \"%s\" element.") % pName));
// whitespace in front is ok, just read again if found
if( mReader->getNodeType() == irr::io::EXN_TEXT)
if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of \"%s\" element.") % pName));
if( mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp( mReader->getNodeName(), pName) != 0)
ThrowException( boost::str( boost::format( "Expected end of \"%s\" element.") % pName));
}
@@ -482,3 +995,22 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
return res;
}
// ------------------------------------------------------------------------------------------------
// Determines the input data type for the given semantic string
ColladaParser::InputType ColladaParser::GetTypeForSemantic( const std::string& pSemantic)
{
if( pSemantic == "POSITION")
return IT_Position;
else if( pSemantic == "TEXCOORD")
return IT_Texcoord;
else if( pSemantic == "NORMAL")
return IT_Normal;
else if( pSemantic == "COLOR")
return IT_Color;
else if( pSemantic == "VERTEX")
return IT_Vertex;
DefaultLogger::get()->warn( boost::str( boost::format( "Unknown vertex input type \"%s\". Ignoring.") % pSemantic));
return IT_Invalid;
}

View File

@@ -97,16 +97,65 @@ public:
/** Accessor to a data array */
struct Accessor
{
unsigned int mCount; // in number of objects
unsigned int mOffset; // in number of values
unsigned int mStride; // Stride in number of values
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:
@@ -129,7 +178,31 @@ protected:
void ReadGeometryLibrary();
/** Reads a mesh from the geometry library */
void ReadGeometry();
void ReadMesh( Mesh* pMesh);
/** Reads a data array holding a number of floats, and stores it in the global library */
void ReadFloatArray();
/** Reads an accessor and stores it in the global library under the given ID -
* accessors use the ID of the parent <source> element
*/
void ReadAccessor( const std::string& pID);
/** Reads input declarations of per-vertex mesh data into the given mesh */
void ReadVertexData( Mesh* pMesh);
/** Reads input declarations of per-index mesh data into the given mesh */
void ReadIndexData( Mesh* pMesh);
/** Reads a single input channel element and stores it in the given array, if valid */
void ReadInputChannel( std::vector<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);
/** 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);
/** Reads the library of node hierarchies and scene parts */
void ReadSceneLibrary();
@@ -153,6 +226,9 @@ protected:
/** Compares the current xml element name to the given string and returns true if equal */
bool IsElement( const char* pName) const { assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); return strcmp( mReader->getNodeName(), pName) == 0; }
/** Tests for the opening tag of the given element, throws an exception if not found */
void TestOpening( const char* pName);
/** Tests for the closing tag of the given element, throws an exception if not found */
void TestClosing( const char* pName);
@@ -168,6 +244,12 @@ protected:
/** Calculates the resulting transformation fromm all the given transform steps */
aiMatrix4x4 CalculateResultTransform( const std::vector<Transform>& pTransforms) const;
/** Determines the input data type for the given semantic string */
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;
protected:
/** Filename, for a verbose error message */
std::string mFileName;
@@ -175,6 +257,18 @@ protected:
/** XML reader */
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;
DataLibrary mDataLibrary;
/** Same for accessors which define how the data in a data array is accessed. */
typedef std::map<std::string, Accessor> AccessorLibrary;
AccessorLibrary mAccessorLibrary;
/** Mesh library: mesh by ID */
typedef std::map<std::string, Mesh*> MeshLibrary;
MeshLibrary mMeshLibrary;
/** node library: root node of the hierarchy part by ID */
typedef std::map<std::string, Node*> NodeLibrary;
NodeLibrary mNodeLibrary;
@@ -189,6 +283,17 @@ protected:
enum { UP_X, UP_Y, UP_Z } mUpDirection;
};
// ------------------------------------------------------------------------------------------------
// Finds the item in the given library by its reference, throws if not found
template <typename Type>
const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const
{
std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL);
if( it == pLibrary.end())
ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL));
return it->second;
}
} // end of namespace Assimp
#endif // AI_COLLADAPARSER_H_INC

293
test/Collada/COLLADA.dae Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

210
test/Collada/cube.dae Normal file
View File

@@ -0,0 +1,210 @@
<?xml version="1.0"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<asset>
<contributor>
<author>alorino</author>
<authoring_tool>Maya 7.0 | ColladaMaya v2.01 Jun 9 2006 at 16:08:19 | FCollada v1.11</authoring_tool>
<comments>Collada Maya Export Options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
curveConstrainSampling=0;exportCameraAsLookat=0;
exportLights=1;exportCameras=1;exportJointsAndSkin=1;
exportAnimations=1;exportTriangles=0;exportInvisibleNodes=0;
exportNormals=1;exportTexCoords=1;exportVertexColors=1;exportTangents=0;
exportTexTangents=0;exportConstraints=0;exportPhysics=0;exportXRefs=1;
dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
<copyright>
Copyright 2006 Sony Computer Entertainment Inc.
Licensed under the SCEA Shared Source License, Version 1.0 (the
&quot;License&quot;); you may not use this file except in compliance with the
License. You may obtain a copy of the License at:
http://research.scea.com/scea_shared_source_license.html
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</copyright>
</contributor>
<created>2006-06-21T21:23:22Z</created>
<modified>2006-06-21T21:23:22Z</modified>
<unit meter="0.01" name="centimeter"/>
<up_axis>Y_UP</up_axis>
</asset>
<library_cameras>
<camera id="PerspCamera" name="PerspCamera">
<optics>
<technique_common>
<perspective>
<yfov>37.8493</yfov>
<aspect_ratio>1</aspect_ratio>
<znear>10</znear>
<zfar>1000</zfar>
</perspective>
</technique_common>
</optics>
</camera>
<camera id="testCameraShape" name="testCameraShape">
<optics>
<technique_common>
<perspective>
<yfov>37.8501</yfov>
<aspect_ratio>1</aspect_ratio>
<znear>0.01</znear>
<zfar>1000</zfar>
</perspective>
</technique_common>
</optics>
</camera>
</library_cameras>
<library_lights>
<light id="light-lib" name="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>
<technique profile="MAX3D">
<intensity>1.000000</intensity>
</technique>
</light>
<light id="pointLightShape1-lib" name="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_materials>
<material id="Blue" name="Blue">
<instance_effect url="#Blue-fx"/>
</material>
</library_materials>
<library_effects>
<effect id="Blue-fx">
<profile_COMMON>
<technique sid="common">
<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>
<reflective>
<color>0 0 0 1</color>
</reflective>
<reflectivity>
<float>0.5</float>
</reflectivity>
<transparent>
<color>0 0 0 1</color>
</transparent>
<transparency>
<float>1</float>
</transparency>
<index_of_refraction>
<float>0</float>
</index_of_refraction>
</phong>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<library_geometries>
<geometry id="box-lib" name="box">
<mesh>
<source id="box-lib-positions" name="position">
<float_array id="box-lib-positions-array" count="24">-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="8" offset="0" source="#box-lib-positions-array" stride="3">
<param name="X" type="float"></param>
<param name="Y" type="float"></param>
<param name="Z" type="float"></param>
</accessor>
</technique_common>
</source>
<source id="box-lib-normals" name="normal">
<float_array id="box-lib-normals-array" count="72">0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 -1 0 0 -1 0 0 -1 0 0 -1</float_array>
<technique_common>
<accessor count="24" offset="0" source="#box-lib-normals-array" stride="3">
<param name="X" type="float"></param>
<param name="Y" type="float"></param>
<param name="Z" type="float"></param>
</accessor>
</technique_common>
</source>
<vertices id="box-lib-vertices">
<input semantic="POSITION" source="#box-lib-positions"/>
</vertices>
<polylist count="6" material="BlueSG">
<input offset="0" semantic="VERTEX" source="#box-lib-vertices"/>
<input offset="1" semantic="NORMAL" source="#box-lib-normals"/>
<vcount>4 4 4 4 4 4</vcount>
<p>0 0 2 1 3 2 1 3 0 4 1 5 5 6 4 7 6 8 7 9 3 10 2 11 0 12 4 13 6 14 2 15 3 16 7 17 5 18 1 19 5 20 7 21 6 22 4 23</p>
</polylist>
</mesh>
</geometry>
</library_geometries>
<library_visual_scenes>
<visual_scene id="VisualSceneNode" name="untitled">
<node id="Camera" name="Camera">
<translate sid="translate">-427.749 333.855 655.017</translate>
<rotate sid="rotateY">0 1 0 -33</rotate>
<rotate sid="rotateX">1 0 0 -22.1954</rotate>
<rotate sid="rotateZ">0 0 1 0</rotate>
<instance_camera url="#PerspCamera"/>
</node>
<node id="Light" name="Light">
<translate sid="translate">-500 1000 400</translate>
<rotate sid="rotateZ">0 0 1 0</rotate>
<rotate sid="rotateY">0 1 0 0</rotate>
<rotate sid="rotateX">1 0 0 0</rotate>
<instance_light url="#light-lib"/>
</node>
<node id="Box" name="Box">
<rotate sid="rotateZ">0 0 1 0</rotate>
<rotate sid="rotateY">0 1 0 0</rotate>
<rotate sid="rotateX">1 0 0 0</rotate>
<instance_geometry url="#box-lib">
<bind_material>
<technique_common>
<instance_material symbol="BlueSG" target="#Blue"/>
</technique_common>
</bind_material>
</instance_geometry>
</node>
<node id="testCamera" name="testCamera">
<translate sid="translate">-427.749 333.855 655.017</translate>
<rotate sid="rotateY">0 1 0 -33</rotate>
<rotate sid="rotateX">1 0 0 -22.1954</rotate>
<rotate sid="rotateZ">0 0 1 0</rotate>
<instance_camera url="#testCameraShape"/>
</node>
<node id="pointLight1" name="pointLight1">
<translate sid="translate">3 4 10</translate>
<rotate sid="rotateZ">0 0 1 0</rotate>
<rotate sid="rotateY">0 1 0 0</rotate>
<rotate sid="rotateX">1 0 0 0</rotate>
<instance_light url="#pointLightShape1-lib"/>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#VisualSceneNode"/>
</scene>
</COLLADA>

View File

@@ -0,0 +1,210 @@
<?xml version="1.0"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
<asset>
<contributor>
<author>alorino</author>
<authoring_tool>Maya 7.0 | ColladaMaya v2.01 Jun 9 2006 at 16:08:19 | FCollada v1.11</authoring_tool>
<comments>Collada Maya Export Options: bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
curveConstrainSampling=0;exportCameraAsLookat=0;
exportLights=1;exportCameras=1;exportJointsAndSkin=1;
exportAnimations=1;exportTriangles=0;exportInvisibleNodes=0;
exportNormals=1;exportTexCoords=1;exportVertexColors=1;exportTangents=0;
exportTexTangents=0;exportConstraints=0;exportPhysics=0;exportXRefs=1;
dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
<copyright>
Copyright 2006 Sony Computer Entertainment Inc.
Licensed under the SCEA Shared Source License, Version 1.0 (the
&quot;License&quot;); you may not use this file except in compliance with the
License. You may obtain a copy of the License at:
http://research.scea.com/scea_shared_source_license.html
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</copyright>
</contributor>
<created>2006-06-21T21:23:22Z</created>
<modified>2006-06-21T21:23:22Z</modified>
<unit meter="0.01" name="centimeter"/>
<up_axis>Y_UP</up_axis>
</asset>
<library_cameras>
<camera id="PerspCamera" name="PerspCamera">
<optics>
<technique_common>
<perspective>
<yfov>37.8493</yfov>
<aspect_ratio>1</aspect_ratio>
<znear>10</znear>
<zfar>1000</zfar>
</perspective>
</technique_common>
</optics>
</camera>
<camera id="testCameraShape" name="testCameraShape">
<optics>
<technique_common>
<perspective>
<yfov>37.8501</yfov>
<aspect_ratio>1</aspect_ratio>
<znear>0.01</znear>
<zfar>1000</zfar>
</perspective>
</technique_common>
</optics>
</camera>
</library_cameras>
<library_lights>
<light id="light-lib" name="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>
<technique profile="MAX3D">
<intensity>1.000000</intensity>
</technique>
</light>
<light id="pointLightShape1-lib" name="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_materials>
<material id="Blue" name="Blue">
<instance_effect url="#Blue-fx"/>
</material>
</library_materials>
<library_effects>
<effect id="Blue-fx">
<profile_COMMON>
<technique sid="common">
<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>
<reflective>
<color>0 0 0 1</color>
</reflective>
<reflectivity>
<float>0.5</float>
</reflectivity>
<transparent>
<color>0 0 0 1</color>
</transparent>
<transparency>
<float>1</float>
</transparency>
<index_of_refraction>
<float>0</float>
</index_of_refraction>
</phong>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<library_geometries>
<geometry id="box-lib" name="box">
<mesh>
<source id="box-lib-positions" name="position">
<float_array id="box-lib-positions-array" count="24">-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="8" offset="0" source="#box-lib-positions-array" stride="3">
<param name="X" type="float"></param>
<param name="Y" type="float"></param>
<param name="Z" type="float"></param>
</accessor>
</technique_common>
</source>
<source id="box-lib-normals" name="normal">
<float_array id="box-lib-normals-array" count="72">0 0 1 0 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 0 1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 0 -1 0 0 -1 0 0 -1 0 0 -1</float_array>
<technique_common>
<accessor count="24" offset="0" source="#box-lib-normals-array" stride="3">
<param name="X" type="float"></param>
<param name="Y" type="float"></param>
<param name="Z" type="float"></param>
</accessor>
</technique_common>
</source>
<vertices id="box-lib-vertices">
<input semantic="POSITION" source="#box-lib-positions"/>
</vertices>
<triangles count="12" material="BlueSG">
<input offset="0" semantic="VERTEX" source="#box-lib-vertices"/>
<input offset="1" semantic="NORMAL" source="#box-lib-normals"/>
<p>0 0 2 1 3 2 0 0 3 2 1 3 0 4 1 5 5 6 0 4 5 6 4 7 6 8 7 9 3 10 6 8 3 10 2 11 0 12 4 13 6 14 0 12 6 14 2 15 3 16 7 17 5 18 3 16 5 18 1 19 5 20 7 21 6 22 5 20 6 22 4 23</p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_visual_scenes>
<visual_scene id="VisualSceneNode" name="untitled">
<node id="Camera" name="Camera">
<translate sid="translate">-427.749 333.855 655.017</translate>
<rotate sid="rotateY">0 1 0 -33</rotate>
<rotate sid="rotateX">1 0 0 -22.1954</rotate>
<rotate sid="rotateZ">0 0 1 0</rotate>
<instance_camera url="#PerspCamera"/>
</node>
<node id="Light" name="Light">
<translate sid="translate">-500 1000 400</translate>
<rotate sid="rotateZ">0 0 1 0</rotate>
<rotate sid="rotateY">0 1 0 0</rotate>
<rotate sid="rotateX">1 0 0 0</rotate>
<instance_light url="#light-lib"/>
</node>
<node id="Box" name="Box">
<rotate sid="rotateZ">0 0 1 0</rotate>
<rotate sid="rotateY">0 1 0 0</rotate>
<rotate sid="rotateX">1 0 0 0</rotate>
<instance_geometry url="#box-lib">
<bind_material>
<technique_common>
<instance_material symbol="BlueSG" target="#Blue"/>
</technique_common>
</bind_material>
</instance_geometry>
</node>
<node id="testCamera" name="testCamera">
<translate sid="translate">-427.749 333.855 655.017</translate>
<rotate sid="rotateY">0 1 0 -33</rotate>
<rotate sid="rotateX">1 0 0 -22.1954</rotate>
<rotate sid="rotateZ">0 0 1 0</rotate>
<instance_camera url="#testCameraShape"/>
</node>
<node id="pointLight1" name="pointLight1">
<translate sid="translate">3 4 10</translate>
<rotate sid="rotateZ">0 0 1 0</rotate>
<rotate sid="rotateY">0 1 0 0</rotate>
<rotate sid="rotateX">1 0 0 0</rotate>
<instance_light url="#pointLightShape1-lib"/>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#VisualSceneNode"/>
</scene>
</COLLADA>

199
test/Collada/duck.dae Normal file

File diff suppressed because one or more lines are too long

BIN
test/Collada/duckCM.tga Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

135
test/Collada/sphere.dae Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

File diff suppressed because one or more lines are too long