- 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
pull/1/head
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/scoped_array.hpp>
# include <boost/format.hpp> # include <boost/format.hpp>
# include <boost/math/common_factor_rt.hpp> # include <boost/math/common_factor_rt.hpp>
# include <boost/foreach.hpp>
#endif #endif

View File

@ -72,6 +72,8 @@ ColladaParser::~ColladaParser()
delete mReader; delete mReader;
for( NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it) for( NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it)
delete it->second; 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) else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{ {
if( strcmp( mReader->getNodeName(), "asset") != 0)
ThrowException( "Expected end of \"asset\" element.");
break; break;
} }
} }
@ -172,9 +177,493 @@ void ColladaParser::ReadAssetInfo()
// Reads the geometry library contents // Reads the geometry library contents
void ColladaParser::ReadGeometryLibrary() 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(); 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 // Reads the library of node hierarchies and scene parts
void ColladaParser::ReadSceneLibrary() void ColladaParser::ReadSceneLibrary()
@ -214,6 +703,9 @@ void ColladaParser::ReadSceneLibrary()
} }
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) 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; 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 // Tests for the closing tag of the given element, throws an exception if not found
void ColladaParser::TestClosing( const char* pName) void ColladaParser::TestClosing( const char* pName)
@ -378,6 +886,11 @@ void ColladaParser::TestClosing( const char* pName)
// read closing tag // read closing tag
if( !mReader->read()) if( !mReader->read())
ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of \"%s\" element.") % pName)); 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) if( mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp( mReader->getNodeName(), pName) != 0)
ThrowException( boost::str( boost::format( "Expected end of \"%s\" element.") % pName)); ThrowException( boost::str( boost::format( "Expected end of \"%s\" element.") % pName));
} }
@ -482,3 +995,22 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
return res; 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 */ /** Accessor to a data array */
struct Accessor struct Accessor
{ {
unsigned int mCount; // in number of objects size_t mCount; // in number of objects
unsigned int mOffset; // in number of values size_t mOffset; // in number of values
unsigned int mStride; // Stride 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 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 */ /** Contains data for a single mesh */
struct 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: protected:
@ -129,7 +178,31 @@ protected:
void ReadGeometryLibrary(); void ReadGeometryLibrary();
/** Reads a mesh from the geometry library */ /** 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 */ /** Reads the library of node hierarchies and scene parts */
void ReadSceneLibrary(); void ReadSceneLibrary();
@ -153,6 +226,9 @@ protected:
/** Compares the current xml element name to the given string and returns true if equal */ /** 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; } 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 */ /** Tests for the closing tag of the given element, throws an exception if not found */
void TestClosing( const char* pName); void TestClosing( const char* pName);
@ -168,6 +244,12 @@ protected:
/** Calculates the resulting transformation fromm all the given transform steps */ /** Calculates the resulting transformation fromm all the given transform steps */
aiMatrix4x4 CalculateResultTransform( const std::vector<Transform>& pTransforms) const; 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: protected:
/** Filename, for a verbose error message */ /** Filename, for a verbose error message */
std::string mFileName; std::string mFileName;
@ -175,6 +257,18 @@ protected:
/** XML reader */ /** XML reader */
irr::io::IrrXMLReader* mReader; 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 */ /** node library: root node of the hierarchy part by ID */
typedef std::map<std::string, Node*> NodeLibrary; typedef std::map<std::string, Node*> NodeLibrary;
NodeLibrary mNodeLibrary; NodeLibrary mNodeLibrary;
@ -189,6 +283,17 @@ protected:
enum { UP_X, UP_Y, UP_Z } mUpDirection; 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 } // end of namespace Assimp
#endif // AI_COLLADAPARSER_H_INC #endif // AI_COLLADAPARSER_H_INC

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

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>

File diff suppressed because one or more lines are too long

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

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