- finalized Collada mesh part - can read static models now, using dummy materials
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@246 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
fe3c008301
commit
78969d0a95
|
@ -90,7 +90,25 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
|
||||||
// build the node hierarchy from it
|
// build the node hierarchy from it
|
||||||
pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode);
|
pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode);
|
||||||
|
|
||||||
pScene->mFlags = AI_SCENE_FLAGS_INCOMPLETE;
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -112,5 +130,113 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
|
||||||
node->mChildren[a]->mParent = node;
|
node->mChildren[a]->mParent = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// construct meshes
|
||||||
|
BuildMeshesForNode( pParser, pNode, node);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Builds meshes for the given node and references them
|
||||||
|
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const ColladaParser::Node* pNode, aiNode* pTarget)
|
||||||
|
{
|
||||||
|
// accumulated mesh references by this node
|
||||||
|
std::vector<size_t> newMeshRefs;
|
||||||
|
|
||||||
|
// for the moment we simply ignore all material tags and transfer the meshes one by one
|
||||||
|
BOOST_FOREACH( const std::string& mid, pNode->mMeshes)
|
||||||
|
{
|
||||||
|
// find the referred mesh
|
||||||
|
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid);
|
||||||
|
if( srcMeshIt == pParser.mMeshLibrary.end())
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn( boost::str( boost::format( "Unable to find geometry for ID \"%s\". Skipping.") % mid));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
if( dstMeshIt != mMeshIndexbyID.end())
|
||||||
|
{
|
||||||
|
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 ColladaParser::Mesh* srcMesh = srcMeshIt->second;
|
||||||
|
|
||||||
|
// copy positions
|
||||||
|
dstMesh->mNumVertices = srcMesh->mPositions.size();
|
||||||
|
dstMesh->mVertices = new aiVector3D[dstMesh->mNumVertices];
|
||||||
|
std::copy( srcMesh->mPositions.begin(), srcMesh->mPositions.end(), 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() == dstMesh->mNumVertices)
|
||||||
|
{
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
if( srcMesh->mTexCoords[a].size() == dstMesh->mNumVertices)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
dstMesh->mColors[a] = new aiColor4D[dstMesh->mNumVertices];
|
||||||
|
std::copy( srcMesh->mColors[a].begin(), srcMesh->mColors[a].end(), dstMesh->mColors[a]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store the mesh, and store its new index in the node
|
||||||
|
newMeshRefs.push_back( mMeshes.size());
|
||||||
|
mMeshes.push_back( dstMesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now place all mesh references we gathered in the target node
|
||||||
|
pTarget->mNumMeshes = newMeshRefs.size();
|
||||||
|
if( newMeshRefs.size())
|
||||||
|
{
|
||||||
|
pTarget->mMeshes = new size_t[pTarget->mNumMeshes];
|
||||||
|
std::copy( newMeshRefs.begin(), newMeshRefs.end(), pTarget->mMeshes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Stores all meshes in the given scene
|
||||||
|
void ColladaLoader::StoreSceneMeshes( aiScene* pScene)
|
||||||
|
{
|
||||||
|
pScene->mNumMeshes = mMeshes.size();
|
||||||
|
if( mMeshes.size() > 0)
|
||||||
|
{
|
||||||
|
pScene->mMeshes = new aiMesh*[mMeshes.size()];
|
||||||
|
std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -85,9 +85,21 @@ protected:
|
||||||
/** Recursively constructs a scene node for the given parser node and returns it. */
|
/** Recursively constructs a scene node for the given parser node and returns it. */
|
||||||
aiNode* BuildHierarchy( const ColladaParser& pParser, const ColladaParser::Node* pNode);
|
aiNode* BuildHierarchy( const ColladaParser& pParser, const ColladaParser::Node* pNode);
|
||||||
|
|
||||||
|
/** Builds meshes for the given node and references them */
|
||||||
|
void BuildMeshesForNode( const ColladaParser& pParser, const ColladaParser::Node* pNode, aiNode* pTarget);
|
||||||
|
|
||||||
|
/** Stores all meshes in the given scene */
|
||||||
|
void StoreSceneMeshes( aiScene* pScene);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Filename, for a verbose error message */
|
/** Filename, for a verbose error message */
|
||||||
std::string mFileName;
|
std::string mFileName;
|
||||||
|
|
||||||
|
/** Which mesh-material compound was stored under which mesh ID */
|
||||||
|
std::map<std::string, size_t> mMeshIndexbyID;
|
||||||
|
|
||||||
|
/** Accumulated meshes for the target scene */
|
||||||
|
std::vector<aiMesh*> mMeshes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -747,7 +747,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
|
||||||
child->mName = mReader->getAttributeValue( attrName);
|
child->mName = mReader->getAttributeValue( attrName);
|
||||||
|
|
||||||
// TODO: (thom) support SIDs
|
// TODO: (thom) support SIDs
|
||||||
assert( TestAttribute( "sid") == -1);
|
// assert( TestAttribute( "sid") == -1);
|
||||||
|
|
||||||
pNode->mChildren.push_back( child);
|
pNode->mChildren.push_back( child);
|
||||||
child->mParent = pNode;
|
child->mParent = pNode;
|
||||||
|
@ -759,6 +759,10 @@ void ColladaParser::ReadSceneNode( Node* pNode)
|
||||||
// test for it, in case we need to implement it
|
// test for it, in case we need to implement it
|
||||||
assert( false);
|
assert( false);
|
||||||
SkipElement();
|
SkipElement();
|
||||||
|
} else if( IsElement( "instance_geometry"))
|
||||||
|
{
|
||||||
|
// Reference to a mesh, we possible material associations
|
||||||
|
ReadNodeGeometry( pNode);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// skip everything else for the moment
|
// skip everything else for the moment
|
||||||
|
@ -800,6 +804,23 @@ void ColladaParser::ReadNodeTransformation( Node* pNode, TransformType pType)
|
||||||
TestClosing( tagName.c_str());
|
TestClosing( tagName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
// Reads a mesh reference in a node and adds it to the node's mesh list
|
||||||
|
void ColladaParser::ReadNodeGeometry( Node* pNode)
|
||||||
|
{
|
||||||
|
// referred mesh is given as an attribute of the <instance_geometry> element
|
||||||
|
int attrUrl = GetAttribute( "url");
|
||||||
|
const char* url = mReader->getAttributeValue( attrUrl);
|
||||||
|
if( url[0] != '#')
|
||||||
|
ThrowException( "Unknown reference format");
|
||||||
|
|
||||||
|
// store the mesh ID
|
||||||
|
pNode->mMeshes.push_back( std::string( url+1));
|
||||||
|
|
||||||
|
// for the moment, skip the rest
|
||||||
|
SkipElement();
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Reads the collada scene
|
// Reads the collada scene
|
||||||
void ColladaParser::ReadScene()
|
void ColladaParser::ReadScene()
|
||||||
|
|
|
@ -84,6 +84,8 @@ public:
|
||||||
/** 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
|
||||||
|
|
||||||
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; }
|
||||||
};
|
};
|
||||||
|
@ -213,6 +215,9 @@ protected:
|
||||||
/** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
|
/** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
|
||||||
void ReadNodeTransformation( Node* pNode, TransformType pType);
|
void ReadNodeTransformation( Node* pNode, TransformType pType);
|
||||||
|
|
||||||
|
/** Reads a mesh reference in a node and adds it to the node's mesh list */
|
||||||
|
void ReadNodeGeometry( Node* pNode);
|
||||||
|
|
||||||
/** Reads the collada scene */
|
/** Reads the collada scene */
|
||||||
void ReadScene();
|
void ReadScene();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue