- corrected example code in the documentation. Thanks to Ingrater to point it out.

- Further work on the Collada loader. Halve way through the material import, I have to leave it here and continue at home.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@253 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
ulfjorensen 2008-11-27 15:54:35 +00:00
parent 9fc698bb2f
commit 5639220859
5 changed files with 268 additions and 11 deletions

View File

@ -66,6 +66,13 @@ struct Transform
float f[16]; ///< Interpretation of data depends on the type of the transformation float f[16]; ///< Interpretation of data depends on the type of the transformation
}; };
/** A reference to a mesh inside a node, including materials assigned to the various subgroups */
struct MeshInstance
{
std::string mMesh; ///< ID of the mesh
std::map<std::string, std::string> mMaterials; ///< Map of materials by the subgroup ID they're applied to
};
/** A node in a scene hierarchy */ /** A node in a scene hierarchy */
struct Node struct Node
{ {
@ -77,7 +84,7 @@ struct Node
/** Operations in order to calculate the resulting transformation to parent. */ /** Operations in order to calculate the resulting transformation to parent. */
std::vector<Transform> mTransforms; std::vector<Transform> mTransforms;
std::vector<std::string> mMeshes; ///< Meshes at this node std::vector<MeshInstance> mMeshes; ///< Meshes at this node
Node() { mParent = NULL; } Node() { mParent = NULL; }
~Node() { for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) delete *it; } ~Node() { for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) delete *it; }
@ -166,6 +173,48 @@ enum PrimitiveType
Prim_Polygon Prim_Polygon
}; };
/** A collada material. Pretty much the only member is a reference to an effect. */
struct Material
{
std::string mEffect;
};
/** Shading type supported by the standard effect spec of Collada */
enum ShadeType
{
Shade_Invalid,
Shade_Constant,
Shade_Lambert,
Shade_Phong,
Shade_Blinn
};
/** A collada effect. Can contain about anything according to the Collada spec, but we limit our version to a reasonable subset. */
struct Effect
{
ShadeType mShadeType;
aiColor4D mEmmisive, mAmbient, mDiffuse, mSpecular;
aiColor4D mReflectivity, mRefractivity;
std::string mTexEmmisive, mTexAmbient, mTexDiffuse, mTexSpecular;
float mShininess, mRefractIndex;
Effect() : mEmmisive( 0, 0, 0, 1), mAmbient( 0.1f, 0.1f, 0.1f, 1),
mDiffuse( 0.6f, 0.6f, 0.6f, 1), mSpecular( 0.4f, 0.4f, 0.4f, 1),
mReflectivity( 0, 0, 0, 0), mRefractivity( 0, 0, 0, 0)
{
mShadeType = Shade_Phong;
mShininess = 10;
mRefractIndex = 1;
}
};
/** An image, meaning texture */
struct Image
{
std::string mFileName;
};
} // end of namespace Collada } // end of namespace Collada
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -159,18 +159,18 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
std::vector<size_t> newMeshRefs; std::vector<size_t> newMeshRefs;
// for the moment we simply ignore all material tags and transfer the meshes one by one // for the moment we simply ignore all material tags and transfer the meshes one by one
BOOST_FOREACH( const std::string& mid, pNode->mMeshes) BOOST_FOREACH( const Collada::MeshInstance& mid, pNode->mMeshes)
{ {
// find the referred mesh // find the referred mesh
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid); ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMesh);
if( srcMeshIt == pParser.mMeshLibrary.end()) if( srcMeshIt == pParser.mMeshLibrary.end())
{ {
DefaultLogger::get()->warn( boost::str( boost::format( "Unable to find geometry for ID \"%s\". Skipping.") % mid)); DefaultLogger::get()->warn( boost::str( boost::format( "Unable to find geometry for ID \"%s\". Skipping.") % mid.mMesh));
continue; continue;
} }
// if we already have the mesh at the library, just add its index to the node's array // if we already have the mesh at the library, just add its index to the node's array
std::map<std::string, size_t>::const_iterator dstMeshIt = mMeshIndexbyID.find( mid); std::map<std::string, size_t>::const_iterator dstMeshIt = mMeshIndexbyID.find( mid.mMesh);
if( dstMeshIt != mMeshIndexbyID.end()) if( dstMeshIt != mMeshIndexbyID.end())
{ {
newMeshRefs.push_back( dstMeshIt->second); newMeshRefs.push_back( dstMeshIt->second);

View File

@ -174,6 +174,152 @@ void ColladaParser::ReadAssetInfo()
} }
} }
// ------------------------------------------------------------------------------------------------
// Reads the image library contents
void ColladaParser::ReadImageLibrary()
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "image"))
{
// read ID. Another entry which is "optional" by design but obligatory in reality
int attrID = GetAttribute( "id");
std::string id = mReader->getAttributeValue( attrID);
// create an entry and store it in the library under its ID
mImageLibrary[id] = Image();
// read on from there
ReadImage( mImageLibrary[id]);
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "library_images") != 0)
ThrowException( "Expected end of \"library_images\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads an image entry into the given image
void ColladaParser::ReadImage( Collada::Image& pImage)
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "init_from"))
{
// element content is filename - hopefully
const char* content = GetTextContent();
pImage.mFileName = content;
TestClosing( "init_from");
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "image") != 0)
ThrowException( "Expected end of \"image\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads the material library
void ColladaParser::ReadMaterialLibrary()
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "material"))
{
// read ID. By now you propably know my opinion about this "specification"
int attrID = GetAttribute( "id");
std::string id = mReader->getAttributeValue( attrID);
// create an entry and store it in the library under its ID
mMaterialLibrary[id] = Material();
// read on from there
ReadMaterial( mMaterialLibrary[id]);
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "library_materials") != 0)
ThrowException( "Expected end of \"library_materials\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads a material entry into the given material
void ColladaParser::ReadMaterial( Collada::Material& pMaterial)
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "instance_effect"))
{
// referred effect by URL
int attrUrl = GetAttribute( "url");
const char* url = mReader->getAttributeValue( attrUrl);
if( url[0] != '#')
ThrowException( "Unknown reference format");
pMaterial.mEffect = url;
SkipElement();
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "material") != 0)
ThrowException( "Expected end of \"image\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads the effect library
void ColladaParser::ReadEffectLibrary()
{
}
// ------------------------------------------------------------------------------------------------
// Reads an effect entry into the given effect
void ColladaParser::ReadEffect( Collada::Effect* pEffect)
{
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the geometry library contents // Reads the geometry library contents
void ColladaParser::ReadGeometryLibrary() void ColladaParser::ReadGeometryLibrary()
@ -200,7 +346,7 @@ void ColladaParser::ReadGeometryLibrary()
// read on from there // read on from there
ReadMesh( mesh); ReadMesh( mesh);
// check for the closing tag of the outer <geometry" element, the inner closing of <mesh> has been consumed by ReadMesh() // check for the closing tag of the outer <geometry> element, the inner closing of <mesh> has been consumed by ReadMesh()
TestClosing( "geometry"); TestClosing( "geometry");
} else } else
{ {
@ -871,11 +1017,41 @@ void ColladaParser::ReadNodeGeometry( Node* pNode)
if( url[0] != '#') if( url[0] != '#')
ThrowException( "Unknown reference format"); ThrowException( "Unknown reference format");
// store the mesh ID Collada::MeshInstance instance;
pNode->mMeshes.push_back( std::string( url+1)); instance.mMesh = url+1; // skipping the leading #
// read material associations. Ignore additional elements inbetween
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "instance_material"))
{
// read ID of the geometry subgroup and the target material
int attrGroup = GetAttribute( "symbol");
std::string group = mReader->getAttributeValue( attrGroup);
int attrMaterial = GetAttribute( "target");
const char* urlMat = mReader->getAttributeValue( attrMaterial);
if( urlMat[0] != '#')
ThrowException( "Unknown reference format");
std::string mat = mReader->getAttributeValue( attrMaterial+1);
// store the association
instance.mMaterials[group] = mat;
} else
{
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "instance_geometry") == 0)
break;
}
}
// for the moment, skip the rest // store it
SkipElement(); pNode->mMeshes.push_back( instance);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -72,6 +72,24 @@ protected:
/** Reads asset informations such as coordinate system informations and legal blah */ /** Reads asset informations such as coordinate system informations and legal blah */
void ReadAssetInfo(); void ReadAssetInfo();
/** Reads the image library contents */
void ReadImageLibrary();
/** Reads an image entry into the given image */
void ReadImage( Collada::Image& pImage);
/** Reads the material library */
void ReadMaterialLibrary();
/** Reads a material entry into the given material */
void ReadMaterial( Collada::Material& pMaterial);
/** Reads the effect library */
void ReadEffectLibrary();
/** Reads an effect entry into the given effect*/
void ReadEffect( Collada::Effect* pEffect);
/** Reads the geometry library contents */ /** Reads the geometry library contents */
void ReadGeometryLibrary(); void ReadGeometryLibrary();
@ -174,6 +192,18 @@ protected:
typedef std::map<std::string, Collada::Node*> NodeLibrary; typedef std::map<std::string, Collada::Node*> NodeLibrary;
NodeLibrary mNodeLibrary; NodeLibrary mNodeLibrary;
/** Image library: stores texture properties by ID */
typedef std::map<std::string, Collada::Image> ImageLibrary;
ImageLibrary mImageLibrary;
/** Effect library: surface attributes by ID */
typedef std::map<std::string, Collada::Effect> EffectLibrary;
EffectLibrary mEffectLibrary;
/** Material library: surface material by ID */
typedef std::map<std::string, Collada::Material> MaterialLibrary;
MaterialLibrary mMaterialLibrary;
/** Pointer to the root node. Don't delete, it just points to one of the nodes in the node library. */ /** Pointer to the root node. Don't delete, it just points to one of the nodes in the node library. */
Collada::Node* mRootNode; Collada::Node* mRootNode;

View File

@ -135,6 +135,7 @@ C++ example:
@code @code
#include <assimp.hpp> // C++ importer interface #include <assimp.hpp> // C++ importer interface
#include <aiScene.h> // root structure of the imported data #include <aiScene.h> // root structure of the imported data
#include <aiPostProcess.h> // Post processing flags
#include <aiMesh.h> // example: mesh data structures. you'll propably need other includes, too #include <aiMesh.h> // example: mesh data structures. you'll propably need other includes, too
bool DoTheImportThing( const std::string& pFile) bool DoTheImportThing( const std::string& pFile)
@ -148,7 +149,7 @@ bool DoTheImportThing( const std::string& pFile)
// if the import failed, report it // if the import failed, report it
if( !scene) if( !scene)
{ {
DoTheErrorLogging( importer.GetErrorText()); DoTheErrorLogging( importer.GetErrorString());
return false; return false;
} }
@ -177,6 +178,7 @@ C example:
@code @code
#include <assimp.h> // Plain C importer interface #include <assimp.h> // Plain C importer interface
#include <aiScene.h> // Root structure of the imported data #include <aiScene.h> // Root structure of the imported data
#include <aiPostProcess.h> // Post processing flags
#include <aiMesh.h> // Example: mesh data structures. you'll propably need other includes, too #include <aiMesh.h> // Example: mesh data structures. you'll propably need other includes, too
bool DoTheImportThing( const char* pFile) bool DoTheImportThing( const char* pFile)