Small update to the ASE loader.
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@64 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
fc8a8b54f9
commit
6ad0892396
|
@ -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;
|
||||
aiMatrix4x4 mParentAdjust = decompTrafo.mMatrix;
|
||||
mParentAdjust.Inverse();
|
||||
//if(ComputeLocalToWorldShift(mParentAdjust, decompTrafo, mesh.inherit))
|
||||
{
|
||||
node->mTransformation = mParentAdjust*mesh.mTransform;
|
||||
}
|
||||
//else node->mTransformation = mesh.mTransform;
|
||||
|
||||
delete[] szMyName;
|
||||
pcScene->mMeshes[i]->mColors[1] = NULL;
|
||||
// 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]);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
111
code/ASEParser.h
111
code/ASEParser.h
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue