- further Collada work: materials are now loaded from profile_COMMON, meshes are properly split up at material borders

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@260 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
ulfjorensen 2008-12-04 17:06:26 +00:00
parent d320a4bc64
commit 917db45b3c
9 changed files with 526 additions and 161 deletions

View File

@ -44,38 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ASSIMP_INTERNAL_BUILD
#ifdef ASSIMP_BUILD_DLL_EXPORT
# if _MSC_VER >= 1400
# pragma message( "AssimpBuild: Building Windows DLL" )
# endif
#endif
// *******************************************************************
// Print detailled memory allocation statistics? In this case we'll
// need to overload all C++ memory management functions. It is assumed
// that old C routines, such as malloc(), are NOT used in Assimp.
// *******************************************************************
#ifdef ASSIMP_BUILD_MEMORY_STATISTICS
void *operator new (size_t);
void operator delete (void *);
void *operator new[] (size_t);
void operator delete[] (void *);
# if _MSC_VER >= 1400
# pragma message( "AssimpBuild: Memory tracking enabled" )
# endif
#endif
#if _MSC_VER >= 1400
# ifdef _DEBUG
# pragma message( "AssimpBuild: Debug build" )
# else
# pragma message( "AssimpBuild: Release build" )
# endif
#endif
// *******************************************************************
// If we have at least VC8 some C string manipulation functions
// are mapped to their safe _s counterparts (e.g. _itoa_s).
@ -98,7 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <queue>
#include <iostream>
#include <algorithm>
#include <numeric>
// *******************************************************************
// public ASSIMP headers
@ -124,10 +92,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *******************************************************************
#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
#if _MSC_VER >= 1400
# pragma message( "AssimpBuild: Using -noBoost workaround" )
#endif
# include "../include/BoostWorkaround/boost/scoped_ptr.hpp"
# include "../include/BoostWorkaround/boost/scoped_array.hpp"
# include "../include/BoostWorkaround/boost/format.hpp"
@ -135,10 +99,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#else
#if _MSC_VER >= 1400
# pragma message( "AssimpBuild: Using standard boost headers" )
#endif
# include <boost/scoped_ptr.hpp>
# include <boost/scoped_array.hpp>
# include <boost/format.hpp>

View File

