Small update to the ASE loader.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@64 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2008-07-18 20:29:46 +00:00
parent fc8a8b54f9
commit 6ad0892396
11 changed files with 715 additions and 383 deletions

View File

@ -126,6 +126,7 @@ void ASEImporter::InternReadFile(
// allocate storage and copy the contents of the file to a memory buffer
// (terminate it with zero)
this->mBuffer = new unsigned char[fileSize+1];
this->pcScene = pScene;
file->Read( (void*)mBuffer, 1, fileSize);
this->mBuffer[fileSize] = '\0';
@ -135,10 +136,7 @@ void ASEImporter::InternReadFile(
// if absolutely no material has been loaded from the file
// we need to generate a default material
if (this->mParser->m_vMaterials.empty())
{
this->GenerateDefaultMaterial();
}
this->GenerateDefaultMaterial();
// process all meshes
std::vector<aiMesh*> avOutMeshes;
@ -165,17 +163,26 @@ void ASEImporter::InternReadFile(
this->ConvertMeshes(*i,avOutMeshes);
}
// now build the output mesh list
// now build the output mesh list. remove dummies
pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
pScene->mMeshes[i] = avOutMeshes[i];
aiMesh** pp = pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
for (std::vector<aiMesh*>::const_iterator
i = avOutMeshes.begin();
i != avOutMeshes.end();++i)
{
if (!(*i)->mNumFaces)continue;
*pp++ = *i;
}
pScene->mNumMeshes = (unsigned int)(pp - pScene->mMeshes);
// buil final material indices (remove submaterials and make the final list)
this->BuildMaterialIndices(pScene);
this->BuildMaterialIndices();
// build the final node graph
this->BuildNodes(pScene);
this->BuildNodes();
// build output animations
this->BuildAnimations();
// delete the ASE parser
delete this->mParser;
@ -187,28 +194,120 @@ void ASEImporter::GenerateDefaultMaterial()
{
ai_assert(NULL != this->mParser);
// add a simple material without sub materials to the parser's list
this->mParser->m_vMaterials.push_back ( ASE::Material() );
ASE::Material& mat = this->mParser->m_vMaterials.back();
bool bHas = false;
for (std::vector<ASE::Mesh>::iterator
i = this->mParser->m_vMeshes.begin();
i != this->mParser->m_vMeshes.end();++i)
{
if ((*i).bSkip)continue;
if (ASE::Face::DEFAULT_MATINDEX == (*i).iMaterialIndex)
{
(*i).iMaterialIndex = (unsigned int)this->mParser->m_vMaterials.size();
bHas = true;
}
}
if (bHas || this->mParser->m_vMaterials.empty())
{
// add a simple material without sub materials to the parser's list
this->mParser->m_vMaterials.push_back ( ASE::Material() );
ASE::Material& mat = this->mParser->m_vMaterials.back();
mat.mDiffuse = aiColor3D(0.5f,0.5f,0.5f);
mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
mat.mShading = Dot3DSFile::Gouraud;
mat.mName = AI_DEFAULT_MATERIAL_NAME;
mat.mDiffuse = aiColor3D(0.5f,0.5f,0.5f);
mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
mat.mShading = Dot3DSFile::Gouraud;
mat.mName = AI_DEFAULT_MATERIAL_NAME;
}
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes(aiScene* pcScene,aiNode* pcParent,
const char* szName)
void ASEImporter::BuildAnimations()
{
// check whether we have at least one mesh which has animations
std::vector<ASE::Mesh>::iterator i = this->mParser->m_vMeshes.begin();
unsigned int iNum = 0;
for (;i != this->mParser->m_vMeshes.end();++i)
{
if ((*i).bSkip)continue;
if ((*i).mAnim.akeyPositions.size() > 1 || (*i).mAnim.akeyRotations.size() > 1)
++iNum;
}
if (iNum)
{
this->pcScene->mNumAnimations = 1;
this->pcScene->mAnimations = new aiAnimation*[1];
aiAnimation* pcAnim = this->pcScene->mAnimations[0] = new aiAnimation();
pcAnim->mNumBones = iNum;
pcAnim->mBones = new aiBoneAnim*[iNum];
pcAnim->mTicksPerSecond = this->mParser->iFrameSpeed * this->mParser->iTicksPerFrame;
iNum = 0;
i = this->mParser->m_vMeshes.begin();
for (;i != this->mParser->m_vMeshes.end();++i)
{
if ((*i).bSkip)continue;
if ((*i).mAnim.akeyPositions.size() > 1 || (*i).mAnim.akeyRotations.size() > 1)
{
aiBoneAnim* pcBoneAnim = pcAnim->mBones[iNum++] = new aiBoneAnim();
pcBoneAnim->mBoneName.Set((*i).mName);
// copy position keys
if ((*i).mAnim.akeyPositions.size() > 1 )
{
pcBoneAnim->mNumPositionKeys = (unsigned int) (*i).mAnim.akeyPositions.size();
pcBoneAnim->mPositionKeys = new aiVectorKey[pcBoneAnim->mNumPositionKeys];
::memcpy(pcBoneAnim->mPositionKeys,&(*i).mAnim.akeyPositions[0],
pcBoneAnim->mNumPositionKeys * sizeof(aiVectorKey));
for (unsigned int qq = 0; qq < pcBoneAnim->mNumPositionKeys;++qq)
{
double dTime = pcBoneAnim->mPositionKeys[qq].mTime;
pcAnim->mDuration = std::max(pcAnim->mDuration,dTime);
}
}
// copy rotation keys
if ((*i).mAnim.akeyRotations.size() > 1 )
{
pcBoneAnim->mNumRotationKeys = (unsigned int) (*i).mAnim.akeyPositions.size();
pcBoneAnim->mRotationKeys = new aiQuatKey[pcBoneAnim->mNumPositionKeys];
::memcpy(pcBoneAnim->mRotationKeys,&(*i).mAnim.akeyRotations[0],
pcBoneAnim->mNumRotationKeys * sizeof(aiQuatKey));
for (unsigned int qq = 0; qq < pcBoneAnim->mNumRotationKeys;++qq)
{
double dTime = pcBoneAnim->mRotationKeys[qq].mTime;
pcAnim->mDuration = std::max(pcAnim->mDuration,dTime);
}
}
}
}
}
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes(aiNode* pcParent,const char* szName)
{
aiMatrix4x4 m;
ASE::DecompTransform dec(m);
this->AddNodes(pcParent,szName,dec);
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::AddNodes(aiNode* pcParent,const char* szName,
const ASE::DecompTransform& decompTrafo)
{
const size_t len = szName ? strlen(szName) : 0;
ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
std::vector<aiNode*> apcNodes;
aiMesh** pcMeshes = pcScene->mMeshes;
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
{
// get the name of the mesh ([0] = name, [1] = parent)
std::string* szMyName = (std::string*)pcScene->mMeshes[i]->mColors[1];
// get the name of the mesh
aiMesh* pcMesh = *pcMeshes++;
const ASE::Mesh& mesh = *((const ASE::Mesh*)pcMesh->mColors[2]);
// TODO: experimental quick'n'dirty, clean this up ...
std::string szMyName[2] = {mesh.mName,mesh.mParent} ;
if (!szMyName)
{
continue;
@ -226,25 +325,39 @@ void ASEImporter::AddNodes(aiScene* pcScene,aiNode* pcParent,
apcNodes.push_back(new aiNode());
aiNode* node = apcNodes.back();
// get the transformation matrix of the mesh
aiMatrix4x4* pmTransform = (aiMatrix4x4*)pcScene->mMeshes[i]->mColors[2];
node->mName.Set(szMyName[0]);
node->mNumMeshes = 1;
node->mMeshes = new unsigned int[1];
node->mMeshes[0] = i;
node->mParent = pcParent;
node->mTransformation = *pmTransform;
// delete the matrix (a mesh is always the child of ONE node, so this is safe)
delete pmTransform;
pcScene->mMeshes[i]->mColors[2] = NULL;
delete[] szMyName;
pcScene->mMeshes[i]->mColors[1] = NULL;
aiMatrix4x4 mParentAdjust = decompTrafo.mMatrix;
mParentAdjust.Inverse();
//if(ComputeLocalToWorldShift(mParentAdjust, decompTrafo, mesh.inherit))
{
node->mTransformation = mParentAdjust*mesh.mTransform;
}
//else node->mTransformation = mesh.mTransform;
// Transform all vertices of the mesh back into their local space ->
// at the moment they are pretransformed
aiMatrix4x4 mInverse = mesh.mTransform;
mInverse.Inverse();
aiVector3D* pvCurPtr = pcMesh->mVertices;
const aiVector3D* const pvEndPtr = pcMesh->mVertices + pcMesh->mNumVertices;
while (pvCurPtr != pvEndPtr)
{
*pvCurPtr = mInverse * (*pvCurPtr);
pvCurPtr++;
}
//pcMesh->mColors[2] = NULL;
// add sub nodes
this->AddNodes(pcScene,node,node->mName.data);
aiMatrix4x4 mNewAbs = decompTrafo.mMatrix * node->mTransformation;
ASE::DecompTransform dec( mNewAbs);
this->AddNodes(node,node->mName.data,dec);
}
// allocate enough space for the child nodes
@ -259,7 +372,7 @@ void ASEImporter::AddNodes(aiScene* pcScene,aiNode* pcParent,
return;
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::BuildNodes(aiScene* pcScene)
void ASEImporter::BuildNodes()
{
ai_assert(NULL != pcScene);
@ -270,15 +383,18 @@ void ASEImporter::BuildNodes(aiScene* pcScene)
pcScene->mRootNode->mName.Set("<root>");
// add all nodes
this->AddNodes(pcScene,pcScene->mRootNode,NULL);
this->AddNodes(pcScene->mRootNode,NULL);
// now iterate through al meshes and find those that have not yet
// been added to the nodegraph (= their parent could not be recognized)
std::vector<unsigned int> aiList;
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
{
// get the name of the mesh ([0] = name, [1] = parent)
std::string* szMyName = (std::string*)pcScene->mMeshes[i]->mColors[1];
// get the name of the mesh
const ASE::Mesh& mesh = *((const ASE::Mesh*)pcScene->mMeshes[i]->mColors[2]);
// TODO: experimental quick'n'dirty, clean this up ...
std::string szMyName[2] = {mesh.mName,mesh.mParent} ;
if (!szMyName)
{
continue;
@ -289,8 +405,9 @@ void ASEImporter::BuildNodes(aiScene* pcScene)
for (unsigned int i2 = 0; i2 < pcScene->mNumMeshes;++i2)
{
if (i2 == i)continue;
// get the name of the mesh ([0] = name, [1] = parent)
std::string* szMyName2 = (std::string*)pcScene->mMeshes[i2]->mColors[1];
const ASE::Mesh& mesh2 = *((const ASE::Mesh*)pcScene->mMeshes[i2]->mColors[2]);
// TODO: experimental quick'n'dirty, clean this up ...
std::string szMyName2[2] = {mesh2.mName,mesh2.mParent} ;
if (!szMyName2)
{
continue;
@ -328,7 +445,7 @@ void ASEImporter::BuildNodes(aiScene* pcScene)
aiNode* pcNode = new aiNode();
pcNode->mParent = pcScene->mRootNode;
pcNode->mName.Set(szMyName[1]);
this->AddNodes(pcScene,pcNode,szMyName[1].c_str());
this->AddNodes(pcNode,szMyName[1].c_str());
apcNodes.push_back(pcNode);
}
pcScene->mRootNode->mChildren = new aiNode*[apcNodes.size()];
@ -338,6 +455,9 @@ void ASEImporter::BuildNodes(aiScene* pcScene)
pcScene->mRootNode->mNumChildren = (unsigned int)apcNodes.size();
}
for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
pcScene->mMeshes[i]->mColors[2] = NULL;
// if there is only one subnode, set it as root node
if (1 == pcScene->mRootNode->mNumChildren)
{
@ -456,15 +576,15 @@ void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)
// now need to transform all vertices with the inverse of their
// transformation matrix ...
aiMatrix4x4 mInverse = mesh.mTransform;
mInverse.Inverse();
//aiMatrix4x4 mInverse = mesh.mTransform;
//mInverse.Inverse();
for (std::vector<aiVector3D>::iterator
i = mesh.mPositions.begin();
i != mesh.mPositions.end();++i)
{
(*i) = mInverse * (*i);
}
//for (std::vector<aiVector3D>::iterator
// i = mesh.mPositions.begin();
// i != mesh.mPositions.end();++i)
//{
// (*i) = mInverse * (*i);
//}
return;
}
@ -669,15 +789,8 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
// store the real index here ... color channel 3
p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
// store the real transformation matrix in color channel 2
p_pcOut->mColors[2] = (aiColor4D*) new aiMatrix4x4(mesh.mTransform);
// store the name of the mesh and the
// name of its parent in color channel 1
p_pcOut->mColors[1] = (aiColor4D*) new std::string[2];
((std::string*)p_pcOut->mColors[1])[0] = mesh.mName;
((std::string*)p_pcOut->mColors[1])[1] = mesh.mParent;
// store a pointer to the mesh in color channel 2
p_pcOut->mColors[2] = (aiColor4D*) &mesh;
avOutMeshes.push_back(p_pcOut);
// convert vertices
@ -821,15 +934,17 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
// store the real index here ... in color channel 3
p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
// store the transformation matrix in color channel 2
p_pcOut->mColors[2] = (aiColor4D*) new aiMatrix4x4(mesh.mTransform);
// store a pointer to the mesh in color channel 2
p_pcOut->mColors[2] = (aiColor4D*) &mesh;
avOutMeshes.push_back(p_pcOut);
// store the name of the mesh and the
// name of its parent in color channel 1
p_pcOut->mColors[1] = (aiColor4D*) new std::string[2];
((std::string*)p_pcOut->mColors[1])[0] = mesh.mName;
((std::string*)p_pcOut->mColors[1])[1] = mesh.mParent;
// if the mesh hasn't faces or vertices, there are two cases
// possible: 1. the model is invalid. 2. This is a dummy
// helper object which we are going to remove later ...
if (mesh.mFaces.empty() || mesh.mPositions.empty())
{
return;
}
// convert vertices
p_pcOut->mNumVertices = (unsigned int)mesh.mPositions.size();
@ -951,7 +1066,7 @@ void ComputeBounds(ASE::Mesh& mesh,aiVector3D& minVec, aiVector3D& maxVec,
return;
}
// ------------------------------------------------------------------------------------------------
void ASEImporter::BuildMaterialIndices(aiScene* pcScene)
void ASEImporter::BuildMaterialIndices()
{
ai_assert(NULL != pcScene);
@ -1033,7 +1148,7 @@ void ASEImporter::BuildMaterialIndices(aiScene* pcScene)
}
}
// prepare for the next step
for (unsigned int hans = 0; hans < pcScene->mNumMaterials;++hans)
for (unsigned int hans = 0; hans < this->mParser->m_vMaterials.size();++hans)
{
TextureTransform::ApplyScaleNOffset(this->mParser->m_vMaterials[hans]);
}

View File

@ -130,24 +130,28 @@ protected:
// -------------------------------------------------------------------
/** Setup the final material indices for each mesh
* \param pcScene Scene object to be filled
*/
void BuildMaterialIndices(aiScene* pcScene);
void BuildMaterialIndices();
// -------------------------------------------------------------------
/** Build the node graph
* \param pcScene Scene object to be filled
*/
void BuildNodes(aiScene* pcScene);
void BuildNodes();
// -------------------------------------------------------------------
/** Build output animations
*/
void BuildAnimations();
// -------------------------------------------------------------------
/** Add sub nodes to a node
* \param pcScene Scene object to be filled
* \param pcParent parent node to be filled
* \param szName Name of the parent node
* \param decompTrafo Decomposed absolute parent transformation mat
*/
void AddNodes(aiScene* pcScene,aiNode* pcParent,
const char* szName);
void AddNodes(aiNode* pcParent,const char* szName);
void AddNodes(aiNode* pcParent,const char* szName,
const ASE::DecompTransform& decompTrafo);
// -------------------------------------------------------------------
/** Generate a default material and add it to the parser's list
@ -166,6 +170,9 @@ protected:
/** true if this is an .ask file */
bool mIsAsk;
/** Scene to be filled */
aiScene* pcScene;
};
} // end of namespace Assimp

View File

@ -67,6 +67,44 @@ using namespace Assimp::ASE;
#define BLUBB(_message_) \
{this->LogError(_message_);return;}
#define AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth) \
else if ('{' == *this->m_szFile)iDepth++; \
else if ('}' == *this->m_szFile) \
{ \
if (0 == --iDepth) \
{ \
++this->m_szFile; \
this->SkipToNextToken(); \
return; \
} \
} \
else if ('\0' == *this->m_szFile) \
{ \
return; \
} \
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; \
++this->m_szFile;
#define AI_ASE_HANDLE_SECTION(iDepth, level, msg) \
else if ('{' == *this->m_szFile)iDepth++; \
else if ('}' == *this->m_szFile) \
{ \
if (0 == --iDepth) \
{ \
++this->m_szFile; \
this->SkipToNextToken(); \
return; \
} \
} \
else if ('\0' == *this->m_szFile) \
{ \
this->LogError("Encountered unexpected EOL while parsing a " msg \
" chunk (Level " level ")"); \
} \
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber; \
++this->m_szFile;
// ------------------------------------------------------------------------------------------------
Parser::Parser (const char* szFile)
{
@ -78,6 +116,10 @@ Parser::Parser (const char* szFile)
this->m_clrAmbient.r = std::numeric_limits<float>::quiet_NaN();
this->iLineNumber = 0;
this->iFirstFrame = 0;
this->iLastFrame = 0;
this->iFrameSpeed = 30; // use 30 as default value for this property
this->iTicksPerFrame = 1; // use 1 as default value for this property
}
// ------------------------------------------------------------------------------------------------
void Parser::LogWarning(const char* szWarn)
@ -234,6 +276,15 @@ void Parser::Parse()
this->ParseLV1GeometryObjectBlock(this->m_vMeshes.back());
continue;
}
// helper object = dummy in the hierarchy
if (0 == strncmp(this->m_szFile,"*HELPEROBJECT",13) &&
IsSpaceOrNewLine(*(this->m_szFile+13)))
{
this->m_szFile+=14;
this->m_vMeshes.push_back(Mesh());
this->ParseLV1GeometryObjectBlock(this->m_vMeshes.back());
continue;
}
// ignore comments, lights and cameras
// (display comments on the console)
if (0 == strncmp(this->m_szFile,"*LIGHTOBJECT",12) &&
@ -260,18 +311,7 @@ void Parser::Parse()
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... why not?
return;
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth);
}
return;
}
@ -301,19 +341,36 @@ void Parser::ParseLV1SceneBlock()
this->ParseLV4MeshFloatTriple( &this->m_clrAmbient.r );
continue;
}
if (0 == strncmp(this->m_szFile,"*SCENE_FIRSTFRAME",17) &&
IsSpaceOrNewLine(*(this->m_szFile+17)))
{
this->m_szFile+=18;
this->ParseLV4MeshLong(this->iFirstFrame);
continue;
}
if (0 == strncmp(this->m_szFile,"*SCENE_LASTFRAME",16) &&
IsSpaceOrNewLine(*(this->m_szFile+16)))
{
this->m_szFile+=17;
this->ParseLV4MeshLong(this->iLastFrame);
continue;
}
if (0 == strncmp(this->m_szFile,"*SCENE_FRAMESPEED",17) &&
IsSpaceOrNewLine(*(this->m_szFile+17)))
{
this->m_szFile+=18;
this->ParseLV4MeshLong(this->iFrameSpeed);
continue;
}
if (0 == strncmp(this->m_szFile,"*SCENE_TICKSPERFRAME",20) &&
IsSpaceOrNewLine(*(this->m_szFile+20)))
{
this->m_szFile+=21;
this->ParseLV4MeshLong(this->iTicksPerFrame);
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... why not?
return;
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth);
}
return;
}
@ -361,18 +418,7 @@ void Parser::ParseLV1MaterialListBlock()
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... why not?
return;
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth);
}
return;
}
@ -594,18 +640,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level2 block, this can't be
BLUBB("Unable to finish parsing a lv2 material block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"2","*MATERIAL");
}
return;
}
@ -669,18 +704,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
this->ParseLV4MeshFloat(map.mTextureBlend);continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level3 block, this can't be
BLUBB("Unable to finish parsing a lv3 map block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MAP_XXXXXX");
}
return;
}
@ -788,23 +812,99 @@ void Parser::ParseLV1GeometryObjectBlock(ASE::Mesh& mesh)
this->m_szFile+=14;
this->ParseLV4MeshLong(mesh.iMaterialIndex);continue;
}
// animation data of the node
if (0 == strncmp(this->m_szFile,"*TM_ANIMATION" ,13) &&
IsSpaceOrNewLine(*(this->m_szFile+13)))
{
this->m_szFile+=14;
this->ParseLV2AnimationBlock(mesh);continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level1 block, this can be
return;
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_TOP_LEVEL_SECTION(iDepth);
}
return;
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2AnimationBlock(ASE::Mesh& mesh)
{
int iDepth = 0;
while (true)
{
if ('*' == *this->m_szFile)
{
// position keyframes
if (0 == strncmp(this->m_szFile,"*CONTROL_POS_TRACK" ,18) &&
IsSpaceOrNewLine(*(this->m_szFile+18)))
{
this->m_szFile+=19;
this->ParseLV3PosAnimationBlock(mesh);continue;
}
// rotation keyframes
if (0 == strncmp(this->m_szFile,"*CONTROL_ROT_TRACK" ,18) &&
IsSpaceOrNewLine(*(this->m_szFile+18)))
{
this->m_szFile+=19;
this->ParseLV3RotAnimationBlock(mesh);continue;
}
}
AI_ASE_HANDLE_SECTION(iDepth,"2","TM_ANIMATION");
}
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3PosAnimationBlock(ASE::Mesh& mesh)
{
int iDepth = 0;
while (true)
{
if ('*' == *this->m_szFile)
{
// position keyframe
if (0 == strncmp(this->m_szFile,"*CONTROL_POS_SAMPLE" ,19) &&
IsSpaceOrNewLine(*(this->m_szFile+19)))
{
this->m_szFile+=20;
unsigned int iIndex;
mesh.mAnim.akeyPositions.push_back(aiVectorKey());
aiVectorKey& key = mesh.mAnim.akeyPositions.back();
this->ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
key.mTime = (double)iIndex;
}
}
AI_ASE_HANDLE_SECTION(iDepth,"3","*CONTROL_POS_TRACK");
}
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV3RotAnimationBlock(ASE::Mesh& mesh)
{
int iDepth = 0;
while (true)
{
if ('*' == *this->m_szFile)
{
// rotation keyframe
if (0 == strncmp(this->m_szFile,"*CONTROL_ROT_SAMPLE" ,19) &&
IsSpaceOrNewLine(*(this->m_szFile+19)))
{
this->m_szFile+=20;
unsigned int iIndex;
mesh.mAnim.akeyRotations.push_back(aiQuatKey());
aiQuatKey& key = mesh.mAnim.akeyRotations.back();
// first read the axis, then the angle in radians
aiVector3D v;float f;
this->ParseLV4MeshFloatTriple(&v.x,iIndex);
this->ParseLV4MeshFloat(f);
key.mTime = (double)iIndex;
key.mValue = aiQuaternion(v,f);
}
}
AI_ASE_HANDLE_SECTION(iDepth,"3","*CONTROL_ROT_TRACK");
}
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV2NodeTransformBlock(ASE::Mesh& mesh)
{
int iDepth = 0;
@ -840,19 +940,44 @@ void Parser::ParseLV2NodeTransformBlock(ASE::Mesh& mesh)
this->m_szFile+=9;
this->ParseLV4MeshFloatTriple(mesh.mTransform[3]);continue;
}
// inherited position axes
if (0 == strncmp(this->m_szFile,"*INHERIT_POS" ,12) &&
IsSpaceOrNewLine(*(this->m_szFile+12)))
{
this->m_szFile+=13;
unsigned int aiVal[3];
this->ParseLV4MeshLongTriple(aiVal);
for (unsigned int i = 0; i < 3;++i)
mesh.inherit.abInheritPosition[i] = aiVal[i] != 0;
continue;
}
// inherited rotation axes
if (0 == strncmp(this->m_szFile,"*INHERIT_ROT" ,12) &&
IsSpaceOrNewLine(*(this->m_szFile+12)))
{
this->m_szFile+=13;
unsigned int aiVal[3];
this->ParseLV4MeshLongTriple(aiVal);
for (unsigned int i = 0; i < 3;++i)
mesh.inherit.abInheritRotation[i] = aiVal[i] != 0;
continue;
}
// inherited scaling axes
if (0 == strncmp(this->m_szFile,"*INHERIT_SCL" ,12) &&
IsSpaceOrNewLine(*(this->m_szFile+12)))
{
this->m_szFile+=13;
unsigned int aiVal[3];
this->ParseLV4MeshLongTriple(aiVal);
for (unsigned int i = 0; i < 3;++i)
mesh.inherit.abInheritScaling[i] = aiVal[i] != 0;
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level2 block, this can't be
BLUBB("Unable to finish parsing a lv2 node transform block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"2","*NODE_TM");
}
return;
}
@ -1015,18 +1140,7 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
this->ParseLV3MeshWeightsBlock(mesh);continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level2 block, this can't be
BLUBB("Unable to finish parsing a lv2 mesh block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"2","*MESH");
}
return;
}
@ -1072,18 +1186,7 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level2 block, this can't be
BLUBB("Unable to finish parsing a lv2 *MESH_WEIGHTS block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_WEIGHTS");
}
return;
}
@ -1118,18 +1221,7 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
}
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level4 block, this can't be
BLUBB("Unable to finish parsing a lv4 *MESH_BONE_LIST block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_BONE_LIST");
}
}
// ------------------------------------------------------------------------------------------------
@ -1183,18 +1275,7 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level4 block, this can't be
BLUBB("Unable to finish parsing a lv4 *MESH_BONE_VERTEX_LIST block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"4","*MESH_BONE_VERTEX");
}
return;
}
@ -1227,18 +1308,7 @@ void Parser::ParseLV3MeshVertexListBlock(
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level3 block, this can't be
BLUBB("Unable to finish parsing a lv3 vertex list block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_VERTEX_LIST");
}
return;
}
@ -1269,18 +1339,7 @@ void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level3 block, this can't be
BLUBB("Unable to finish parsing LV3 *MESH_FACE_LIST block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_FACE_LIST");
}
return;
}
@ -1319,18 +1378,7 @@ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level3 block, this can't be
BLUBB("Unable to finish parsing LV3 *MESH_VERTEX_LIST block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_TVERT_LIST");
}
return;
}
@ -1367,18 +1415,7 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level3 block, this can't be
BLUBB("Unable to finish parsing LV3 *MESH_TFACELIST block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_TFACE_LIST");
}
return;
}
@ -1426,18 +1463,7 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level2 block, this can't be
BLUBB("Unable to finish parsing a LV3 *MESH_MAPPINGCHANNEL block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_MAPPING_CHANNEL");
}
return;
}
@ -1470,18 +1496,7 @@ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
continue;
}
}
if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level3 block, this can't be
BLUBB("Unable to finish parsing LV3 *MESH_CVERTLIST block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_CVERTEX_LIST");
}
return;
}
@ -1517,18 +1532,7 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
else if ('\0' == *this->m_szFile)
{
// END OF FILE ... this is a level3 block, this can't be
BLUBB("Unable to finish parsing LV3 *MESH_CFACELIST block. Unexpected EOF")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
++this->m_szFile;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_CFACE_LIST");
}
return;
}
@ -1545,7 +1549,8 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
{
if ('*' == *this->m_szFile)
{
if (0 == strncmp(this->m_szFile,"*MESH_VERTEXNORMAL",18) && IsSpaceOrNewLine(*(this->m_szFile+18)))
if (0 == strncmp(this->m_szFile,"*MESH_VERTEXNORMAL",18) &&
IsSpaceOrNewLine(*(this->m_szFile+18)))
{
this->m_szFile += 19;
@ -1565,18 +1570,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
continue;
}
}
else if ('{' == *this->m_szFile)iDepth++;
else if ('}' == *this->m_szFile)
{
if (0 == --iDepth){++this->m_szFile;this->SkipToNextToken();return;}
}
// seems we have reached the end of the file ...
else if ('\0' == *this->m_szFile)
{
BLUBB("Unable to parse *MESH_NORMALS Element: Unexpected EOL [#1]")
}
else if(IsLineEnd(*this->m_szFile))++this->iLineNumber;
this->m_szFile++;
AI_ASE_HANDLE_SECTION(iDepth,"3","*MESH_NORMALS");
}
return;
}
@ -1729,40 +1723,19 @@ void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
{
ai_assert(NULL != apOut);
// skip spaces and tabs
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
for (unsigned int i = 0; i < 3;++i)
{
// LOG
this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#1]");
++this->iLineNumber;
apOut[0] = apOut[1] = apOut[2] = 0;
return;
// skip spaces and tabs
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
{
// LOG
this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#1]");
++this->iLineNumber;
apOut[0] = apOut[1] = apOut[2] = 0;
return;
}
apOut[i] = strtol10(this->m_szFile,&this->m_szFile);
}
apOut[0] = strtol10(this->m_szFile,&this->m_szFile);
// skip spaces and tabs
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
{
// LOG
this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#2]");
++this->iLineNumber;
apOut[1] = apOut[2] = 0;
return;
}
apOut[1] = strtol10(this->m_szFile,&this->m_szFile);
// skip spaces and tabs
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
{
// LOG
this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#3]");
apOut[2] = 0;
++this->iLineNumber;
return;
}
apOut[2] = strtol10(this->m_szFile,&this->m_szFile);
// go to the next valid sequence
//SkipSpacesAndLineEnd(this->m_szFile,&this->m_szFile);
}
// ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
@ -1773,7 +1746,7 @@ void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
{
// LOG
this->LogWarning("Unable to parse indexable long triple: unexpected EOL [#4]");
this->LogWarning("Unable to parse indexed long triple: unexpected EOL [#4]");
rIndexOut = 0;
apOut[0] = apOut[1] = apOut[2] = 0;
++this->iLineNumber;
@ -1795,7 +1768,7 @@ void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
{
// LOG
this->LogWarning("Unable to parse indexable float triple: unexpected EOL [#1]");
this->LogWarning("Unable to parse indexed float triple: unexpected EOL [#1]");
rIndexOut = 0;
apOut[0] = apOut[1] = apOut[2] = 0.0f;
++this->iLineNumber;
@ -1812,41 +1785,21 @@ void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
void Parser::ParseLV4MeshFloatTriple(float* apOut)
{
ai_assert(NULL != apOut);
// skip spaces and tabs
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
for (unsigned int i = 0; i < 3;++i)
{
// LOG
this->LogWarning("Unable to parse float triple: unexpected EOL [#5]");
apOut[0] = apOut[1] = apOut[2] = 0.0f;
++this->iLineNumber;
return;
// skip spaces and tabs
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
{
// LOG
this->LogWarning("Unable to parse float triple: unexpected EOL [#5]");
apOut[0] = apOut[1] = apOut[2] = 0.0f;
++this->iLineNumber;
return;
}
// parse the float
this->m_szFile = fast_atof_move(this->m_szFile,apOut[i]);
}
// parse the first float
this->m_szFile = fast_atof_move(this->m_szFile,apOut[0]);
// skip spaces and tabs
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
{
// LOG
this->LogWarning("Unable to parse float triple: unexpected EOL [#6]");
apOut[1] = apOut[2] = 0.0f;
++this->iLineNumber;
return;
}
// parse the second float
this->m_szFile = fast_atof_move(this->m_szFile,apOut[1]);
// skip spaces and tabs
if(!SkipSpaces(this->m_szFile,&this->m_szFile))
{
// LOG
this->LogWarning("Unable to parse float triple: unexpected EOL [#7]");
apOut[2] = 0.0f;
++this->iLineNumber;
return;
}
// parse the third float
this->m_szFile = fast_atof_move(this->m_szFile,apOut[2]);
// go to the next valid sequence
//this->SkipToNextToken();
return;
}
// ------------------------------------------------------------------------------------------------

View File

@ -43,17 +43,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_ASEFILEHELPER_H_INC
#define AI_ASEFILEHELPER_H_INC
// STL/CRT headers
#include <string>
#include <vector>
#include <list>
#include <sstream>
// public ASSIMP headers
#include "../include/aiTypes.h"
#include "../include/aiMesh.h"
#include "../include/aiAnim.h"
// for some helper routines like IsSpace()
#include "PlyParser.h"
#include "qnan.h"
// ASE is quite similar to 3ds. We can reuse some structures
#include "3DSLoader.h"
@ -130,9 +132,10 @@ struct Bone
Bone()
{
static int iCnt = 0;
std::stringstream ss(mName);
ss << "%%_UNNAMED_" << iCnt++ << "_%%";
ss.flush();
char szTemp[128];
::sprintf(szTemp,"UNNAMED_%i",iCnt++);
mName = szTemp;
}
//! Name of the bone
@ -152,6 +155,73 @@ struct BoneVertex
//aiVector3D mPosition;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file animation */
struct Animation
{
//! List of rotation keyframes
std::vector< aiQuatKey > akeyRotations;
//! List of position keyframes
std::vector< aiVectorKey > akeyPositions;
};
// ---------------------------------------------------------------------------
/** Helper structure to represent the inheritance information of an ASE node */
struct InheritanceInfo
{
//! Default constructor
InheritanceInfo()
{
// set the inheritance flag for all axes by default to true
for (unsigned int i = 0; i < 3;++i)
abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
}
//! Inherit the parent's position?, axis order is x,y,z
bool abInheritPosition[3];
//! Inherit the parent's rotation?, axis order is x,y,z
bool abInheritRotation[3];
//! Inherit the parent's scaling?, axis order is x,y,z
bool abInheritScaling[3];
};
// ---------------------------------------------------------------------------
/** Stores a decomposed transformation matrix */
struct DecompTransform
{
//! Construction from a reference to an existing matrix
DecompTransform(aiMatrix4x4& ref)
: vScaling(1.0f,1.0f,1.0f)
, vPosition(std::numeric_limits<float>::quiet_NaN(),0.0f,0.0f)
, mMatrix(ref)
{}
//! Translational component
mutable aiVector3D vPosition;
//! Rotational component
mutable aiQuaternion qRotation;
//! Scaling component
mutable aiVector3D vScaling;
//! Reference to the matrix being decomposed
const aiMatrix4x4& mMatrix;
//! Decomposes the matrix if this has not yet been done
inline void NeedDecomposedMatrixNOW() const
{
if (is_qnan(vPosition.x))
{
mMatrix.Decompose(vScaling,qRotation,vPosition);
}
}
};
// ---------------------------------------------------------------------------
/** Helper structure to represent an ASE file mesh */
struct Mesh
@ -160,9 +230,9 @@ struct Mesh
Mesh() : bSkip(false)
{
static int iCnt = 0;
std::stringstream ss(mName);
ss << "%%_UNNAMED_" << iCnt++ << "_%%";
ss.flush();
char szTemp[128];
::sprintf(szTemp,"UNNAMED_%i",iCnt++);
mName = szTemp;
// use 2 texture vertex components by default
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
@ -203,6 +273,9 @@ struct Mesh
//! Transformation matrix of the mesh
aiMatrix4x4 mTransform;
//! Animation channels for the node
Animation mAnim;
//! Material index of the mesh
unsigned int iMaterialIndex;
@ -211,6 +284,10 @@ struct Mesh
//! used internally
bool bSkip;
//! Specifies which axes transformations a node inherits
//! from its parent ...
InheritanceInfo inherit;
};
// ---------------------------------------------------------------------------------
@ -259,6 +336,13 @@ private:
//! \param mesh Mesh object to be filled
void ParseLV2NodeTransformBlock(Mesh& mesh);
// -------------------------------------------------------------------
//! Parse a *TM_ANIMATION block in a file
//! \param mesh Mesh object to be filled
void ParseLV2AnimationBlock(Mesh& mesh);
void ParseLV3PosAnimationBlock(Mesh& mesh);
void ParseLV3RotAnimationBlock(Mesh& mesh);
// -------------------------------------------------------------------
//! Parse a *MESH block in a file
//! \param mesh Mesh object to be filled
@ -453,6 +537,19 @@ public:
//! Current line in the file
unsigned int iLineNumber;
//! First frame
unsigned int iFirstFrame;
//! Last frame
unsigned int iLastFrame;
//! Frame speed - frames per second
unsigned int iFrameSpeed;
//! Ticks per frame
unsigned int iTicksPerFrame;
};

View File

@ -110,8 +110,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh)
// what we can check, though, is if the mesh has normals and texture coord. That's a requirement
if( pMesh->mNormals == NULL || pMesh->mTextureCoords[0] == NULL)
{
DefaultLogger::get()->error("Normal vectors and at least one "
"texture coordinate set are required to calculate tangents. ");
DefaultLogger::get()->error("Unable to compute tangents: UV0 and normals must be there ");
return false;
}

View File

@ -42,20 +42,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the post processing step to validate
* the data structure returned by Assimp
*/
// STL headers
#include <vector>
#include <assert.h>
// internal headers
#include "ValidateDataStructure.h"
#include "BaseImporter.h"
#include "StringComparison.h"
#include "fast_atof.h"
// public ASSIMP headers
#include "../include/DefaultLogger.h"
#include "../include/aiPostProcess.h"
#include "../include/aiMesh.h"
#include "../include/aiScene.h"
#include "../include/aiAssert.h"
// CRT headers
#include <stdarg.h>
using namespace Assimp;
@ -128,7 +133,7 @@ void ValidateDSProcess::ReportWarning(const char* msg,...)
throw new ImportErrorException("Idiot ... learn coding!");
}
va_end(args);
DefaultLogger::get()->warn("Validation failed: " + std::string(szBuffer,iLen));
DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
}
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
@ -286,7 +291,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
{
if (face.mIndices[a] >= pMesh->mNumVertices)
{
this->ReportError("aiMesh::mFaces[%i]::mIndices[%a] is out of range",i,a);
this->ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a);
}
if (abRefList[face.mIndices[a]])
{
@ -636,6 +641,7 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
{
this->Validate(&pBoneAnim->mBoneName);
#if 0
// check whether there is a bone with this name ...
unsigned int i = 0;
for (; i < this->mScene->mNumMeshes;++i)
@ -650,14 +656,14 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
__break_out:
if (i == this->mScene->mNumMeshes)
{
this->ReportWarning("aiBoneAnim::mBoneName is %s. However, no bone with this name was found",
this->ReportWarning("aiBoneAnim::mBoneName is \"%s\". However, no bone with this name was found",
pBoneAnim->mBoneName.data);
}
if (!pBoneAnim->mNumPositionKeys && !pBoneAnim->mNumRotationKeys && !pBoneAnim->mNumScalingKeys)
{
this->ReportWarning("A bone animation channel has no keys");
}
#endif
// otherwise check whether one of the keys exceeds the total duration of the animation
if (pBoneAnim->mNumPositionKeys)
{

View File

@ -66,9 +66,12 @@ struct aiQuatKey
C_STRUCT aiQuaternion mValue; ///< The value of this key
};
/** Describes the animation of a single bone. The name specifies the bone which is affected by this
/** Describes the animation of a single node. The name specifies the bone/node which is affected by this
* animation channel. The keyframes are given in three separate series of values, one each for
* position, rotation and scaling.
* <br>
* NOTE: The name "BoneAnim" is misleading. This structure is also used to describe
* the animation of regular nodes on the node graph. They needn't be nodes.
*/
struct aiBoneAnim
{

View File

@ -52,6 +52,8 @@ struct aiMatrix4x4
aiMatrix4x4& Inverse();
float Determinant() const;
inline bool IsIdentity() const;
float* operator[](unsigned int p_iIndex);
const float* operator[](unsigned int p_iIndex) const;
@ -87,6 +89,37 @@ struct aiMatrix4x4
inline void FromEulerAngles(float x, float y, float z);
/** \brief Returns a rotation matrix for a rotation around the x axis
* \param a Rotation angle, in radians
* \param out Receives the output matrix
* \return Reference to the output matrix
*/
static aiMatrix4x4& RotationX(float a, aiMatrix4x4& out);
/** \brief Returns a rotation matrix for a rotation around the y axis
* \param a Rotation angle, in radians
* \param out Receives the output matrix
* \return Reference to the output matrix
*/
static aiMatrix4x4& RotationY(float a, aiMatrix4x4& out);
/** \brief Returns a rotation matrix for a rotation around the z axis
* \param a Rotation angle, in radians
* \param out Receives the output matrix
* \return Reference to the output matrix
*/
static aiMatrix4x4& RotationZ(float a, aiMatrix4x4& out);
/** \brief Returns a translation matrix
* \param v Translation vector
* \param out Receives the output matrix
* \return Reference to the output matrix
*/
static aiMatrix4x4& Translation(aiVector3D v, aiMatrix4x4& out);
#endif // __cplusplus
float a1, a2, a3, a4;

View File

@ -237,6 +237,65 @@ inline void aiMatrix4x4::FromEulerAngles(float x, float y, float z)
_this.a4 = _this.b4 = _this.c4 = _this.d1 = _this.d2 = _this.d3 = 0.0f;
_this.d4 = 1.0f;
}
// ---------------------------------------------------------------------------
inline bool aiMatrix4x4::IsIdentity() const
{
return !(a1 != 1.0f || a2 || a3 || a4 ||
b1 || b2 != 1.0f || b3 || b4 ||
c1 || c2 || c3 != 1.0f || a4 ||
d1 || d2 || d3 || d4 != 1.0f);
}
// ---------------------------------------------------------------------------
inline aiMatrix4x4& aiMatrix4x4::RotationX(float a, aiMatrix4x4& out)
{
/*
| 1 0 0 0 |
M = | 0 cos(A) -sin(A) 0 |
| 0 sin(A) cos(A) 0 |
| 0 0 0 1 | */
out.aiMatrix4x4::aiMatrix4x4();
out.b2 = out.c3 = cos(a);
out.b3 = -(out.c2 = sin(a));
return out;
}
// ---------------------------------------------------------------------------
inline aiMatrix4x4& aiMatrix4x4::RotationY(float a, aiMatrix4x4& out)
{
/*
| cos(A) 0 sin(A) 0 |
M = | 0 1 0 0 |
| -sin(A) 0 cos(A) 0 |
| 0 0 0 1 |
*/
out.aiMatrix4x4::aiMatrix4x4();
out.a1 = out.c3 = cos(a);
out.c1 = -(out.a3 = sin(a));
return out;
}
// ---------------------------------------------------------------------------
inline aiMatrix4x4& aiMatrix4x4::RotationZ(float a, aiMatrix4x4& out)
{
/*
| cos(A) -sin(A) 0 0 |
M = | sin(A) cos(A) 0 0 |
| 0 0 1 0 |
| 0 0 0 1 | */
out.aiMatrix4x4::aiMatrix4x4();
out.a1 = out.b2 = cos(a);
out.a2 = -(out.b1 = sin(a));
return out;
}
// ---------------------------------------------------------------------------
inline aiMatrix4x4& aiMatrix4x4::Translation(aiVector3D v, aiMatrix4x4& out)
{
out.aiMatrix4x4::aiMatrix4x4();
out.d1 = v.x;
out.d2 = v.y;
out.d3 = v.z;
return out;
}
#endif // __cplusplus
#endif // AI_MATRIX4x4_INL_INC

View File

@ -1,3 +1,43 @@
/*
Open Asset Import Library (ASSIMP)
----------------------------------------------------------------------
Copyright (c) 2006-2008, ASSIMP Development Team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the ASSIMP Development Team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file Quaternion structure, including operators when compiling in C++ */
#ifndef AI_QUATERNION_H_INC
#define AI_QUATERNION_H_INC
@ -23,8 +63,12 @@ struct aiQuaternion
/** Construct from euler angles */
aiQuaternion( float rotx, float roty, float rotz);
/** Construct from an axis angle pair */
aiQuaternion( aiVector3D axis, float angle);
/** Returns a matrix representation of the quaternion */
aiMatrix3x3 GetMatrix() const;
#endif // __cplusplus
//! w,x,y,z components of the quaternion
@ -113,6 +157,21 @@ inline aiMatrix3x3 aiQuaternion::GetMatrix() const
return resMatrix;
}
// ---------------------------------------------------------------------------
// Construction from an axis-angle pair
inline aiQuaternion::aiQuaternion( aiVector3D axis, float angle)
{
axis.Normalize();
const float sin_a = sin( angle / 2 );
const float cos_a = cos( angle / 2 );
x = axis.x * sin_a;
y = axis.y * sin_a;
z = axis.z * sin_a;
w = cos_a;
}
} // end extern "C"

View File

@ -119,6 +119,7 @@ struct aiNode
//! and propably meshes with bones.
#define AI_SCENE_FLAGS_ANIM_SKELETON_ONLY 0x1
// ---------------------------------------------------------------------------
/** The root structure of the imported data.
*