@ -144,6 +144,13 @@ struct InputChannel
InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
};
/** Subset of a mesh with a certain material */
struct SubMesh
{
std::string mMaterial; ///< subgroup identifier
size_t mNumFaces; ///< number of faces in this submesh
};
/** Contains data for a single mesh */
struct Mesh
{
@ -158,6 +165,9 @@ struct Mesh
// Faces. Stored are only the number of vertices for each face. 1 == point, 2 == line, 3 == triangle, 4+ == poly
std::vector<size_t> mFaceSize;
// Submeshes in this mesh, each with a given material
std::vector<SubMesh> mSubMeshes;
};
/** Which type of primitives the ReadPrimitives() function is going to read */
@ -179,6 +189,20 @@ struct Material
std::string mEffect;
};
/** Type of the effect param */
enum ParamType
{
Param_Sampler,
Param_Surface
};
/** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
struct EffectParam
{
ParamType mType;
std::string mReference; // to which other thing the param is referring to.
};
/** Shading type supported by the standard effect spec of Collada */
enum ShadeType
{
@ -194,18 +218,25 @@ enum ShadeType
struct Effect
{
ShadeType mShadeType;
aiColor4D mEmmisive, mAmbient, mDiffuse, mSpecular;
aiColor4D mReflectivity, mRefractivity;
std::string mTexEmmisive, mTexAmbient, mTexDiffuse, mTexSpecular;
aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular;
aiColor4D mReflective, mRefractive;
std::string mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular;
float mShininess, mRefractIndex;
float mReflectivity, mRefractivity;
Effect() : mEmmisive( 0, 0, 0, 1), mAmbient( 0.1f, 0.1f, 0.1f, 1),
// local params referring to each other by their SID
typedef std::map<std::string, Collada::EffectParam> ParamLibrary;
ParamLibrary mParams;
Effect() : mEmissive( 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)
mReflective( 0, 0, 0, 0), mRefractive( 0, 0, 0, 0)
{
mShadeType = Shade_Phong;
mShininess = 10;
mRefractIndex = 1;
mShininess = 10.0f;
mRefractIndex = 1.0f;
mReflectivity = 0.0f;
mRefractivity = 0.0f;
}
};

View File

@ -87,6 +87,12 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// parse the input file
ColladaParser parser( pFile);
if( !parser.mRootNode)
throw new ImportErrorException( "File came out empty. Somethings wrong here.");
// create the materials first, for the meshes to find
BuildMaterials( parser, pScene);
// build the node hierarchy from it
pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode);
@ -107,23 +113,6 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// store all meshes
StoreSceneMeshes( pScene);
// create dummy material
Assimp::MaterialHelper* mat = new Assimp::MaterialHelper;
aiString name( std::string( "dummy"));
mat->AddProperty( &name, AI_MATKEY_NAME);
int shadeMode = aiShadingMode_Phong;
mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
aiColor4D colAmbient( 0.2f, 0.2f, 0.2f, 1.0f), colDiffuse( 0.8f, 0.8f, 0.8f, 1.0f), colSpecular( 0.5f, 0.5f, 0.5f, 0.5f);
mat->AddProperty( &colAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty( &colDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty( &colSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
float specExp = 5.0f;
mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS);
pScene->mNumMaterials = 1;
pScene->mMaterials = new aiMaterial*[1];
pScene->mMaterials[0] = mat;
}
// ------------------------------------------------------------------------------------------------
@ -168,70 +157,100 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
DefaultLogger::get()->warn( boost::str( boost::format( "Unable to find geometry for ID \"%s\". Skipping.") % mid.mMesh));
continue;
}
const Collada::Mesh* srcMesh = srcMeshIt->second;
// 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.mMesh);
if( dstMeshIt != mMeshIndexbyID.end())
// build a mesh for each of its subgroups
size_t vertexStart = 0, faceStart = 0;
for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm)
{
newMeshRefs.push_back( dstMeshIt->second);
} else
{
// else we have to add the mesh to the collection and store its newly assigned index at the node
aiMesh* dstMesh = new aiMesh;
const Collada::Mesh* srcMesh = srcMeshIt->second;
const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm];
// find material assigned to this submesh
std::map<std::string, std::string>::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial);
std::string meshMaterial;
if( meshMatIt != mid.mMaterials.end())
meshMaterial = meshMatIt->second;
else
DefaultLogger::get()->warn( boost::str( boost::format( "No material specified for subgroup \"%s\" in geometry \"%s\".") % submesh.mMaterial % mid.mMesh));
// copy positions
dstMesh->mNumVertices = srcMesh->mPositions.size();
dstMesh->mVertices = new aiVector3D[dstMesh->mNumVertices];
std::copy( srcMesh->mPositions.begin(), srcMesh->mPositions.end(), dstMesh->mVertices);
// built lookup index of the Mesh-Submesh-Material combination
ColladaMeshIndex index( mid.mMesh, sm, meshMaterial);
// normals, if given. HACK: (thom) Due to the fucking Collada spec we never know if we have the same
// number of normals as there are positions. So we also ignore any vertex attribute if it has a different count
if( srcMesh->mNormals.size() == dstMesh->mNumVertices)
// if we already have the mesh at the library, just add its index to the node's array
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index);
if( dstMeshIt != mMeshIndexByID.end())
{
dstMesh->mNormals = new aiVector3D[dstMesh->mNumVertices];
std::copy( srcMesh->mNormals.begin(), srcMesh->mNormals.end(), dstMesh->mNormals);
}
// same for texturecoords, as many as we have
for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
newMeshRefs.push_back( dstMeshIt->second);
} else
{
if( srcMesh->mTexCoords[a].size() == dstMesh->mNumVertices)
// else we have to add the mesh to the collection and store its newly assigned index at the node
aiMesh* dstMesh = new aiMesh;
// count the vertices addressed by its faces
size_t numVertices =
std::accumulate( srcMesh->mFaceSize.begin() + faceStart, srcMesh->mFaceSize.begin() + faceStart + submesh.mNumFaces, 0);
// copy positions
dstMesh->mNumVertices = numVertices;
dstMesh->mVertices = new aiVector3D[numVertices];
std::copy( srcMesh->mPositions.begin() + vertexStart, srcMesh->mPositions.begin() + vertexStart + numVertices, dstMesh->mVertices);
// normals, if given. HACK: (thom) Due to the fucking Collada spec we never know if we have the same
// number of normals as there are positions. So we also ignore any vertex attribute if it has a different count
if( srcMesh->mNormals.size() == srcMesh->mPositions.size())
{
dstMesh->mTextureCoords[a] = new aiVector3D[dstMesh->mNumVertices];
for( size_t b = 0; b < dstMesh->mNumVertices; ++b)
dstMesh->mTextureCoords[a][b].Set( srcMesh->mTexCoords[a][b].x, srcMesh->mTexCoords[a][b].y, 0.0f);
dstMesh->mNumUVComponents[a] = 2;
dstMesh->mNormals = new aiVector3D[numVertices];
std::copy( srcMesh->mNormals.begin() + vertexStart, srcMesh->mNormals.begin() + vertexStart + numVertices, dstMesh->mNormals);
}
}
// same for vertex colors, as many as we have
for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
{
if( srcMesh->mColors[a].size() == dstMesh->mNumVertices)
// same for texturecoords, as many as we have
for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)
{
dstMesh->mColors[a] = new aiColor4D[dstMesh->mNumVertices];
std::copy( srcMesh->mColors[a].begin(), srcMesh->mColors[a].end(), dstMesh->mColors[a]);
if( srcMesh->mTexCoords[a].size() == srcMesh->mPositions.size())
{
dstMesh->mTextureCoords[a] = new aiVector3D[numVertices];
for( size_t b = vertexStart; b < vertexStart + numVertices; ++b)
dstMesh->mTextureCoords[a][b].Set( srcMesh->mTexCoords[a][b].x, srcMesh->mTexCoords[a][b].y, 0.0f);
dstMesh->mNumUVComponents[a] = 2;
}
}
}
// create faces. Due to the fact that each face uses unique vertices, we can simply count up on each vertex
size_t vertex = 0;
dstMesh->mNumFaces = srcMesh->mFaceSize.size();
dstMesh->mFaces = new aiFace[dstMesh->mNumFaces];
for( size_t a = 0; a < dstMesh->mNumFaces; ++a)
{
size_t s = srcMesh->mFaceSize[a];
aiFace& face = dstMesh->mFaces[a];
face.mNumIndices = s;
face.mIndices = new unsigned int[s];
for( size_t b = 0; b < s; ++b)
face.mIndices[b] = vertex++;
}
// same for vertex colors, as many as we have
for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++)
{
if( srcMesh->mColors[a].size() == srcMesh->mPositions.size())
{
dstMesh->mColors[a] = new aiColor4D[numVertices];
std::copy( srcMesh->mColors[a].begin() + vertexStart, srcMesh->mColors[a].begin() + vertexStart + numVertices, dstMesh->mColors[a]);
}
}
// store the mesh, and store its new index in the node
newMeshRefs.push_back( mMeshes.size());
mMeshes.push_back( dstMesh);
// create faces. Due to the fact that each face uses unique vertices, we can simply count up on each vertex
size_t vertex = 0;
dstMesh->mNumFaces = submesh.mNumFaces;
dstMesh->mFaces = new aiFace[dstMesh->mNumFaces];
for( size_t a = 0; a < dstMesh->mNumFaces; ++a)
{
size_t s = srcMesh->mFaceSize[ faceStart + a];
aiFace& face = dstMesh->mFaces[a];
face.mNumIndices = s;
face.mIndices = new unsigned int[s];
for( size_t b = 0; b < s; ++b)
face.mIndices[b] = vertex++;
}
// store the mesh, and store its new index in the node
newMeshRefs.push_back( mMeshes.size());
mMeshIndexByID[index] = mMeshes.size();
mMeshes.push_back( dstMesh);
vertexStart += numVertices; faceStart += submesh.mNumFaces;
// assign the material index
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial);
if( matIt != mMaterialIndexByName.end())
dstMesh->mMaterialIndex = matIt->second;
else
dstMesh->mMaterialIndex = 0;
}
}
}
@ -255,3 +274,106 @@ void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
}
}
// ------------------------------------------------------------------------------------------------
// Constructs materials from the collada material definitions
void ColladaLoader::BuildMaterials( const ColladaParser& pParser, aiScene* pScene)
{
std::vector<aiMaterial*> newMats;
for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); matIt != pParser.mMaterialLibrary.end(); ++matIt)
{
const Collada::Material& material = matIt->second;
// a material is only a reference to an effect
ColladaParser::EffectLibrary::const_iterator effIt = pParser.mEffectLibrary.find( material.mEffect);
if( effIt == pParser.mEffectLibrary.end())
continue;
const Collada::Effect& effect = effIt->second;
// create material
Assimp::MaterialHelper* mat = new Assimp::MaterialHelper;
aiString name( matIt->first);
mat->AddProperty( &name, AI_MATKEY_NAME);
int shadeMode;
switch( effect.mShadeType)
{
case Collada::Shade_Constant: shadeMode = aiShadingMode_NoShading; break;
case Collada::Shade_Lambert: shadeMode = aiShadingMode_Gouraud; break;
case Collada::Shade_Blinn: shadeMode = aiShadingMode_Blinn; break;
default: shadeMode = aiShadingMode_Phong; break;
}
mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
mat->AddProperty( &effect.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty( &effect.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty( &effect.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
mat->AddProperty( &effect.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
mat->AddProperty( &effect.mShininess, 1, AI_MATKEY_SHININESS);
mat->AddProperty( &effect.mRefractIndex, 1, AI_MATKEY_REFRACTI);
// add textures, if given
if( !effect.mTexAmbient.empty())
mat->AddProperty( &FindFilenameForEffectTexture( pParser, effect, effect.mTexAmbient), AI_MATKEY_TEXTURE_AMBIENT( 0));
if( !effect.mTexDiffuse.empty())
mat->AddProperty( &FindFilenameForEffectTexture( pParser, effect, effect.mTexDiffuse), AI_MATKEY_TEXTURE_DIFFUSE( 0));
if( !effect.mTexEmissive.empty())
mat->AddProperty( &FindFilenameForEffectTexture( pParser, effect, effect.mTexEmissive), AI_MATKEY_TEXTURE_EMISSIVE( 0));
if( !effect.mTexSpecular.empty())
mat->AddProperty( &FindFilenameForEffectTexture( pParser, effect, effect.mTexSpecular), AI_MATKEY_TEXTURE_SPECULAR( 0));
// store the material
mMaterialIndexByName[matIt->first] = newMats.size();
newMats.push_back( mat);
}
// store a dummy material if none were given
if( newMats.size() == 0)
{
Assimp::MaterialHelper* mat = new Assimp::MaterialHelper;
aiString name( std::string( "dummy"));
mat->AddProperty( &name, AI_MATKEY_NAME);
int shadeMode = aiShadingMode_Phong;
mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
aiColor4D colAmbient( 0.2f, 0.2f, 0.2f, 1.0f), colDiffuse( 0.8f, 0.8f, 0.8f, 1.0f), colSpecular( 0.5f, 0.5f, 0.5f, 0.5f);
mat->AddProperty( &colAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
mat->AddProperty( &colDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty( &colSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
float specExp = 5.0f;
mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS);
}
// store the materials in the scene
pScene->mNumMaterials = newMats.size();
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
std::copy( newMats.begin(), newMats.end(), pScene->mMaterials);
}
// ------------------------------------------------------------------------------------------------
// Resolves the texture name for the given effect texture entry
const aiString& ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser, const Collada::Effect& pEffect, const std::string& pName)
{
// recurse through the param references until we end up at an image
std::string name = pName;
while( 1)
{
// the given string is a param entry. Find it
Collada::Effect::ParamLibrary::const_iterator it = pEffect.mParams.find( name);
// if not found, we're at the end of the recursion. The resulting string should be the image ID
if( it == pEffect.mParams.end())
break;
// else recurse on
name = it->second.mReference;
}
// find the image referred by this name in the image library of the scene
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
if( imIt == pParser.mImageLibrary.end())
throw new ImportErrorException( boost::str( boost::format( "Unable to resolve effect texture entry \"%s\", ended up at ID \"%s\".") % pName % name));
static aiString result;
result.Set( imIt->second.mFileName);
return result;
}

View File

@ -49,6 +49,30 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp
{
struct ColladaMeshIndex
{
std::string mMeshID;
size_t mSubMesh;
std::string mMaterial;
ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial)
: mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial)
{ }
bool operator < (const ColladaMeshIndex& p) const
{
if( mMeshID == p.mMeshID)
{
if( mSubMesh == p.mSubMesh)
return mMaterial < p.mMaterial;
else
return mSubMesh < p.mSubMesh;
} else
{
return mMeshID < p.mMeshID;
}
}
};
/** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing
* more useless stuff, so I limited the data to what I think is useful for games.
*/
@ -91,12 +115,21 @@ protected:
/** Stores all meshes in the given scene */
void StoreSceneMeshes( aiScene* pScene);
/** Constructs materials from the collada material definitions */
void BuildMaterials( const ColladaParser& pParser, aiScene* pScene);
/** Resolves the texture name for the given effect texture entry */
const aiString& FindFilenameForEffectTexture( const ColladaParser& pParser, const Collada::Effect& pEffect, const std::string& pName);
protected:
/** Filename, for a verbose error message */
std::string mFileName;
/** Which mesh-material compound was stored under which mesh ID */
std::map<std::string, size_t> mMeshIndexbyID;
std::map<ColladaMeshIndex, size_t> mMeshIndexByID;
/** Which material was stored under which index in the scene */
std::map<std::string, size_t> mMaterialIndexByName;
/** Accumulated meshes for the target scene */
std::vector<aiMesh*> mMeshes;

View File

@ -112,6 +112,12 @@ void ColladaParser::ReadStructure()
{
if( IsElement( "asset"))
ReadAssetInfo();
else if( IsElement( "library_images"))
ReadImageLibrary();
else if( IsElement( "library_materials"))
ReadMaterialLibrary();
else if( IsElement( "library_effects"))
ReadEffectLibrary();
else if( IsElement( "library_geometries"))
ReadGeometryLibrary();
else if( IsElement( "library_visual_scenes"))
@ -289,7 +295,7 @@ void ColladaParser::ReadMaterial( Collada::Material& pMaterial)
if( url[0] != '#')
ThrowException( "Unknown reference format");
pMaterial.mEffect = url;
pMaterial.mEffect = url+1;
SkipElement();
} else
@ -312,12 +318,214 @@ void ColladaParser::ReadMaterial( Collada::Material& pMaterial)
// Reads the effect library
void ColladaParser::ReadEffectLibrary()
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "effect"))
{
// read ID. Do I have to repeat my ranting about "optional" attributes?
int attrID = GetAttribute( "id");
std::string id = mReader->getAttributeValue( attrID);
// create an entry and store it in the library under its ID
mEffectLibrary[id] = Effect();
// read on from there
ReadEffect( mEffectLibrary[id]);
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "library_effects") != 0)
ThrowException( "Expected end of \"library_effects\" element.");
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads an effect entry into the given effect
void ColladaParser::ReadEffect( Collada::Effect* pEffect)
void ColladaParser::ReadEffect( Collada::Effect& pEffect)
{
// for the moment we don't support any other type of effect.
// TODO: (thom) Rewrite this so that it ignores the whole effect instead of bailing out
TestOpening( "profile_COMMON");
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "newparam"))
{
// save ID
int attrSID = GetAttribute( "sid");
std::string sid = mReader->getAttributeValue( attrSID);
pEffect.mParams[sid] = EffectParam();
ReadEffectParam( pEffect.mParams[sid]);
}
else if( IsElement( "technique"))
{
// just syntactic sugar
}
else if( IsElement( "phong"))
pEffect.mShadeType = Shade_Phong;
else if( IsElement( "constant"))
pEffect.mShadeType = Shade_Constant;
else if( IsElement( "lambert"))
pEffect.mShadeType = Shade_Lambert;
else if( IsElement( "blinn"))
pEffect.mShadeType = Shade_Blinn;
else if( IsElement( "emission"))
ReadEffectColor( pEffect.mEmissive, pEffect.mTexEmissive);
else if( IsElement( "ambient"))
ReadEffectColor( pEffect.mAmbient, pEffect.mTexAmbient);
else if( IsElement( "diffuse"))
ReadEffectColor( pEffect.mDiffuse, pEffect.mTexDiffuse);
else if( IsElement( "specular"))
ReadEffectColor( pEffect.mSpecular, pEffect.mTexSpecular);
else if( IsElement( "reflective"))
ReadEffectColor( pEffect.mReflective, std::string());
else if( IsElement( "transparent"))
ReadEffectColor( pEffect.mRefractive, std::string());
else if( IsElement( "shininess"))
ReadEffectFloat( pEffect.mShininess);
else if( IsElement( "reflectivity"))
ReadEffectFloat( pEffect.mReflectivity);
else if( IsElement( "transparency"))
ReadEffectFloat( pEffect.mRefractivity);
else if( IsElement( "index_of_refraction"))
ReadEffectFloat( pEffect.mRefractIndex);
else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "effect") == 0)
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads an effect entry containing a color or a texture defining that color
void ColladaParser::ReadEffectColor( aiColor4D& pColor, std::string& pSampler)
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "color"))
{
// text content contains 4 floats
const char* content = GetTextContent();
content = fast_atof_move( content, pColor.r);
SkipSpacesAndLineEnd( &content);
content = fast_atof_move( content, pColor.g);
SkipSpacesAndLineEnd( &content);
content = fast_atof_move( content, pColor.b);
SkipSpacesAndLineEnd( &content);
content = fast_atof_move( content, pColor.a);
SkipSpacesAndLineEnd( &content);
TestClosing( "color");
}
else if( IsElement( "texture"))
{
int attrTex = GetAttribute( "texture");
pSampler = mReader->getAttributeValue( attrTex);
SkipElement();
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads an effect entry containing a float
void ColladaParser::ReadEffectFloat( float& pFloat)
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "float"))
{
// text content contains a single floats
const char* content = GetTextContent();
content = fast_atof_move( content, pFloat);
SkipSpacesAndLineEnd( &content);
TestClosing( "float");
} else
{
// ignore the rest
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
break;
}
}
}
// ------------------------------------------------------------------------------------------------
// Reads an effect parameter specification of any kind
void ColladaParser::ReadEffectParam( Collada::EffectParam& pParam)
{
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
if( IsElement( "surface"))
{
// image ID given inside <init_from> tags
TestOpening( "init_from");
const char* content = GetTextContent();
pParam.mType = Param_Surface;
pParam.mReference = content;
TestClosing( "init_from");
// don't care for remaining stuff
SkipElement( "surface");
}
else if( IsElement( "sampler2D"))
{
// surface ID is given inside <source> tags
TestOpening( "source");
const char* content = GetTextContent();
pParam.mType = Param_Sampler;
pParam.mReference = content;
TestClosing( "source");
// don't care for remaining stuff
SkipElement( "sampler2D");
} else
{
// ignore unknown element
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
break;
}
}
}
// ------------------------------------------------------------------------------------------------
@ -584,6 +792,14 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
int attrCount = GetAttribute( "count");
size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount);
// material subgroup
int attrMaterial = TestAttribute( "material");
SubMesh subgroup;
if( attrMaterial > -1)
subgroup.mMaterial = mReader->getAttributeValue( attrMaterial);
subgroup.mNumFaces = numPrimitives;
pMesh->mSubMeshes.push_back( subgroup);
// distinguish between polys and triangles
std::string elementName = mReader->getNodeName();
PrimitiveType primType = Prim_Invalid;
@ -1020,36 +1236,36 @@ void ColladaParser::ReadNodeGeometry( Node* pNode)
Collada::MeshInstance instance;
instance.mMesh = url+1; // skipping the leading #
// read material associations. Ignore additional elements inbetween
while( mReader->read())
if( !mReader->isEmptyElement())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
// read material associations. Ignore additional elements inbetween
while( mReader->read())
{
if( IsElement( "instance_material"))
if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
{
// 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);
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 = urlMat+1;
// store the association
instance.mMaterials[group] = mat;
} else
// store the association
instance.mMaterials[group] = mat;
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
SkipElement();
}
}
else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
{
if( strcmp( mReader->getNodeName(), "instance_geometry") == 0)
break;
}
if( strcmp( mReader->getNodeName(), "instance_geometry") == 0)
break;
}
}
}
// store it
pNode->mMeshes.push_back( instance);
}
@ -1106,9 +1322,17 @@ void ColladaParser::SkipElement()
if( mReader->isEmptyElement())
return;
// reroute
SkipElement( mReader->getNodeName());
}
// ------------------------------------------------------------------------------------------------
// Skips all data until the end node of the given element
void ColladaParser::SkipElement( const char* pElement)
{
// copy the current node's name because it'a pointer to the reader's internal buffer,
// which is going to change with the upcoming parsing
std::string element = mReader->getNodeName();
std::string element = pElement;
while( mReader->read())
{
if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)

View File

@ -88,7 +88,15 @@ protected:
void ReadEffectLibrary();
/** Reads an effect entry into the given effect*/
void ReadEffect( Collada::Effect* pEffect);
void ReadEffect( Collada::Effect& pEffect);
/** Reads an effect entry containing a color or a texture defining that color */
void ReadEffectColor( aiColor4D& pColor, std::string& pSampler);
/** Reads an effect entry containing a float */
void ReadEffectFloat( float& pFloat);
/** Reads an effect parameter specification of any kind */
void ReadEffectParam( Collada::EffectParam& pParam);
/** Reads the geometry library contents */
void ReadGeometryLibrary();
@ -142,6 +150,9 @@ protected:
/** Skips all data until the end node of the current element */
void SkipElement();
/** Skips all data until the end node of the given element */
void SkipElement( const char* pElement);
/** 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; }

View File

@ -541,10 +541,8 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
// put a large try block around everything to catch all std::exception's
// that might be thrown by STL containers or by new().
// ImportErrorException's are throw by ourselves and caught elsewhere.
#ifndef _DEBUG
try
{
#endif
// check whether this Importer instance has already loaded
// a scene. In this case we need to delete the old one
if (this->mScene)
@ -644,7 +642,6 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
// clear any data allocated by post-process steps
mPPShared->Clean();
#ifndef _DEBUG
}
catch (std::exception &e)
{
@ -659,7 +656,6 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags
DefaultLogger::get()->error(mErrorString);
delete mScene;mScene = NULL;
}
#endif
// either successful or failure - the pointer expresses it anyways
return mScene;

View File

@ -59,20 +59,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------
#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
#if _MSC_VER >= 1400
# pragma message( "AssimpBuild: Using -noBoost workaround for boost::random" )
#endif
# include "../include/BoostWorkaround/boost/random/uniform_int.hpp"
# include "../include/BoostWorkaround/boost/random/variate_generator.hpp"
# include "../include/BoostWorkaround/boost/random/mersenne_twister.hpp"
#else
#if _MSC_VER >= 1400
# pragma message( "AssimpBuild: Using standard boost headers for boost::random" )
#endif
# include <boost/random/uniform_int.hpp>
# include <boost/random/variate_generator.hpp>
# include <boost/random/mersenne_twister.hpp>

View File

@ -2,10 +2,6 @@
#ifndef BOOST_MT_INCLUDED
#define BOOST_MT_INCLUDED
#if _MSC_VER >= 1400
# pragma message( "AssimpBuild: Using CRT's rand() as replacement for mt19937" )
#endif
namespace boost
{