3DS bugfixes; ASE bugfix (newline), PLY revert to older version, SMD is working now (partially); homepage added to SVN
git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@63 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
This commit is contained in:
@@ -429,10 +429,10 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
|
||||
a = (*i).mFaceMaterials.begin();
|
||||
a != (*i).mFaceMaterials.end();++a,++iNum)
|
||||
{
|
||||
// check range
|
||||
// check range
|
||||
if ((*a) >= this->mScene->mMaterials.size())
|
||||
{
|
||||
DefaultLogger::get()->error("Face material index is out of range");
|
||||
DefaultLogger::get()->error("3DS face material index is out of range");
|
||||
|
||||
// use the last material instead
|
||||
aiSplit[this->mScene->mMaterials.size()-1].push_back(iNum);
|
||||
@@ -440,7 +440,6 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
|
||||
else aiSplit[*a].push_back(iNum);
|
||||
}
|
||||
// now generate submeshes
|
||||
|
||||
bool bFirst = true;
|
||||
for (unsigned int p = 0; p < this->mScene->mMaterials.size();++p)
|
||||
{
|
||||
@@ -452,19 +451,9 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
|
||||
p_pcOut->mMaterialIndex = p;
|
||||
|
||||
// use the color data as temporary storage
|
||||
p_pcOut->mColors[0] = (aiColor4D*)new std::string((*i).mName);
|
||||
p_pcOut->mColors[0] = (aiColor4D*)(&*i);
|
||||
avOutMeshes.push_back(p_pcOut);
|
||||
|
||||
// (code for keyframe animation. however, this is currently not supported by Assimp)
|
||||
#if 0
|
||||
if (bFirst)
|
||||
{
|
||||
p_pcOut->mColors[1] = (aiColor4D*)new aiMatrix4x4();
|
||||
*((aiMatrix4x4*)p_pcOut->mColors[1]) = (*i).mMat;
|
||||
bFirst = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// convert vertices
|
||||
p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
|
||||
p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
|
||||
@@ -552,87 +541,72 @@ void Dot3DSImporter::ConvertMeshes(aiScene* pcOut)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,Dot3DS::Node* pcIn)
|
||||
{
|
||||
// find the corresponding mesh indices
|
||||
std::vector<unsigned int> iArray;
|
||||
iArray.reserve(3);
|
||||
|
||||
if (pcIn->mName != "$$$DUMMY")
|
||||
{
|
||||
for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a)
|
||||
{
|
||||
if (0 == ASSIMP_stricmp(pcIn->mName.c_str(),
|
||||
((std::string*)pcSOut->mMeshes[a]->mColors[0])->c_str()))
|
||||
const Dot3DS::Mesh* pcMesh = (const Dot3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
|
||||
ai_assert(NULL != pcMesh);
|
||||
|
||||
if (0 == ASSIMP_stricmp(pcIn->mName.c_str(),pcMesh->mName.c_str()))
|
||||
{
|
||||
iArray.push_back(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
pcOut->mName.Set(pcIn->mName);
|
||||
pcOut->mNumMeshes = (unsigned int)iArray.size();
|
||||
pcOut->mMeshes = new unsigned int[iArray.size()];
|
||||
|
||||
for (unsigned int i = 0;i < iArray.size();++i)
|
||||
{
|
||||
const unsigned int iIndex = iArray[i];
|
||||
|
||||
// (code for keyframe animation. however, this is currently not supported by Assimp)
|
||||
#if 0
|
||||
if (NULL != pcSOut->mMeshes[iIndex]->mColors[1])
|
||||
if (!iArray.empty())
|
||||
{
|
||||
pcOut->mTransformation = *((aiMatrix4x4*)
|
||||
(pcSOut->mMeshes[iIndex]->mColors[1]));
|
||||
aiMatrix4x4& mTrafo = ((Dot3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0])->mMat;
|
||||
aiMatrix4x4 mInv = mTrafo;
|
||||
mInv.Inverse();
|
||||
|
||||
delete (aiMatrix4x4*)pcSOut->mMeshes[iIndex]->mColors[1];
|
||||
pcSOut->mMeshes[iIndex]->mColors[1] = NULL;
|
||||
pcOut->mName.Set(pcIn->mName);
|
||||
pcOut->mNumMeshes = (unsigned int)iArray.size();
|
||||
pcOut->mMeshes = new unsigned int[iArray.size()];
|
||||
for (unsigned int i = 0;i < iArray.size();++i)
|
||||
{
|
||||
const unsigned int iIndex = iArray[i];
|
||||
aiMesh* const mesh = pcSOut->mMeshes[iIndex];
|
||||
|
||||
// http://www.zfx.info/DisplayThread.php?MID=235690#235690
|
||||
const aiVector3D& pivot = pcIn->vPivot;
|
||||
const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices;
|
||||
aiVector3D* pvCurrent = mesh->mVertices;
|
||||
|
||||
if(pivot.x || pivot.y || pivot.z)
|
||||
{
|
||||
while (pvCurrent != pvEnd)
|
||||
{
|
||||
*pvCurrent = mInv * (*pvCurrent);
|
||||
pvCurrent->x -= pivot.x;
|
||||
pvCurrent->y -= pivot.y;
|
||||
pvCurrent->z -= pivot.z;
|
||||
*pvCurrent = mTrafo * (*pvCurrent);
|
||||
std::swap( pvCurrent->y, pvCurrent->z );
|
||||
++pvCurrent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (pvCurrent != pvEnd)
|
||||
{
|
||||
std::swap( pvCurrent->y, pvCurrent->z );
|
||||
pvCurrent->y *= -1.0f;
|
||||
++pvCurrent;
|
||||
}
|
||||
}
|
||||
pcOut->mMeshes[i] = iIndex;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pcOut->mMeshes[i] = iIndex;
|
||||
/*else
|
||||
{
|
||||
DefaultLogger::get()->warn("A node that is not a dummy does not "
|
||||
"reference a valid mesh.");
|
||||
}*/
|
||||
}
|
||||
|
||||
// (code for keyframe animation. however, this is currently not supported by Assimp)
|
||||
#if 0
|
||||
// build the scaling matrix. Toggle y and z axis
|
||||
aiMatrix4x4 mS;
|
||||
mS.a1 = pcIn->vScaling.x;
|
||||
mS.b2 = pcIn->vScaling.z;
|
||||
mS.c3 = pcIn->vScaling.y;
|
||||
|
||||
// build the translation matrix. Toggle y and z axis
|
||||
aiMatrix4x4 mT;
|
||||
mT.a4 = pcIn->vPosition.x;
|
||||
mT.b4 = pcIn->vPosition.z;
|
||||
mT.c4 = pcIn->vPosition.y;
|
||||
|
||||
// build the pivot matrix. Toggle y and z axis
|
||||
aiMatrix4x4 mP;
|
||||
mP.a4 = -pcIn->vPivot.x;
|
||||
mP.b4 = -pcIn->vPivot.z;
|
||||
mP.c4 = -pcIn->vPivot.y;
|
||||
|
||||
|
||||
#endif
|
||||
// build a matrix to flip the z coordinate of the vertices
|
||||
aiMatrix4x4 mF;
|
||||
mF.c3 = -1.0f;
|
||||
|
||||
|
||||
// build the final matrix
|
||||
// NOTE: This should be the identity. Theoretically. In reality
|
||||
// there are many models with very funny local matrices and
|
||||
// very different keyframe values ... this is the only reason
|
||||
// why we extract the data from the first keyframe.
|
||||
pcOut->mTransformation = mF; /* mF * mT * pcIn->mRotation * mS * mP *
|
||||
pcOut->mTransformation.Inverse(); */
|
||||
|
||||
// (code for keyframe animation. however, this is currently not supported by Assimp)
|
||||
#if 0
|
||||
if (pcOut->mTransformation != mF)
|
||||
{
|
||||
DefaultLogger::get()->warn("The local transformation matrix of the "
|
||||
"3ds file does not match the first keyframe. Using the "
|
||||
"information from the keyframe.");
|
||||
}
|
||||
#endif
|
||||
|
||||
pcOut->mTransformation = aiMatrix4x4();
|
||||
pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
|
||||
pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
|
||||
for (unsigned int i = 0; i < pcIn->mChildren.size();++i)
|
||||
@@ -697,13 +671,22 @@ void Dot3DSImporter::GenerateNodeGraph(aiScene* pcOut)
|
||||
else this->AddNodeToGraph(pcOut, pcOut->mRootNode, this->mRootNode);
|
||||
|
||||
for (unsigned int a = 0; a < pcOut->mNumMeshes;++a)
|
||||
{
|
||||
delete (std::string*)pcOut->mMeshes[a]->mColors[0];
|
||||
pcOut->mMeshes[a]->mColors[0] = NULL;
|
||||
|
||||
// may be NULL
|
||||
delete (aiMatrix4x4*)pcOut->mMeshes[a]->mColors[1];
|
||||
pcOut->mMeshes[a]->mColors[1] = NULL;
|
||||
// if the root node has only one child ... set the child as root node
|
||||
if (1 == pcOut->mRootNode->mNumChildren)
|
||||
{
|
||||
aiNode* pcOld = pcOut->mRootNode;
|
||||
pcOut->mRootNode = pcOut->mRootNode->mChildren[0];
|
||||
pcOut->mRootNode->mParent = NULL;
|
||||
pcOld->mChildren[0] = NULL;
|
||||
delete pcOld;
|
||||
}
|
||||
|
||||
// if the root node is a default node setup a name for it
|
||||
if (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$')
|
||||
{
|
||||
pcOut->mRootNode->mName.Set("<root>");
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -458,7 +458,11 @@ struct Mesh
|
||||
static int iCnt = 0;
|
||||
|
||||
char szTemp[128];
|
||||
sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
|
||||
#if _MSC_VER >= 1400
|
||||
::sprintf_s(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
|
||||
#else
|
||||
::sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
|
||||
#endif
|
||||
mName = szTemp;
|
||||
}
|
||||
|
||||
@@ -489,20 +493,24 @@ struct Node
|
||||
{
|
||||
Node()
|
||||
|
||||
// (code for keyframe animation. however, this is currently not supported by Assimp)
|
||||
#if 0
|
||||
: vScaling(1.0f,1.0f,1.0f)
|
||||
#endif
|
||||
: mHierarchyPos(0),mHierarchyIndex(0)
|
||||
|
||||
{
|
||||
static int iCnt = 0;
|
||||
|
||||
char szTemp[128];
|
||||
sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
|
||||
#if _MSC_VER >= 1400
|
||||
::sprintf_s(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
|
||||
#else
|
||||
::sprintf(szTemp,"$$_UNNAMED_%i_$$",iCnt++);
|
||||
#endif
|
||||
mName = szTemp;
|
||||
|
||||
mHierarchyPos = 0;
|
||||
mHierarchyIndex = 0;
|
||||
#ifdef AI_3DS_KEYFRAME_ANIMATION
|
||||
aRotationKeys.reserve(10);
|
||||
aPositionKeys.reserve(10);
|
||||
aScalingKeys.reserve(10);
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Pointer to the parent node
|
||||
@@ -520,14 +528,20 @@ struct Node
|
||||
//! Index of the node
|
||||
int16_t mHierarchyIndex;
|
||||
|
||||
// (code for keyframe animation. however, this is currently not supported by Assimp)
|
||||
#if 0
|
||||
aiVector3D vPivot;
|
||||
aiVector3D vScaling;
|
||||
aiMatrix4x4 mRotation;
|
||||
aiVector3D vPosition;
|
||||
#ifdef AI_3DS_KEYFRAME_ANIMATION
|
||||
//! Rotation keys loaded from the file
|
||||
std::vector<aiQuatKey> aRotationKeys;
|
||||
|
||||
//! Position keys loaded from the file
|
||||
std::vector<aiVectorKey> aPositionKeys;
|
||||
|
||||
//! Scaling keys loaded from the file
|
||||
std::vector<aiVectorKey> aScalingKeys;
|
||||
#endif
|
||||
|
||||
//! Pivot position loaded from the file
|
||||
aiVector3D vPivot;
|
||||
|
||||
//! Add a child node, setup the right parent node for it
|
||||
//! \param pc Node to be 'adopted'
|
||||
inline Node& push_back(Node* pc)
|
||||
|
||||
@@ -139,7 +139,17 @@ void Dot3DSImporter::InternReadFile(
|
||||
this->bHasBG = false;
|
||||
|
||||
int iRemaining = (unsigned int)fileSize;
|
||||
this->ParseMainChunk(&iRemaining);
|
||||
|
||||
// parse the file
|
||||
try
|
||||
{
|
||||
this->ParseMainChunk(iRemaining);
|
||||
}
|
||||
catch ( ImportErrorException* ex)
|
||||
{
|
||||
delete[] this->mBuffer;
|
||||
throw ex;
|
||||
};
|
||||
|
||||
// Generate an unique set of vertices/indices for
|
||||
// all meshes contained in the file
|
||||
@@ -202,8 +212,7 @@ void Dot3DSImporter::ReadChunk(const Dot3DSFile::Chunk** p_ppcOut)
|
||||
// read chunk
|
||||
if (this->mCurrent >= this->mLast)
|
||||
{
|
||||
*p_ppcOut = NULL;
|
||||
return;
|
||||
throw new ImportErrorException("Unexpected end of file, can't read chunk header");
|
||||
}
|
||||
const uintptr_t iDiff = this->mLast - this->mCurrent;
|
||||
if (iDiff < sizeof(Dot3DSFile::Chunk))
|
||||
@@ -211,18 +220,21 @@ void Dot3DSImporter::ReadChunk(const Dot3DSFile::Chunk** p_ppcOut)
|
||||
*p_ppcOut = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*p_ppcOut = (const Dot3DSFile::Chunk*) this->mCurrent;
|
||||
if ((**p_ppcOut).Size + this->mCurrent > this->mLast)
|
||||
{
|
||||
throw new ImportErrorException("Unexpected end of file, can't read chunk footer");
|
||||
}
|
||||
this->mCurrent += sizeof(Dot3DSFile::Chunk);
|
||||
return;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseMainChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseMainChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -235,7 +247,7 @@ void Dot3DSImporter::ParseMainChunk(int* piRemaining)
|
||||
case Dot3DSFile::CHUNK_MAIN:
|
||||
//case 0x444d: // bugfix
|
||||
|
||||
this->ParseEditorChunk(&iRemaining);
|
||||
this->ParseEditorChunk(iRemaining);
|
||||
break;
|
||||
};
|
||||
if (pcCurNext < this->mCurrent)
|
||||
@@ -247,17 +259,17 @@ void Dot3DSImporter::ParseMainChunk(int* piRemaining)
|
||||
}
|
||||
// Go to the starting position of the next top-level chunk
|
||||
this->mCurrent = pcCurNext;
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return this->ParseMainChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseEditorChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseEditorChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -269,14 +281,35 @@ void Dot3DSImporter::ParseEditorChunk(int* piRemaining)
|
||||
{
|
||||
case Dot3DSFile::CHUNK_OBJMESH:
|
||||
|
||||
this->ParseObjectChunk(&iRemaining);
|
||||
this->ParseObjectChunk(iRemaining);
|
||||
break;
|
||||
|
||||
// NOTE: In several documentations in the internet this
|
||||
// chunk appears at different locations
|
||||
case Dot3DSFile::CHUNK_KEYFRAMER:
|
||||
|
||||
this->ParseKeyframeChunk(&iRemaining);
|
||||
this->ParseKeyframeChunk(iRemaining);
|
||||
break;
|
||||
|
||||
case Dot3DSFile::CHUNK_VERSION:
|
||||
|
||||
if (psChunk->Size >= 2+sizeof(Dot3DSFile::Chunk))
|
||||
{
|
||||
// print the version number
|
||||
char szBuffer[128];
|
||||
#if _MSC_VER >= 1400
|
||||
::sprintf_s(szBuffer,"3DS file version chunk: %i",
|
||||
(int) *((uint16_t*)this->mCurrent));
|
||||
#else
|
||||
::sprintf(szBuffer,"3DS file version chunk: %i",
|
||||
(int) *((uint16_t*)this->mCurrent));
|
||||
#endif
|
||||
DefaultLogger::get()->info(szBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultLogger::get()->warn("Invalid version chunk in 3DS file");
|
||||
}
|
||||
break;
|
||||
};
|
||||
if (pcCurNext < this->mCurrent)
|
||||
@@ -288,17 +321,17 @@ void Dot3DSImporter::ParseEditorChunk(int* piRemaining)
|
||||
}
|
||||
// Go to the starting position of the next top-level chunk
|
||||
this->mCurrent = pcCurNext;
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return this->ParseEditorChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseObjectChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseObjectChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -329,13 +362,13 @@ void Dot3DSImporter::ParseObjectChunk(int* piRemaining)
|
||||
|
||||
this->mCurrent += iCnt;
|
||||
iRemaining -= iCnt;
|
||||
this->ParseChunk(&iRemaining);
|
||||
this->ParseChunk(iRemaining);
|
||||
break;
|
||||
|
||||
case Dot3DSFile::CHUNK_MAT_MATERIAL:
|
||||
|
||||
this->mScene->mMaterials.push_back(Dot3DS::Material());
|
||||
this->ParseMaterialChunk(&iRemaining);
|
||||
this->ParseMaterialChunk(iRemaining);
|
||||
break;
|
||||
|
||||
case Dot3DSFile::CHUNK_AMBCOLOR:
|
||||
@@ -373,7 +406,7 @@ void Dot3DSImporter::ParseObjectChunk(int* piRemaining)
|
||||
// chunk appears at different locations
|
||||
case Dot3DSFile::CHUNK_KEYFRAMER:
|
||||
|
||||
this->ParseKeyframeChunk(&iRemaining);
|
||||
this->ParseKeyframeChunk(iRemaining);
|
||||
break;
|
||||
|
||||
};
|
||||
@@ -386,8 +419,8 @@ void Dot3DSImporter::ParseObjectChunk(int* piRemaining)
|
||||
}
|
||||
// Go to the starting position of the next top-level chunk
|
||||
this->mCurrent = pcCurNext;
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return this->ParseObjectChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -395,17 +428,17 @@ void Dot3DSImporter::SkipChunk()
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
this->mCurrent += psChunk->Size - sizeof(Dot3DSFile::Chunk);
|
||||
return;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -417,7 +450,7 @@ void Dot3DSImporter::ParseChunk(int* piRemaining)
|
||||
{
|
||||
case Dot3DSFile::CHUNK_TRIMESH:
|
||||
// this starts a new mesh
|
||||
this->ParseMeshChunk(&iRemaining);
|
||||
this->ParseMeshChunk(iRemaining);
|
||||
break;
|
||||
};
|
||||
if (pcCurNext < this->mCurrent)
|
||||
@@ -430,17 +463,17 @@ void Dot3DSImporter::ParseChunk(int* piRemaining)
|
||||
// Go to the starting position of the next top-level chunk
|
||||
this->mCurrent = pcCurNext;
|
||||
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return this->ParseChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseKeyframeChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseKeyframeChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -452,7 +485,7 @@ void Dot3DSImporter::ParseKeyframeChunk(int* piRemaining)
|
||||
{
|
||||
case Dot3DSFile::CHUNK_TRACKINFO:
|
||||
// this starts a new mesh
|
||||
this->ParseHierarchyChunk(&iRemaining);
|
||||
this->ParseHierarchyChunk(iRemaining);
|
||||
break;
|
||||
};
|
||||
if (pcCurNext < this->mCurrent)
|
||||
@@ -465,8 +498,8 @@ void Dot3DSImporter::ParseKeyframeChunk(int* piRemaining)
|
||||
// Go to the starting position of the next top-level chunk
|
||||
this->mCurrent = pcCurNext;
|
||||
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return this->ParseKeyframeChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -487,12 +520,12 @@ void Dot3DSImporter::InverseNodeSearch(Dot3DS::Node* pcNode,Dot3DS::Node* pcCurr
|
||||
return this->InverseNodeSearch(pcNode,pcCurrent->mParent);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseHierarchyChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -545,15 +578,14 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
|
||||
this->mCurrentNode = pcNode;
|
||||
break;
|
||||
|
||||
// (code for keyframe animation. however, this is currently not supported by Assimp)
|
||||
#if 0
|
||||
|
||||
case Dot3DSFile::CHUNK_TRACKPIVOT:
|
||||
|
||||
this->mCurrentNode->vPivot = *((aiVector3D*)this->mCurrent);
|
||||
// pivot = origin of rotation and scaling
|
||||
this->mCurrentNode->vPivot = *((const aiVector3D*)this->mCurrent);
|
||||
this->mCurrent += sizeof(aiVector3D);
|
||||
break;
|
||||
|
||||
#ifdef AI_3DS_KEYFRAME_ANIMATION
|
||||
|
||||
case Dot3DSFile::CHUNK_TRACKPOS:
|
||||
|
||||
@@ -569,26 +601,32 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
|
||||
} pos[keys];
|
||||
*/
|
||||
this->mCurrent += 10;
|
||||
iTemp = *((uint16_t*)mCurrent);
|
||||
iTemp = *((const uint16_t*)mCurrent);
|
||||
|
||||
this->mCurrent += sizeof(uint16_t) * 2;
|
||||
|
||||
if (0 != iTemp)
|
||||
{
|
||||
for (unsigned int i = 0; i < (unsigned int)iTemp;++i)
|
||||
{
|
||||
uint16_t sNum = *((uint16_t*)mCurrent);
|
||||
this->mCurrent += sizeof(uint16_t);
|
||||
for (unsigned int i = 0; i < (unsigned int)iTemp;++i)
|
||||
{
|
||||
uint16_t sNum = *((const uint16_t*)mCurrent);
|
||||
this->mCurrent += sizeof(uint16_t);
|
||||
|
||||
if (0 == sNum)
|
||||
{
|
||||
this->mCurrent += sizeof(uint32_t);
|
||||
this->mCurrentNode->vPosition = *((aiVector3D*)this->mCurrent);
|
||||
this->mCurrent += sizeof(aiVector3D);
|
||||
}
|
||||
else this->mCurrent += sizeof(uint32_t) + sizeof(aiVector3D);
|
||||
}
|
||||
aiVectorKey v;
|
||||
v.mTime = (double)sNum;
|
||||
|
||||
this->mCurrent += sizeof(uint32_t);
|
||||
v.mValue = *((const aiVector3D*)this->mCurrent);
|
||||
this->mCurrent += sizeof(aiVector3D);
|
||||
|
||||
// check whether we do already have this keyframe
|
||||
for (std::vector<aiVectorKey>::const_iterator
|
||||
i = this->mCurrentNode->aPositionKeys.begin();
|
||||
i != this->mCurrentNode->aPositionKeys.end();++i)
|
||||
{
|
||||
if ((*i).mTime == v.mTime){v.mTime = -10e10f;break;}
|
||||
}
|
||||
// add the new keyframe
|
||||
if (v.mTime != -10e10f)this->mCurrentNode->aPositionKeys.push_back(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case Dot3DSFile::CHUNK_TRACKROTATE:
|
||||
@@ -605,72 +643,39 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
|
||||
} pos[keys];
|
||||
*/
|
||||
this->mCurrent += 10;
|
||||
iTemp = *((uint16_t*)mCurrent);
|
||||
iTemp = *((const uint16_t*)mCurrent);
|
||||
|
||||
this->mCurrent += sizeof(uint16_t) * 2;
|
||||
if (0 != iTemp)
|
||||
|
||||
for (unsigned int i = 0; i < (unsigned int)iTemp;++i)
|
||||
{
|
||||
uint16_t sNum = *((const uint16_t*)mCurrent);
|
||||
this->mCurrent += sizeof(uint16_t);
|
||||
|
||||
aiQuatKey v;
|
||||
v.mTime = (double)sNum;
|
||||
|
||||
this->mCurrent += sizeof(uint32_t);
|
||||
|
||||
float fRadians = *((const float*)this->mCurrent);
|
||||
this->mCurrent += sizeof(float);
|
||||
|
||||
aiVector3D vAxis = *((const aiVector3D*)this->mCurrent);
|
||||
this->mCurrent += sizeof(aiVector3D);
|
||||
|
||||
// construct a rotation quaternion from the axis-angle pair
|
||||
v.mValue = aiQuaternion(vAxis,fRadians);
|
||||
|
||||
// check whether we do already have this keyframe
|
||||
for (std::vector<aiQuatKey>::const_iterator
|
||||
i = this->mCurrentNode->aRotationKeys.begin();
|
||||
i != this->mCurrentNode->aRotationKeys.end();++i)
|
||||
{
|
||||
bool neg = false;
|
||||
unsigned int iNum0 = 0;
|
||||
for (unsigned int i = 0; i < (unsigned int)iTemp;++i)
|
||||
{
|
||||
uint16_t sNum = *((uint16_t*)mCurrent);
|
||||
this->mCurrent += sizeof(uint16_t);
|
||||
|
||||
if (0 == sNum)
|
||||
{
|
||||
this->mCurrent += sizeof(uint32_t);
|
||||
float fRadians = *((float*)this->mCurrent);
|
||||
this->mCurrent += sizeof(float);
|
||||
aiVector3D vAxis = *((aiVector3D*)this->mCurrent);
|
||||
this->mCurrent += sizeof(aiVector3D);
|
||||
|
||||
// some idiotic files have rotations with fRadians = 0 ...
|
||||
if (0.0f != fRadians)
|
||||
{
|
||||
|
||||
// get the rotation matrix around the axis
|
||||
const float fSin = sinf(-fRadians);
|
||||
const float fCos = cosf(-fRadians);
|
||||
const float fOneMinusCos = 1.0f - fCos;
|
||||
|
||||
std::swap(vAxis.z,vAxis.y);
|
||||
//vAxis.z *= -1.0f;
|
||||
//vAxis.Normalize();
|
||||
|
||||
aiMatrix4x4 mRot = aiMatrix4x4(
|
||||
(vAxis.x * vAxis.x) * fOneMinusCos + fCos,
|
||||
(vAxis.x * vAxis.y) * fOneMinusCos /*-*/- (vAxis.z * fSin),
|
||||
(vAxis.x * vAxis.z) * fOneMinusCos /*+*/+ (vAxis.y * fSin),
|
||||
0.0f,
|
||||
(vAxis.y * vAxis.x) * fOneMinusCos /*+*/+ (vAxis.z * fSin),
|
||||
(vAxis.y * vAxis.y) * fOneMinusCos + fCos,
|
||||
(vAxis.y * vAxis.z) * fOneMinusCos /*-*/- (vAxis.x * fSin),
|
||||
0.0f,
|
||||
(vAxis.z * vAxis.x) * fOneMinusCos /*-*/- (vAxis.y * fSin),
|
||||
(vAxis.z * vAxis.y) * fOneMinusCos /*+*/+ (vAxis.x * fSin),
|
||||
(vAxis.z * vAxis.z) * fOneMinusCos + fCos,
|
||||
0.0f,0.0f,0.0f,0.0f,1.0f);
|
||||
mRot.Transpose();
|
||||
|
||||
// build a chain of concatenated rotation matrix'
|
||||
// if there are multiple track chunks for the same frame
|
||||
// (there are some silly files usinf this ...)
|
||||
if (0 != iNum0)
|
||||
{
|
||||
this->mCurrentNode->mRotation = this->mCurrentNode->mRotation * mRot;
|
||||
}
|
||||
else
|
||||
{
|
||||
// for the first time simply set the rotation matrix
|
||||
this->mCurrentNode->mRotation = mRot;
|
||||
}
|
||||
iNum0++;
|
||||
}
|
||||
}
|
||||
else this->mCurrent += sizeof(uint32_t) + sizeof(aiVector3D) + sizeof(float);
|
||||
}
|
||||
if ((*i).mTime == v.mTime){v.mTime = -10e10f;break;}
|
||||
}
|
||||
// add the new keyframe
|
||||
if (v.mTime != -10e10f)this->mCurrentNode->aRotationKeys.push_back(v);
|
||||
}
|
||||
break;
|
||||
|
||||
case Dot3DSFile::CHUNK_TRACKSCALE:
|
||||
@@ -687,40 +692,45 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
|
||||
} pos[keys];
|
||||
*/
|
||||
this->mCurrent += 10;
|
||||
iTemp = *((uint16_t*)mCurrent);
|
||||
iTemp = *((const uint16_t*)mCurrent);
|
||||
|
||||
this->mCurrent += sizeof(uint16_t) * 2;
|
||||
for (unsigned int i = 0; i < (unsigned int)iTemp;++i)
|
||||
{
|
||||
uint16_t sNum = *((const uint16_t*)mCurrent);
|
||||
this->mCurrent += sizeof(uint16_t);
|
||||
|
||||
if (0 != iTemp)
|
||||
aiVectorKey v;
|
||||
v.mTime = (double)sNum;
|
||||
|
||||
this->mCurrent += sizeof(uint32_t);
|
||||
v.mValue = *((const aiVector3D*)this->mCurrent);
|
||||
this->mCurrent += sizeof(aiVector3D);
|
||||
|
||||
// check whether we do already have this keyframe
|
||||
for (std::vector<aiVectorKey>::const_iterator
|
||||
i = this->mCurrentNode->aScalingKeys.begin();
|
||||
i != this->mCurrentNode->aScalingKeys.end();++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < (unsigned int)iTemp;++i)
|
||||
{
|
||||
uint16_t sNum = *((uint16_t*)mCurrent);
|
||||
this->mCurrent += sizeof(uint16_t);
|
||||
if (0 == sNum)
|
||||
{
|
||||
this->mCurrent += sizeof(uint32_t);
|
||||
aiVector3D vMe = *((aiVector3D*)this->mCurrent);
|
||||
// ignore zero scalings
|
||||
if (0.0f != vMe.x && 0.0f != vMe.y && 0.0f != vMe.z)
|
||||
{
|
||||
this->mCurrentNode->vScaling.x *= vMe.x;
|
||||
this->mCurrentNode->vScaling.y *= vMe.y;
|
||||
this->mCurrentNode->vScaling.z *= vMe.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultLogger::get()->warn("Found zero scaling factors. "
|
||||
"This will be ignored.");
|
||||
}
|
||||
this->mCurrent += sizeof(aiVector3D);
|
||||
}
|
||||
else this->mCurrent += sizeof(uint32_t) + sizeof(aiVector3D);
|
||||
}
|
||||
if ((*i).mTime == v.mTime){v.mTime = -10e10f;break;}
|
||||
}
|
||||
break;
|
||||
#endif // end keyframe animation code
|
||||
// add the new keyframe
|
||||
if (v.mTime != -10e10f)this->mCurrentNode->aScalingKeys.push_back(v);
|
||||
|
||||
if (v.mValue.x && v.mValue.y && v.mValue.z)
|
||||
{
|
||||
DefaultLogger::get()->warn("Found zero scaled axis in scaling keyframe");
|
||||
++iCnt;
|
||||
}
|
||||
}
|
||||
// there are 3DS files that have only zero scalings
|
||||
if (iTemp == iCnt)
|
||||
{
|
||||
DefaultLogger::get()->warn("All scaling keys are zero. They will be removed");
|
||||
this->mCurrentNode->aScalingKeys.clear();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
};
|
||||
if (pcCurNext < this->mCurrent)
|
||||
{
|
||||
@@ -732,19 +742,19 @@ void Dot3DSImporter::ParseHierarchyChunk(int* piRemaining)
|
||||
// Go to the starting position of the next top-level chunk
|
||||
this->mCurrent = pcCurNext;
|
||||
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return this->ParseHierarchyChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseFaceChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
Dot3DS::Mesh& mMesh = this->mScene->mMeshes.back();
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -833,19 +843,19 @@ void Dot3DSImporter::ParseFaceChunk(int* piRemaining)
|
||||
// Go to the starting position of the next chunk on this level
|
||||
this->mCurrent = pcCurNext;
|
||||
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return ParseFaceChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseMeshChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
Dot3DS::Mesh& mMesh = this->mScene->mMeshes.back();
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -866,11 +876,12 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
|
||||
while (iNum-- > 0)
|
||||
{
|
||||
mMesh.mPositions.push_back(*((aiVector3D*)this->mCurrent));
|
||||
mMesh.mPositions.back().z *= -1.0f;
|
||||
aiVector3D& v = mMesh.mPositions.back();
|
||||
//std::swap( v.y, v.z);
|
||||
//v.y *= -1.0f;
|
||||
this->mCurrent += sizeof(aiVector3D);
|
||||
}
|
||||
break;
|
||||
|
||||
case Dot3DSFile::CHUNK_TRMATRIX:
|
||||
{
|
||||
// http://www.gamedev.net/community/forums/topic.asp?topic_id=263063
|
||||
@@ -879,43 +890,21 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
|
||||
this->mCurrent += 12 * sizeof(float);
|
||||
|
||||
mMesh.mMat.a1 = pf[0];
|
||||
mMesh.mMat.a2 = pf[1];
|
||||
mMesh.mMat.a3 = pf[2];
|
||||
mMesh.mMat.b1 = pf[3];
|
||||
mMesh.mMat.b1 = pf[1];
|
||||
mMesh.mMat.c1 = pf[2];
|
||||
mMesh.mMat.a2 = pf[3];
|
||||
mMesh.mMat.b2 = pf[4];
|
||||
mMesh.mMat.b3 = pf[5];
|
||||
mMesh.mMat.c1 = pf[6];
|
||||
mMesh.mMat.c2 = pf[7];
|
||||
mMesh.mMat.c2 = pf[5];
|
||||
mMesh.mMat.a3 = pf[6];
|
||||
mMesh.mMat.b3 = pf[7];
|
||||
mMesh.mMat.c3 = pf[8];
|
||||
mMesh.mMat.d1 = pf[9];
|
||||
mMesh.mMat.d2 = pf[10];
|
||||
mMesh.mMat.d3 = pf[11];
|
||||
|
||||
std::swap((float&)mMesh.mMat.d2, (float&)mMesh.mMat.d3);
|
||||
std::swap((float&)mMesh.mMat.a2, (float&)mMesh.mMat.a3);
|
||||
std::swap((float&)mMesh.mMat.b1, (float&)mMesh.mMat.c1);
|
||||
std::swap((float&)mMesh.mMat.c2, (float&)mMesh.mMat.b3);
|
||||
std::swap((float&)mMesh.mMat.b2, (float&)mMesh.mMat.c3);
|
||||
|
||||
mMesh.mMat.Transpose();
|
||||
|
||||
//aiMatrix4x4 mInv = mMesh.mMat;
|
||||
//mInv.Inverse();
|
||||
|
||||
//// invert the matrix and transform all vertices with it
|
||||
//// (the origin of all vertices is 0|0|0 now)
|
||||
//for (register unsigned int i = 0; i < mMesh.mPositions.size();++i)
|
||||
// {
|
||||
// aiVector3D a,c;
|
||||
// a = mMesh.mPositions[i];
|
||||
// c[0]= mInv[0][0]*a[0] + mInv[1][0]*a[1] + mInv[2][0]*a[2] + mInv[3][0];
|
||||
// c[1]= mInv[0][1]*a[0] + mInv[1][1]*a[1] + mInv[2][1]*a[2] + mInv[3][1];
|
||||
// c[2]= mInv[0][2]*a[0] + mInv[1][2]*a[1] + mInv[2][2]*a[2] + mInv[3][2];
|
||||
// mMesh.mPositions[i] = c;
|
||||
// }
|
||||
mMesh.mMat.a4 = pf[9];
|
||||
mMesh.mMat.b4 = pf[10];
|
||||
mMesh.mMat.c4 = pf[11];
|
||||
//mMesh.mMat.Transpose(); // todo ----
|
||||
|
||||
// now check whether the matrix has got a negative determinant
|
||||
// If yes, we need to flip all vertices x axis ....
|
||||
// If yes, we need to flip all vertices' x axis ....
|
||||
// From lib3ds, mesh.c
|
||||
if (mMesh.mMat.Determinant() < 0.0f)
|
||||
{
|
||||
@@ -938,9 +927,9 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
|
||||
mMesh.mPositions[i] = c;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case Dot3DSFile::CHUNK_MAPLIST:
|
||||
|
||||
iNum = *((uint16_t*)this->mCurrent);
|
||||
@@ -983,7 +972,7 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
|
||||
mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd);
|
||||
|
||||
iRemaining = (int)(pcCurNext - this->mCurrent);
|
||||
if (iRemaining > 0)this->ParseFaceChunk(&iRemaining);
|
||||
if (iRemaining > 0)this->ParseFaceChunk(iRemaining);
|
||||
break;
|
||||
|
||||
};
|
||||
@@ -997,17 +986,17 @@ void Dot3DSImporter::ParseMeshChunk(int* piRemaining)
|
||||
// Go to the starting position of the next chunk on this level
|
||||
this->mCurrent = pcCurNext;
|
||||
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return ParseMeshChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseMaterialChunk(int* piRemaining)
|
||||
void Dot3DSImporter::ParseMaterialChunk(int& piRemaining)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -1121,27 +1110,27 @@ void Dot3DSImporter::ParseMaterialChunk(int* piRemaining)
|
||||
// parse texture chunks
|
||||
case Dot3DSFile::CHUNK_MAT_TEXTURE:
|
||||
iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
|
||||
this->ParseTextureChunk(&iRemaining,&this->mScene->mMaterials.back().sTexDiffuse);
|
||||
this->ParseTextureChunk(iRemaining,&this->mScene->mMaterials.back().sTexDiffuse);
|
||||
break;
|
||||
case Dot3DSFile::CHUNK_MAT_BUMPMAP:
|
||||
iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
|
||||
this->ParseTextureChunk(&iRemaining,&this->mScene->mMaterials.back().sTexBump);
|
||||
this->ParseTextureChunk(iRemaining,&this->mScene->mMaterials.back().sTexBump);
|
||||
break;
|
||||
case Dot3DSFile::CHUNK_MAT_OPACMAP:
|
||||
iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
|
||||
this->ParseTextureChunk(&iRemaining,&this->mScene->mMaterials.back().sTexOpacity);
|
||||
this->ParseTextureChunk(iRemaining,&this->mScene->mMaterials.back().sTexOpacity);
|
||||
break;
|
||||
case Dot3DSFile::CHUNK_MAT_MAT_SHINMAP:
|
||||
iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
|
||||
this->ParseTextureChunk(&iRemaining,&this->mScene->mMaterials.back().sTexShininess);
|
||||
this->ParseTextureChunk(iRemaining,&this->mScene->mMaterials.back().sTexShininess);
|
||||
break;
|
||||
case Dot3DSFile::CHUNK_MAT_SPECMAP:
|
||||
iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
|
||||
this->ParseTextureChunk(&iRemaining,&this->mScene->mMaterials.back().sTexSpecular);
|
||||
this->ParseTextureChunk(iRemaining,&this->mScene->mMaterials.back().sTexSpecular);
|
||||
break;
|
||||
case Dot3DSFile::CHUNK_MAT_SELFIMAP:
|
||||
iRemaining = (psChunk->Size - sizeof(Dot3DSFile::Chunk));
|
||||
this->ParseTextureChunk(&iRemaining,&this->mScene->mMaterials.back().sTexEmissive);
|
||||
this->ParseTextureChunk(iRemaining,&this->mScene->mMaterials.back().sTexEmissive);
|
||||
break;
|
||||
};
|
||||
if (pcCurNext < this->mCurrent)
|
||||
@@ -1154,17 +1143,17 @@ void Dot3DSImporter::ParseMaterialChunk(int* piRemaining)
|
||||
// Go to the starting position of the next chunk on this level
|
||||
this->mCurrent = pcCurNext;
|
||||
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return ParseMaterialChunk(piRemaining);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Dot3DSImporter::ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut)
|
||||
void Dot3DSImporter::ParseTextureChunk(int& piRemaining,Dot3DS::Texture* pcOut)
|
||||
{
|
||||
const Dot3DSFile::Chunk* psChunk;
|
||||
|
||||
this->ReadChunk(&psChunk);
|
||||
if (NULL == psChunk)return;
|
||||
|
||||
|
||||
const unsigned char* pcCur = this->mCurrent;
|
||||
const unsigned char* pcCurNext = pcCur + (psChunk->Size
|
||||
@@ -1246,8 +1235,8 @@ void Dot3DSImporter::ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut)
|
||||
// Go to the starting position of the next chunk on this level
|
||||
this->mCurrent = pcCurNext;
|
||||
|
||||
*piRemaining -= psChunk->Size;
|
||||
if (0 >= *piRemaining)return;
|
||||
piRemaining -= psChunk->Size;
|
||||
if (0 >= piRemaining)return;
|
||||
return ParseTextureChunk(piRemaining,pcOut);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -138,52 +138,52 @@ protected:
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a main top-level chunk in the file
|
||||
*/
|
||||
void ParseMainChunk(int* piRemaining);
|
||||
void ParseMainChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a top-level chunk in the file
|
||||
*/
|
||||
void ParseChunk(int* piRemaining);
|
||||
void ParseChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a top-level editor chunk in the file
|
||||
*/
|
||||
void ParseEditorChunk(int* piRemaining);
|
||||
void ParseEditorChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a top-level object chunk in the file
|
||||
*/
|
||||
void ParseObjectChunk(int* piRemaining);
|
||||
void ParseObjectChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a material chunk in the file
|
||||
*/
|
||||
void ParseMaterialChunk(int* piRemaining);
|
||||
void ParseMaterialChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a mesh chunk in the file
|
||||
*/
|
||||
void ParseMeshChunk(int* piRemaining);
|
||||
void ParseMeshChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a face list chunk in the file
|
||||
*/
|
||||
void ParseFaceChunk(int* piRemaining);
|
||||
void ParseFaceChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a keyframe chunk in the file
|
||||
*/
|
||||
void ParseKeyframeChunk(int* piRemaining);
|
||||
void ParseKeyframeChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a hierarchy chunk in the file
|
||||
*/
|
||||
void ParseHierarchyChunk(int* piRemaining);
|
||||
void ParseHierarchyChunk(int& piRemaining);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Parse a texture chunk in the file
|
||||
*/
|
||||
void ParseTextureChunk(int* piRemaining,Dot3DS::Texture* pcOut);
|
||||
void ParseTextureChunk(int& piRemaining,Dot3DS::Texture* pcOut);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Convert the meshes in the file
|
||||
|
||||
@@ -105,7 +105,7 @@ bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
||||
void ASEImporter::InternReadFile(
|
||||
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
|
||||
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rt"));
|
||||
|
||||
// Check whether we can read from the file
|
||||
if( file.get() == NULL)
|
||||
@@ -195,7 +195,7 @@ void ASEImporter::GenerateDefaultMaterial()
|
||||
mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
|
||||
mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f);
|
||||
mat.mShading = Dot3DSFile::Gouraud;
|
||||
mat.mName = "$$$ASE_DEFAULT";
|
||||
mat.mName = AI_DEFAULT_MATERIAL_NAME;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ASEImporter::AddNodes(aiScene* pcScene,aiNode* pcParent,
|
||||
|
||||
@@ -41,19 +41,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** @file Implementation of the ASE parser class */
|
||||
|
||||
// internal headers
|
||||
#include "TextureTransform.h"
|
||||
#include "ASELoader.h"
|
||||
#include "MaterialSystem.h"
|
||||
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
// public ASSIMP headers
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/IOStream.h"
|
||||
#include "../include/IOSystem.h"
|
||||
#include "../include/aiMesh.h"
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/aiAssert.h"
|
||||
|
||||
// boost headers
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
@@ -134,7 +136,7 @@ bool Parser::SkipToNextToken()
|
||||
|
||||
// increase the line number counter if necessary
|
||||
if (IsLineEnd(me))++this->iLineNumber;
|
||||
else if ('*' == me || '}' == me || '{' == me)return true;
|
||||
if ('*' == me || '}' == me || '{' == me)return true;
|
||||
else if ('\0' == me)return false;
|
||||
|
||||
++this->m_szFile;
|
||||
|
||||
@@ -81,14 +81,10 @@ inline bool SkipLine( const char_t* in, const char_t** out)
|
||||
{
|
||||
while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++;
|
||||
|
||||
if (*in == (char_t)'\0')
|
||||
{
|
||||
*out = in;
|
||||
return false;
|
||||
}
|
||||
in++;
|
||||
// files are opened in binary mode. Ergo there are both NL and CR
|
||||
while (*in == (char_t)'\r' || *in == (char_t)'\n')in++;
|
||||
*out = in;
|
||||
return true;
|
||||
return *in != (char_t)'\0';
|
||||
}
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
@@ -98,11 +94,12 @@ inline bool SkipLine( const char_t** inout)
|
||||
}
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
inline void SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
|
||||
inline bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
|
||||
{
|
||||
while (*in == (char_t)' ' || *in == (char_t)'\t' ||
|
||||
*in == (char_t)'\r' || *in == (char_t)'\n')in++;
|
||||
*out = in;
|
||||
return *in != '\0';
|
||||
}
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
|
||||
@@ -135,7 +135,7 @@ void PLYImporter::InternReadFile(
|
||||
{
|
||||
szMe += 6;
|
||||
SkipLine(szMe,(const char**)&szMe);
|
||||
if(!PLY::DOM::ParseInstance(szMe,&sPlyDom, (unsigned int)fileSize))
|
||||
if(!PLY::DOM::ParseInstance(szMe,&sPlyDom))
|
||||
{
|
||||
delete[] this->mBuffer;
|
||||
throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#1)");
|
||||
@@ -156,7 +156,7 @@ void PLYImporter::InternReadFile(
|
||||
|
||||
// skip the line, parse the rest of the header and build the DOM
|
||||
SkipLine(szMe,(const char**)&szMe);
|
||||
if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE, (unsigned int)fileSize))
|
||||
if(!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE))
|
||||
{
|
||||
delete[] this->mBuffer;
|
||||
throw new ImportErrorException( "Invalid .ply file: Unable to build DOM (#2)");
|
||||
|
||||
@@ -57,23 +57,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateOut(const char* szCur, const char* szMax)
|
||||
{
|
||||
if (szCur > szMax)
|
||||
{
|
||||
throw new ImportErrorException("Buffer overflow. PLY file contains invalid indices");
|
||||
}
|
||||
return;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_szOut)
|
||||
{
|
||||
ai_assert(NULL != p_szIn);
|
||||
ai_assert(NULL != p_szOut);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
|
||||
PLY::EDataType eOut = PLY::EDT_INVALID;
|
||||
|
||||
@@ -156,7 +145,6 @@ PLY::EDataType PLY::Property::ParseDataType(const char* p_szIn,const char** p_sz
|
||||
DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK");
|
||||
}
|
||||
*p_szOut = p_szIn;
|
||||
ValidateOut(p_szIn,szMax);
|
||||
return eOut;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -165,8 +153,6 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz
|
||||
ai_assert(NULL != p_szIn);
|
||||
ai_assert(NULL != p_szOut);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
|
||||
PLY::ESemantic eOut = PLY::EST_INVALID;
|
||||
if (0 == ASSIMP_strincmp(p_szIn,"red",3))
|
||||
{
|
||||
@@ -336,7 +322,6 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* p_szIn,const char** p_sz
|
||||
{
|
||||
eOut = PLY::EST_INVALID;
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return eOut;
|
||||
}
|
||||
@@ -351,7 +336,6 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
|
||||
// Forms supported:
|
||||
// "property float x"
|
||||
// "property list uchar int vertex_index"
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
// skip leading spaces
|
||||
@@ -373,44 +357,36 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
|
||||
|
||||
// seems to be a list.
|
||||
p_szIn += 5;
|
||||
const char* szPass = szMax;
|
||||
if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(p_szIn, &szPass)))
|
||||
if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
|
||||
{
|
||||
// unable to parse list size data type
|
||||
SkipLine(p_szIn,&p_szIn);
|
||||
*p_szOut = p_szIn;
|
||||
return false;
|
||||
}
|
||||
p_szIn = szPass;
|
||||
if (!SkipSpaces(p_szIn,&p_szIn))return false;
|
||||
szPass = szMax;
|
||||
if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &szPass)))
|
||||
if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
|
||||
{
|
||||
// unable to parse list data type
|
||||
SkipLine(p_szIn,&p_szIn);
|
||||
*p_szOut = p_szIn;
|
||||
return false;
|
||||
}
|
||||
p_szIn = szPass;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* szPass = szMax;
|
||||
if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &szPass)))
|
||||
if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(p_szIn, &p_szIn)))
|
||||
{
|
||||
// unable to parse data type. Skip the property
|
||||
SkipLine(p_szIn,&p_szIn);
|
||||
*p_szOut = p_szIn;
|
||||
return false;
|
||||
}
|
||||
p_szIn = szPass;
|
||||
}
|
||||
|
||||
if (!SkipSpaces(p_szIn,&p_szIn))return false;
|
||||
const char* szCur = p_szIn;
|
||||
const char* szPass = szMax;
|
||||
pOut->Semantic = PLY::Property::ParseSemantic(p_szIn, &szPass);
|
||||
p_szIn = szPass;
|
||||
pOut->Semantic = PLY::Property::ParseSemantic(p_szIn, &p_szIn);
|
||||
|
||||
if (PLY::EST_INVALID == pOut->Semantic)
|
||||
{
|
||||
@@ -422,7 +398,6 @@ bool PLY::Property::ParseProperty (const char* p_szIn,
|
||||
}
|
||||
|
||||
SkipSpacesAndLineEnd(p_szIn,&p_szIn);
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -433,8 +408,6 @@ PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,
|
||||
ai_assert(NULL != p_szIn);
|
||||
ai_assert(NULL != p_szOut);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
|
||||
PLY::EElementSemantic eOut = PLY::EEST_INVALID;
|
||||
if (0 == ASSIMP_strincmp(p_szIn,"vertex",6))
|
||||
{
|
||||
@@ -474,7 +447,6 @@ PLY::EElementSemantic PLY::Element::ParseSemantic(const char* p_szIn,
|
||||
{
|
||||
eOut = PLY::EEST_INVALID;
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return eOut;
|
||||
}
|
||||
@@ -488,7 +460,6 @@ bool PLY::Element::ParseElement (const char* p_szIn,
|
||||
ai_assert(NULL != pOut);
|
||||
|
||||
// Example format: "element vertex 8"
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
// skip leading spaces
|
||||
@@ -506,10 +477,7 @@ bool PLY::Element::ParseElement (const char* p_szIn,
|
||||
|
||||
// parse the semantic of the element
|
||||
const char* szCur = p_szIn;
|
||||
const char* szPass = szMax;
|
||||
pOut->eSemantic = PLY::Element::ParseSemantic(p_szIn,&szPass);
|
||||
p_szIn = szPass;
|
||||
|
||||
pOut->eSemantic = PLY::Element::ParseSemantic(p_szIn,&p_szIn);
|
||||
if (PLY::EEST_INVALID == pOut->eSemantic)
|
||||
{
|
||||
// store the name of the semantic
|
||||
@@ -534,14 +502,11 @@ bool PLY::Element::ParseElement (const char* p_szIn,
|
||||
|
||||
PLY::Property* prop = new PLY::Property();
|
||||
|
||||
const char* szPass = szMax;
|
||||
if(!PLY::Property::ParseProperty(p_szIn,&szPass,prop))break;
|
||||
p_szIn = szPass;
|
||||
if(!PLY::Property::ParseProperty(p_szIn,&p_szIn,prop))break;
|
||||
|
||||
// add the property to the property list
|
||||
pOut->alProperties.push_back(prop);
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -552,7 +517,6 @@ bool PLY::DOM::SkipComments (const char* p_szIn,
|
||||
ai_assert(NULL != p_szIn);
|
||||
ai_assert(NULL != p_szOut);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
// skip spaces
|
||||
@@ -568,7 +532,6 @@ bool PLY::DOM::SkipComments (const char* p_szIn,
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return false;
|
||||
}
|
||||
@@ -591,11 +554,8 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
|
||||
PLY::DOM::SkipComments(p_szIn,&p_szIn);
|
||||
|
||||
PLY::Element* out = new PLY::Element();
|
||||
const char* szPass = szMax;
|
||||
if(PLY::Element::ParseElement(p_szIn,&szPass,out))
|
||||
if(PLY::Element::ParseElement(p_szIn,&p_szIn,out))
|
||||
{
|
||||
p_szIn = szPass;
|
||||
|
||||
// add the element to the list of elements
|
||||
this->alElements.push_back(out);
|
||||
}
|
||||
@@ -608,7 +568,6 @@ bool PLY::DOM::ParseHeader (const char* p_szIn,const char** p_szOut)
|
||||
// ignore unknown header elements
|
||||
}
|
||||
SkipSpacesAndLineEnd(p_szIn,&p_szIn);
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded");
|
||||
@@ -636,14 +595,10 @@ bool PLY::DOM::ParseElementInstanceLists (
|
||||
for (;i != this->alElements.end();++i,++a)
|
||||
{
|
||||
*a = new PLY::ElementInstanceList((*i)); // reserve enough storage
|
||||
|
||||
const char* szPass = szMax;
|
||||
PLY::ElementInstanceList::ParseInstanceList(p_szIn,&szPass,(*i),(*a));
|
||||
p_szIn = szPass;
|
||||
PLY::ElementInstanceList::ParseInstanceList(p_szIn,&p_szIn,(*i),(*a));
|
||||
}
|
||||
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded");
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -657,8 +612,6 @@ bool PLY::DOM::ParseElementInstanceListsBinary (
|
||||
ai_assert(NULL != p_szOut);
|
||||
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin");
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
this->alElementData.resize(this->alElements.size());
|
||||
@@ -670,34 +623,27 @@ bool PLY::DOM::ParseElementInstanceListsBinary (
|
||||
for (;i != this->alElements.end();++i,++a)
|
||||
{
|
||||
*a = new PLY::ElementInstanceList((*i)); // reserve enough storage
|
||||
const char* szPass = szMax;
|
||||
PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&szPass,(*i),(*a),p_bBE);
|
||||
p_szIn = szPass;
|
||||
PLY::ElementInstanceList::ParseInstanceListBinary(p_szIn,&p_szIn,(*i),(*a),p_bBE);
|
||||
}
|
||||
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded");
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool PLY::DOM::ParseInstanceBinary (const char* p_szIn,DOM* p_pcOut,bool p_bBE,unsigned int iSize)
|
||||
bool PLY::DOM::ParseInstanceBinary (const char* p_szIn,DOM* p_pcOut,bool p_bBE)
|
||||
{
|
||||
ai_assert(NULL != p_szIn);
|
||||
ai_assert(NULL != p_pcOut);
|
||||
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin");
|
||||
|
||||
const char* szMax = p_szIn + iSize;
|
||||
const char* szPass = szMax;
|
||||
if(!p_pcOut->ParseHeader(p_szIn,&szPass))
|
||||
if(!p_pcOut->ParseHeader(p_szIn,&p_szIn))
|
||||
{
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
|
||||
return false;
|
||||
}
|
||||
p_szIn = szPass;
|
||||
szPass = szMax;
|
||||
if(!p_pcOut->ParseElementInstanceListsBinary(p_szIn,&szPass,p_bBE))
|
||||
if(!p_pcOut->ParseElementInstanceListsBinary(p_szIn,&p_szIn,p_bBE))
|
||||
{
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure");
|
||||
return false;
|
||||
@@ -706,23 +652,20 @@ bool PLY::DOM::ParseInstanceBinary (const char* p_szIn,DOM* p_pcOut,bool p_bBE,u
|
||||
return true;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool PLY::DOM::ParseInstance (const char* p_szIn,DOM* p_pcOut,unsigned int iSize)
|
||||
bool PLY::DOM::ParseInstance (const char* p_szIn,DOM* p_pcOut)
|
||||
{
|
||||
ai_assert(NULL != p_szIn);
|
||||
ai_assert(NULL != p_pcOut);
|
||||
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin");
|
||||
|
||||
const char* szMax = p_szIn + iSize;
|
||||
const char* szPass = szMax;
|
||||
if(!p_pcOut->ParseHeader(p_szIn,&szPass))
|
||||
|
||||
if(!p_pcOut->ParseHeader(p_szIn,&p_szIn))
|
||||
{
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
|
||||
return false;
|
||||
}
|
||||
p_szIn = szPass;
|
||||
szPass = szMax;
|
||||
if(!p_pcOut->ParseElementInstanceLists(p_szIn,&szPass))
|
||||
if(!p_pcOut->ParseElementInstanceLists(p_szIn,&p_szIn))
|
||||
{
|
||||
DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure");
|
||||
return false;
|
||||
@@ -763,15 +706,11 @@ bool PLY::ElementInstanceList::ParseInstanceList (
|
||||
PLY::DOM::SkipComments(p_szIn,&p_szIn);
|
||||
|
||||
PLY::ElementInstance* out = new PLY::ElementInstance();
|
||||
|
||||
const char* szPass = szMax;
|
||||
PLY::ElementInstance::ParseInstance(p_szIn, &szPass,pcElement, out);
|
||||
p_szIn = szPass;
|
||||
PLY::ElementInstance::ParseInstance(p_szIn, &p_szIn,pcElement, out);
|
||||
// add it to the list
|
||||
p_pcOut->alInstances[i] = out;
|
||||
}
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -788,9 +727,6 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (
|
||||
ai_assert(NULL != pcElement);
|
||||
ai_assert(NULL != p_pcOut);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
// we can add special handling code for unknown element semantics since
|
||||
// we can't skip it as a whole block (we don't know its exact size
|
||||
// due to the fact that lists could be contained in the property list
|
||||
@@ -798,13 +734,10 @@ bool PLY::ElementInstanceList::ParseInstanceListBinary (
|
||||
for (unsigned int i = 0; i < pcElement->NumOccur;++i)
|
||||
{
|
||||
PLY::ElementInstance* out = new PLY::ElementInstance();
|
||||
const char* szPass = szMax;
|
||||
PLY::ElementInstance::ParseInstanceBinary(p_szIn, &p_szIn,pcElement, out, p_bBE);
|
||||
p_szIn = szPass;
|
||||
// add it to the list
|
||||
p_pcOut->alInstances[i] = out;
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -825,15 +758,11 @@ bool PLY::ElementInstance::ParseInstance (
|
||||
// allocate enough storage
|
||||
p_pcOut->alProperties.resize(pcElement->alProperties.size());
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin();
|
||||
std::vector<PLY::Property*>::const_iterator a = pcElement->alProperties.begin();
|
||||
for (;i != p_pcOut->alProperties.end();++i,++a)
|
||||
{
|
||||
const char* szPass = szMax;
|
||||
if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &szPass,(*a),&(*i))))
|
||||
if(!(PLY::PropertyInstance::ParseInstance(p_szIn, &p_szIn,(*a),&(*i))))
|
||||
{
|
||||
DefaultLogger::get()->warn("Unable to parse property instance. "
|
||||
"Skipping this element instance");
|
||||
@@ -844,9 +773,7 @@ bool PLY::ElementInstance::ParseInstance (
|
||||
PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType);
|
||||
(*i).avList.push_back(v);
|
||||
}
|
||||
p_szIn = szPass;
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -863,9 +790,6 @@ bool PLY::ElementInstance::ParseInstanceBinary (
|
||||
ai_assert(NULL != pcElement);
|
||||
ai_assert(NULL != p_pcOut);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
// allocate enough storage
|
||||
p_pcOut->alProperties.resize(pcElement->alProperties.size());
|
||||
|
||||
@@ -873,8 +797,7 @@ bool PLY::ElementInstance::ParseInstanceBinary (
|
||||
std::vector<PLY::Property*>::const_iterator a = pcElement->alProperties.begin();
|
||||
for (;i != p_pcOut->alProperties.end();++i,++a)
|
||||
{
|
||||
const char* szPass = szMax;
|
||||
if(!(PLY::PropertyInstance::ParseInstanceBinary(p_szIn, &szPass,(*a),&(*i),p_bBE)))
|
||||
if(!(PLY::PropertyInstance::ParseInstanceBinary(p_szIn, &p_szIn,(*a),&(*i),p_bBE)))
|
||||
{
|
||||
DefaultLogger::get()->warn("Unable to parse binary property instance. "
|
||||
"Skipping this element instance");
|
||||
@@ -882,9 +805,7 @@ bool PLY::ElementInstance::ParseInstanceBinary (
|
||||
PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a)->eType);
|
||||
(*i).avList.push_back(v);
|
||||
}
|
||||
p_szIn = szPass;
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -897,7 +818,6 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
|
||||
ai_assert(NULL != prop);
|
||||
ai_assert(NULL != p_pcOut);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
// skip spaces at the beginning
|
||||
@@ -907,10 +827,7 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
|
||||
{
|
||||
// parse the number of elements in the list
|
||||
PLY::PropertyInstance::ValueUnion v;
|
||||
|
||||
const char* szPass = szMax;
|
||||
PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eFirstType,&v);
|
||||
p_szIn = szPass;
|
||||
PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eFirstType,&v);
|
||||
|
||||
// convert to unsigned int
|
||||
unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
|
||||
@@ -919,10 +836,7 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
|
||||
for (unsigned int i = 0; i < iNum;++i)
|
||||
{
|
||||
if (!SkipSpaces(p_szIn, &p_szIn))return false;
|
||||
|
||||
const char* szPass = szMax;
|
||||
PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eType,&v);
|
||||
p_szIn = szPass;
|
||||
PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eType,&v);
|
||||
p_pcOut->avList.push_back(v);
|
||||
}
|
||||
}
|
||||
@@ -931,13 +845,10 @@ bool PLY::PropertyInstance::ParseInstance (const char* p_szIn,const char** p_szO
|
||||
// parse the property
|
||||
PLY::PropertyInstance::ValueUnion v;
|
||||
|
||||
const char* szPass = szMax;
|
||||
PLY::PropertyInstance::ParseValue(p_szIn, &szPass,prop->eType,&v);
|
||||
p_szIn = szPass;
|
||||
PLY::PropertyInstance::ParseValue(p_szIn, &p_szIn,prop->eType,&v);
|
||||
p_pcOut->avList.push_back(v);
|
||||
}
|
||||
SkipSpacesAndLineEnd(p_szIn, &p_szIn);
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -950,16 +861,11 @@ bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char**
|
||||
ai_assert(NULL != prop);
|
||||
ai_assert(NULL != p_pcOut);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
if (prop->bIsList)
|
||||
{
|
||||
// parse the number of elements in the list
|
||||
PLY::PropertyInstance::ValueUnion v;
|
||||
const char* szPass = szMax;
|
||||
PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eFirstType,&v,p_bBE);
|
||||
p_szIn = szPass;
|
||||
PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eFirstType,&v,p_bBE);
|
||||
|
||||
// convert to unsigned int
|
||||
unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType);
|
||||
@@ -967,9 +873,7 @@ bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char**
|
||||
// parse all list elements
|
||||
for (unsigned int i = 0; i < iNum;++i)
|
||||
{
|
||||
const char* szPass = szMax;
|
||||
PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eType,&v,p_bBE);
|
||||
p_szIn = szPass;
|
||||
PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eType,&v,p_bBE);
|
||||
p_pcOut->avList.push_back(v);
|
||||
}
|
||||
}
|
||||
@@ -977,12 +881,9 @@ bool PLY::PropertyInstance::ParseInstanceBinary (const char* p_szIn,const char**
|
||||
{
|
||||
// parse the property
|
||||
PLY::PropertyInstance::ValueUnion v;
|
||||
const char* szPass = szMax;
|
||||
PLY::PropertyInstance::ParseValueBinary(p_szIn, &szPass,prop->eType,&v,p_bBE);
|
||||
p_szIn = szPass;
|
||||
PLY::PropertyInstance::ParseValueBinary(p_szIn, &p_szIn,prop->eType,&v,p_bBE);
|
||||
p_pcOut->avList.push_back(v);
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -1013,9 +914,6 @@ bool PLY::PropertyInstance::ParseValue(const char* p_szIn,const char** p_szOut,
|
||||
ai_assert(NULL != p_szOut);
|
||||
ai_assert(NULL != out);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
switch (eType)
|
||||
{
|
||||
case EDT_UInt:
|
||||
@@ -1060,9 +958,9 @@ bool PLY::PropertyInstance::ParseValue(const char* p_szIn,const char** p_szOut,
|
||||
out->fDouble = (double)f;
|
||||
|
||||
default:
|
||||
*p_szOut = p_szIn;
|
||||
return false;
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
@@ -1078,9 +976,6 @@ bool PLY::PropertyInstance::ParseValueBinary(
|
||||
ai_assert(NULL != p_szOut);
|
||||
ai_assert(NULL != out);
|
||||
|
||||
const char* szMax = *p_szOut;
|
||||
*p_szOut = p_szIn;
|
||||
|
||||
switch (eType)
|
||||
{
|
||||
case EDT_UInt:
|
||||
@@ -1163,9 +1058,9 @@ bool PLY::PropertyInstance::ParseValueBinary(
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*p_szOut = p_szIn;
|
||||
return false;
|
||||
}
|
||||
ValidateOut(p_szIn,szMax);
|
||||
*p_szOut = p_szIn;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -481,9 +481,9 @@ public:
|
||||
|
||||
//! Parse the DOM for a PLY file. The input string is assumed
|
||||
//! to be terminated with zero
|
||||
static bool ParseInstance (const char* p_szIn,DOM* p_pcOut, unsigned int iLen);
|
||||
static bool ParseInstance (const char* p_szIn,DOM* p_pcOut);
|
||||
static bool ParseInstanceBinary (const char* p_szIn,
|
||||
DOM* p_pcOut,bool p_bBE, unsigned int iLen);
|
||||
DOM* p_pcOut,bool p_bBE);
|
||||
|
||||
//! Skip all comment lines after this
|
||||
static bool SkipComments (const char* p_szIn,const char** p_szOut);
|
||||
|
||||
112
code/RemoveComments.cpp
Normal file
112
code/RemoveComments.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
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 Defines a helper class, "CommentRemover", which can be
|
||||
* used to remove comments (single and multi line) from a text file.
|
||||
*/
|
||||
#include "../include/aiTypes.h"
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/aiAssert.h"
|
||||
|
||||
#include "RemoveComments.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CommentRemover::RemoveLineComments(const char* szComment,
|
||||
char* szBuffer, char chReplacement /* = ' ' */)
|
||||
{
|
||||
// validate parameters
|
||||
ai_assert(NULL != szComment && NULL != szBuffer && *szComment);
|
||||
|
||||
while (*szBuffer)
|
||||
{
|
||||
if (*szBuffer == *szComment)
|
||||
{
|
||||
if (0 == ::strcmp(szBuffer+1,szComment+1))
|
||||
{
|
||||
while (*szBuffer != '\r' && *szBuffer != '\n' && *szBuffer)
|
||||
*szBuffer++ = chReplacement;
|
||||
}
|
||||
}
|
||||
++szBuffer;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CommentRemover::RemoveMultiLineComments(const char* szCommentStart,
|
||||
const char* szCommentEnd,char* szBuffer,
|
||||
char chReplacement)
|
||||
{
|
||||
// validate parameters
|
||||
ai_assert(NULL != szCommentStart && NULL != szCommentEnd &&
|
||||
NULL != szBuffer && '\0' != *szCommentStart && '\0' != *szCommentEnd);
|
||||
|
||||
const size_t len = ::strlen(szCommentEnd);
|
||||
|
||||
while (*szBuffer)
|
||||
{
|
||||
if (*szBuffer == *szCommentStart)
|
||||
{
|
||||
if (0 == ::strcmp(szBuffer+1,szCommentStart+1))
|
||||
{
|
||||
while (*szBuffer)
|
||||
{
|
||||
if (*szBuffer == *szCommentEnd)
|
||||
{
|
||||
if (0 == ::strcmp(szBuffer+1,szCommentEnd+1))
|
||||
{
|
||||
for (unsigned int i = 0; i < len;++i)
|
||||
*szBuffer++ = chReplacement;
|
||||
goto __continue_outer; // WUHHHAAAAHHAA!
|
||||
}
|
||||
}
|
||||
*szBuffer++ = chReplacement;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
++szBuffer;
|
||||
__continue_outer:
|
||||
int i = 4; // NOP dummy
|
||||
}
|
||||
}
|
||||
|
||||
}; // !! Assimp
|
||||
89
code/RemoveComments.h
Normal file
89
code/RemoveComments.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
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 Declares a helper class, "CommentRemover", which can be
|
||||
* used to remove comments (single and multi line) from a text file.
|
||||
*/
|
||||
#ifndef AI_REMOVE_COMMENTS_H_INC
|
||||
#define AI_REMOVE_COMMENTS_H_INC
|
||||
|
||||
#include "../include/aiAssert.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** \brief Helper class to remove single and multi line comments from a file
|
||||
*
|
||||
* Some mesh formats like MD5 have comments that are quite similar
|
||||
* to those in C or C++ so this code has been moved to a separate
|
||||
* module.
|
||||
*/
|
||||
class CommentRemover
|
||||
{
|
||||
// class cannot be instanced
|
||||
CommentRemover() {}
|
||||
|
||||
public:
|
||||
|
||||
//! Remove single-line comments. The end of a line is
|
||||
//! expected to be either NL or CR or NLCR.
|
||||
//! \param szComment The start sequence of the comment, e.g. "//"
|
||||
//! \param szBuffer Buffer to work with
|
||||
//! \param chReplacement Character to be used as replacement
|
||||
//! for commented lines. By default this is ' '
|
||||
static void RemoveLineComments(const char* szComment,
|
||||
char* szBuffer, char chReplacement = ' ');
|
||||
|
||||
//! Remove multi-line comments. The end of a line is
|
||||
//! expected to be either NL or CR or NLCR. Multi-line comments
|
||||
//! may not be nested (as in C).
|
||||
//! \param szCommentStart The start sequence of the comment, e.g. "/*"
|
||||
//! \param szCommentEnd The end sequence of the comment, e.g. "*/"
|
||||
//! \param szBuffer Buffer to work with
|
||||
//! \param chReplacement Character to be used as replacement
|
||||
//! for commented lines. By default this is ' '
|
||||
static void RemoveMultiLineComments(const char* szCommentStart,
|
||||
const char* szCommentEnd,char* szBuffer,
|
||||
char chReplacement = ' ');
|
||||
};
|
||||
} // ! Assimp
|
||||
|
||||
#endif // !! AI_REMOVE_COMMENTS_H_INC
|
||||
@@ -41,11 +41,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/** @file Implementation of the SMD importer class */
|
||||
|
||||
// internal headers
|
||||
#include "MaterialSystem.h"
|
||||
#include "SMDLoader.h"
|
||||
#include "StringComparison.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
// public headers
|
||||
#include "../include/DefaultLogger.h"
|
||||
#include "../include/IOStream.h"
|
||||
#include "../include/IOSystem.h"
|
||||
@@ -53,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../include/aiScene.h"
|
||||
#include "../include/aiAssert.h"
|
||||
|
||||
// boost headers
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
using namespace Assimp;
|
||||
@@ -105,7 +108,7 @@ bool SMDImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
||||
void SMDImporter::InternReadFile(
|
||||
const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
|
||||
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rt"));
|
||||
|
||||
// Check whether we can read from the file
|
||||
if( file.get() == NULL)
|
||||
@@ -123,6 +126,9 @@ void SMDImporter::InternReadFile(
|
||||
this->bHasUVs = true;
|
||||
this->iLineNumber = 1;
|
||||
|
||||
// append a terminal 0
|
||||
this->mBuffer[this->iFileSize] = '\0';
|
||||
|
||||
// reserve enough space for ... hm ... 10 textures
|
||||
this->aszTextures.reserve(10);
|
||||
|
||||
@@ -137,14 +143,48 @@ void SMDImporter::InternReadFile(
|
||||
// parse the file ...
|
||||
this->ParseFile();
|
||||
|
||||
// now fix invalid time values and make sure the animation starts at frame 0
|
||||
this->FixTimeValues();
|
||||
// if there are no triangles it seems to be an animation SMD,
|
||||
// containing only the animation skeleton.
|
||||
if (this->asTriangles.empty())
|
||||
{
|
||||
if (this->asBones.empty())
|
||||
{
|
||||
throw new ImportErrorException("No triangles and no bones have "
|
||||
"been found in the file. This file seems to be invalid.");
|
||||
}
|
||||
// set the flag in the scene structure which indicates
|
||||
// that there is nothing than an animation skeleton
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_ANIM_SKELETON_ONLY;
|
||||
}
|
||||
|
||||
if (!this->asBones.empty())
|
||||
{
|
||||
// check whether all bones have been initialized
|
||||
for (std::vector<SMD::Bone>::const_iterator
|
||||
i = this->asBones.begin();
|
||||
i != this->asBones.end();++i)
|
||||
{
|
||||
if (!(*i).mName.length())
|
||||
{
|
||||
DefaultLogger::get()->warn("Not all bones have been initialized");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// compute absolute bone transformation matrices
|
||||
this->ComputeAbsoluteBoneTransformations();
|
||||
// now fix invalid time values and make sure the animation starts at frame 0
|
||||
this->FixTimeValues();
|
||||
|
||||
// create output meshes
|
||||
this->CreateOutputMeshes();
|
||||
// compute absolute bone transformation matrices
|
||||
this->ComputeAbsoluteBoneTransformations();
|
||||
}
|
||||
if (!(pScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY))
|
||||
{
|
||||
// create output meshes
|
||||
this->CreateOutputMeshes();
|
||||
|
||||
// build an output material list
|
||||
this->CreateOutputMaterials();
|
||||
}
|
||||
|
||||
// build the output animation
|
||||
this->CreateOutputAnimations();
|
||||
@@ -292,7 +332,7 @@ void SMDImporter::CreateOutputMeshes()
|
||||
|
||||
*pcVerts++ = face.avVertices[0].pos;
|
||||
*pcVerts++ = face.avVertices[1].pos;
|
||||
*pcVerts++ = face.avVertices[2].pos;
|
||||
*pcVerts++ = face.avVertices[2].pos;
|
||||
|
||||
// fill the normals
|
||||
*pcNormals++ = face.avVertices[0].nor;
|
||||
@@ -310,10 +350,9 @@ void SMDImporter::CreateOutputMeshes()
|
||||
for (unsigned int iVert = 0; iVert < 3;++iVert)
|
||||
{
|
||||
float fSum = 0.0f;
|
||||
for (unsigned int iBone = 0;iBone < face.avVertices[0].aiBoneLinks.size();++iBone)
|
||||
for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone)
|
||||
{
|
||||
TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone];
|
||||
|
||||
if (pairval.first >= this->asBones.size())
|
||||
{
|
||||
DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. "
|
||||
@@ -322,16 +361,35 @@ void SMDImporter::CreateOutputMeshes()
|
||||
continue;
|
||||
}
|
||||
aaiBones[pairval.first].push_back(TempWeightListEntry(iNum,pairval.second));
|
||||
|
||||
fSum += pairval.second;
|
||||
}
|
||||
// if the sum of all vertex weights is not 1.0 we must assign
|
||||
// the rest to the vertex' parent node. Well, at least the doc says
|
||||
// we should ...
|
||||
if (fSum <= 0.995f)
|
||||
if (fSum <= 1.0f)
|
||||
{
|
||||
aaiBones[face.avVertices[iVert].iParentNode].push_back(
|
||||
TempWeightListEntry(iNum,1.0f-fSum));
|
||||
if (face.avVertices[iVert].iParentNode >= this->asBones.size())
|
||||
{
|
||||
DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. "
|
||||
"The index of the vertex parent bone is invalid. "
|
||||
"The remaining weights will be normalized to 1.0");
|
||||
|
||||
if (fSum)
|
||||
{
|
||||
fSum = 1 / fSum;
|
||||
for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone)
|
||||
{
|
||||
TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone];
|
||||
if (pairval.first >= this->asBones.size())continue;
|
||||
aaiBones[pairval.first].back().second *= fSum;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aaiBones[face.avVertices[iVert].iParentNode].push_back(
|
||||
TempWeightListEntry(iNum,1.0f-fSum));
|
||||
}
|
||||
}
|
||||
|
||||
pcMesh->mFaces[iFace].mIndices[iVert] = iNum++;
|
||||
@@ -375,7 +433,7 @@ void SMDImporter::CreateOutputMeshes()
|
||||
// add bone child nodes
|
||||
void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent)
|
||||
{
|
||||
ai_assert(NULL != pcNode && 0 != pcNode->mNumChildren && NULL != pcNode->mChildren);
|
||||
ai_assert(NULL != pcNode && 0 == pcNode->mNumChildren && NULL == pcNode->mChildren);
|
||||
|
||||
// first count ...
|
||||
for (unsigned int i = 0; i < this->asBones.size();++i)
|
||||
@@ -399,42 +457,72 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent)
|
||||
|
||||
// store the local transformation matrix of the bind pose
|
||||
pc->mTransformation = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrix;
|
||||
pc->mParent = pcNode;
|
||||
|
||||
// add children to this node, too
|
||||
AddBoneChildren(pc,i);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// create output nodes
|
||||
void SMDImporter::CreateOutputNodes()
|
||||
{
|
||||
// create one root node that renders all meshes
|
||||
this->pScene->mRootNode = new aiNode();
|
||||
::strcpy(this->pScene->mRootNode->mName.data, "SMD_root");
|
||||
this->pScene->mRootNode->mName.length = 8;
|
||||
this->pScene->mRootNode->mNumMeshes = this->pScene->mNumMeshes;
|
||||
this->pScene->mRootNode->mMeshes = new unsigned int[this->pScene->mNumMeshes];
|
||||
for (unsigned int i = 0; i < this->pScene->mNumMeshes;++i)
|
||||
this->pScene->mRootNode->mMeshes[i] = i;
|
||||
if (!(this->pScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY))
|
||||
{
|
||||
// create one root node that renders all meshes
|
||||
this->pScene->mRootNode->mNumMeshes = this->pScene->mNumMeshes;
|
||||
this->pScene->mRootNode->mMeshes = new unsigned int[this->pScene->mNumMeshes];
|
||||
for (unsigned int i = 0; i < this->pScene->mNumMeshes;++i)
|
||||
this->pScene->mRootNode->mMeshes[i] = i;
|
||||
}
|
||||
|
||||
// now add all bones as dummy sub nodes to the graph
|
||||
this->AddBoneChildren(this->pScene->mRootNode,(uint32_t)-1);
|
||||
|
||||
// if we have only one bone we can even remove the root node
|
||||
if (this->pScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY &&
|
||||
1 == this->pScene->mRootNode->mNumChildren)
|
||||
{
|
||||
aiNode* pcOldRoot = this->pScene->mRootNode;
|
||||
this->pScene->mRootNode = pcOldRoot->mChildren[0];
|
||||
pcOldRoot->mChildren[0] = NULL;
|
||||
delete pcOldRoot;
|
||||
|
||||
this->pScene->mRootNode->mParent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
::strcpy(this->pScene->mRootNode->mName.data, "<SMD_root>");
|
||||
this->pScene->mRootNode->mName.length = 10;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// create output animations
|
||||
void SMDImporter::CreateOutputAnimations()
|
||||
{
|
||||
unsigned int iNumBones = 0;
|
||||
for (std::vector<SMD::Bone>::const_iterator
|
||||
i = this->asBones.begin();
|
||||
i != this->asBones.end();++i)
|
||||
{
|
||||
if ((*i).bIsUsed)++iNumBones;
|
||||
}
|
||||
if (!iNumBones)
|
||||
{
|
||||
// just make sure this case doesn't occur ... (it could occur
|
||||
// if the file was invalid)
|
||||
return;
|
||||
}
|
||||
|
||||
this->pScene->mNumAnimations = 1;
|
||||
this->pScene->mAnimations = new aiAnimation*[1];
|
||||
aiAnimation*& anim = this->pScene->mAnimations[0] = new aiAnimation();
|
||||
|
||||
anim->mDuration = this->dLengthOfAnim;
|
||||
anim->mNumBones = iNumBones;
|
||||
anim->mTicksPerSecond = 25.0; // FIXME: is this correct?
|
||||
|
||||
// this->pScene->mAnimations[0]->mNumBones = 0;
|
||||
for (std::vector<SMD::Bone>::const_iterator
|
||||
i = this->asBones.begin();
|
||||
i != this->asBones.end();++i)
|
||||
{
|
||||
if ((*i).bIsUsed)++anim->mNumBones;
|
||||
}
|
||||
aiBoneAnim** pp = anim->mBones = new aiBoneAnim*[anim->mNumBones];
|
||||
|
||||
// now build valid keys
|
||||
@@ -492,8 +580,10 @@ void SMDImporter::ComputeAbsoluteBoneTransformations()
|
||||
for (unsigned int i = 0; i < bone.sAnim.asKeys.size();++i)
|
||||
{
|
||||
double d = std::min(bone.sAnim.asKeys[i].dTime,dMin);
|
||||
if (d < dMin) {
|
||||
dMin = d; iIndex = i;
|
||||
if (d < dMin)
|
||||
{
|
||||
dMin = d;
|
||||
iIndex = i;
|
||||
}
|
||||
}
|
||||
bone.sAnim.iFirstTimeKey = iIndex;
|
||||
@@ -541,7 +631,7 @@ void SMDImporter::ComputeAbsoluteBoneTransformations()
|
||||
void SMDImporter::CreateOutputMaterials()
|
||||
{
|
||||
this->pScene->mNumMaterials = (unsigned int)this->aszTextures.size();
|
||||
this->pScene->mMaterials = new aiMaterial*[std::min(1u, this->pScene->mNumMaterials)];
|
||||
this->pScene->mMaterials = new aiMaterial*[std::max(1u, this->pScene->mNumMaterials)];
|
||||
|
||||
for (unsigned int iMat = 0; iMat < this->pScene->mNumMaterials;++iMat)
|
||||
{
|
||||
@@ -556,7 +646,7 @@ void SMDImporter::CreateOutputMaterials()
|
||||
#endif
|
||||
pcMat->AddProperty(&szName,AI_MATKEY_NAME);
|
||||
|
||||
strcpy(szName.data, this->aszTextures[iMat].c_str() );
|
||||
::strcpy(szName.data, this->aszTextures[iMat].c_str() );
|
||||
szName.length = this->aszTextures[iMat].length();
|
||||
pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
}
|
||||
@@ -594,7 +684,7 @@ void SMDImporter::ParseFile()
|
||||
// read line per line ...
|
||||
while (true)
|
||||
{
|
||||
if(!SkipSpaces(szCurrent,&szCurrent)) break;
|
||||
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
|
||||
|
||||
// "version <n> \n", <n> should be 1 for hl and hl² SMD files
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"version",7) &&
|
||||
@@ -607,55 +697,43 @@ void SMDImporter::ParseFile()
|
||||
DefaultLogger::get()->warn("SMD.version is not 1. This "
|
||||
"file format is not known. Continuing happily ...");
|
||||
}
|
||||
//continue;
|
||||
}
|
||||
// "nodes\n" - Starts the node section
|
||||
else if (0 == ASSIMP_strincmp(szCurrent,"nodes",5) &&
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"nodes",5) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+5)))
|
||||
{
|
||||
szCurrent += 6;
|
||||
this->ParseNodesSection(szCurrent,&szCurrent);
|
||||
//continue;
|
||||
}
|
||||
// "triangles\n" - Starts the triangle section
|
||||
else if (0 == ASSIMP_strincmp(szCurrent,"triangles",9) &&
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"triangles",9) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+9)))
|
||||
{
|
||||
szCurrent += 10;
|
||||
this->ParseTrianglesSection(szCurrent,&szCurrent);
|
||||
//continue;
|
||||
}
|
||||
// "vertexanimation\n" - Starts the vertex animation section
|
||||
else if (0 == ASSIMP_strincmp(szCurrent,"vertexanimation",15) &&
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"vertexanimation",15) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+15)))
|
||||
{
|
||||
this->bHasUVs = false;
|
||||
szCurrent += 16;
|
||||
this->ParseVASection(szCurrent,&szCurrent);
|
||||
//continue;
|
||||
}
|
||||
// "skeleton\n" - Starts the skeleton section
|
||||
else if (0 == ASSIMP_strincmp(szCurrent,"skeleton",8) &&
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"skeleton",8) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+8)))
|
||||
{
|
||||
szCurrent += 9;
|
||||
this->ParseSkeletonSection(szCurrent,&szCurrent);
|
||||
//continue;
|
||||
}
|
||||
else SkipLine(szCurrent,&szCurrent);
|
||||
}
|
||||
|
||||
// if there are no triangles, we can't load the model
|
||||
if (this->asTriangles.empty())
|
||||
{
|
||||
throw new ImportErrorException("No triangles have been found in the file");
|
||||
}
|
||||
// check whether all bones have been initialized
|
||||
for (std::vector<SMD::Bone>::const_iterator
|
||||
i = this->asBones.begin();
|
||||
i != this->asBones.end();++i)
|
||||
{
|
||||
if (!(*i).mName.length())
|
||||
{
|
||||
DefaultLogger::get()->warn("Not all bones have been initialized");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@@ -701,6 +779,8 @@ void SMDImporter::ParseTrianglesSection(const char* szCurrent,
|
||||
// and so on until we reach a token that looks quite similar to "end"
|
||||
while (true)
|
||||
{
|
||||
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
|
||||
|
||||
// "end\n" - Ends the triangles section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"end",3) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+3)))
|
||||
@@ -721,6 +801,8 @@ void SMDImporter::ParseVASection(const char* szCurrent,
|
||||
unsigned int iCurIndex = 0;
|
||||
while (true)
|
||||
{
|
||||
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
|
||||
|
||||
// "end\n" - Ends the "vertexanimation" section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"end",3) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+3)))
|
||||
@@ -730,7 +812,7 @@ void SMDImporter::ParseVASection(const char* szCurrent,
|
||||
break;
|
||||
}
|
||||
// "time <n>\n"
|
||||
else if (0 == ASSIMP_strincmp(szCurrent,"time",4) &&
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"time",4) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+4)))
|
||||
{
|
||||
szCurrent += 5;
|
||||
@@ -767,6 +849,8 @@ void SMDImporter::ParseSkeletonSection(const char* szCurrent,
|
||||
int iTime = 0;
|
||||
while (true)
|
||||
{
|
||||
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
|
||||
|
||||
// "end\n" - Ends the skeleton section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"end",3) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+3)))
|
||||
@@ -796,6 +880,7 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent,
|
||||
const char** szCurrentOut)
|
||||
{
|
||||
unsigned int iBone = 0;
|
||||
SkipSpacesAndLineEnd(szCurrent,&szCurrent);
|
||||
if(!this->ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent))
|
||||
{
|
||||
this->LogErrorNoThrow("Unexpected EOF/EOL while parsing bone index");
|
||||
@@ -836,6 +921,8 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent,
|
||||
++szEnd;
|
||||
}
|
||||
bone.mName = std::string(szCurrent,iBone);
|
||||
szCurrent = szEnd;
|
||||
|
||||
// the only negative bone parent index that could occur is -1 AFAIK
|
||||
if(!this->ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent))
|
||||
{
|
||||
@@ -933,11 +1020,13 @@ void SMDImporter::ParseTriangle(const char* szCurrent,
|
||||
}
|
||||
|
||||
// read the texture file name
|
||||
const char* szEnd = szCurrent;
|
||||
while (!IsSpaceOrNewLine(*szEnd++));
|
||||
const char* szLast = szCurrent;
|
||||
while (!IsSpaceOrNewLine(*szCurrent++));
|
||||
|
||||
face.iTexture = this->GetTextureIndex(std::string(szCurrent,
|
||||
(uintptr_t)szEnd-(uintptr_t)szCurrent));
|
||||
face.iTexture = this->GetTextureIndex(std::string(szLast,
|
||||
(uintptr_t)szCurrent-(uintptr_t)szLast));
|
||||
|
||||
this->SkipLine(szCurrent,&szCurrent);
|
||||
|
||||
// load three vertices
|
||||
for (unsigned int iVert = 0; iVert < 3;++iVert)
|
||||
@@ -945,6 +1034,7 @@ void SMDImporter::ParseTriangle(const char* szCurrent,
|
||||
this->ParseVertex(szCurrent,&szCurrent,
|
||||
face.avVertices[iVert]);
|
||||
}
|
||||
*szCurrentOut = szCurrent;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse a float
|
||||
|
||||
@@ -355,16 +355,16 @@ protected:
|
||||
return true;
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
inline void SkipSpacesAndLineEnd( const char* in, const char** out)
|
||||
inline bool SkipSpacesAndLineEnd( const char* in, const char** out)
|
||||
{
|
||||
::SkipSpacesAndLineEnd(in,out);
|
||||
++iLineNumber;
|
||||
return ::SkipSpacesAndLineEnd(in,out);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** Buffer to hold the loaded file */
|
||||
const char* mBuffer;
|
||||
char* mBuffer;
|
||||
|
||||
/** Output scene to be filled
|
||||
*/
|
||||
|
||||
@@ -155,7 +155,10 @@ void ValidateDSProcess::Execute( aiScene* pScene)
|
||||
this->Validate(pScene->mMeshes[i]);
|
||||
}
|
||||
}
|
||||
else this->ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
|
||||
else if (!(this->mScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY))
|
||||
{
|
||||
this->ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there");
|
||||
}
|
||||
|
||||
// validate all animations
|
||||
if (pScene->mNumAnimations)
|
||||
@@ -185,6 +188,11 @@ void ValidateDSProcess::Execute( aiScene* pScene)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this->mScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY)
|
||||
{
|
||||
this->ReportError("aiScene::mNumAnimations is 0 and the "
|
||||
"AI_SCENE_FLAGS_ANIM_SKELETON_ONLY flag is set.");
|
||||
}
|
||||
|
||||
// validate all textures
|
||||
if (pScene->mNumTextures)
|
||||
@@ -240,71 +248,83 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||
pMesh->mMaterialIndex,this->mScene->mNumMaterials-1);
|
||||
}
|
||||
|
||||
// positions must always be there ...
|
||||
if (!pMesh->mNumVertices || !pMesh->mVertices)
|
||||
if (this->mScene->mFlags & AI_SCENE_FLAGS_ANIM_SKELETON_ONLY)
|
||||
{
|
||||
this->ReportError("The mesh contains no vertices");
|
||||
}
|
||||
|
||||
// faces, too
|
||||
if (!pMesh->mNumFaces || !pMesh->mFaces)
|
||||
{
|
||||
this->ReportError("The mesh contains no faces");
|
||||
}
|
||||
|
||||
// now check whether the face indexing layout is correct:
|
||||
// unique vertices, pseudo-indexed.
|
||||
std::vector<bool> abRefList;
|
||||
abRefList.resize(pMesh->mNumVertices,false);
|
||||
for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
|
||||
{
|
||||
aiFace& face = pMesh->mFaces[i];
|
||||
if (!face.mIndices)this->ReportError("aiMesh::mFaces[%i].mIndices is NULL",i);
|
||||
if (face.mNumIndices < 3)this->ReportError(
|
||||
"aiMesh::mFaces[%i].mIndices is not a triangle or polygon",i);
|
||||
|
||||
for (unsigned int a = 0; a < face.mNumIndices;++a)
|
||||
if (pMesh->mNumVertices || pMesh->mVertices ||
|
||||
pMesh->mNumFaces || pMesh->mFaces)
|
||||
{
|
||||
if (face.mIndices[a] >= pMesh->mNumVertices)
|
||||
{
|
||||
this->ReportError("aiMesh::mFaces[%i]::mIndices[%a] is out of range",i,a);
|
||||
}
|
||||
if (abRefList[face.mIndices[a]])
|
||||
{
|
||||
this->ReportError("aiMesh::mVertices[%i] is referenced twice - second "
|
||||
"time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
|
||||
}
|
||||
abRefList[face.mIndices[a]] = true;
|
||||
this->ReportWarning("The mesh contains vertices and faces although "
|
||||
"the AI_SCENE_FLAGS_ANIM_SKELETON_ONLY flag is set");
|
||||
}
|
||||
}
|
||||
abRefList.clear();
|
||||
|
||||
// texture channel 2 may not be set if channel 1 is zero ...
|
||||
else
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
{
|
||||
if (!pMesh->HasTextureCoords(i))break;
|
||||
}
|
||||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
if (pMesh->HasTextureCoords(i))
|
||||
// positions must always be there ...
|
||||
if (!pMesh->mNumVertices || !pMesh->mVertices)
|
||||
{
|
||||
this->ReportError("Texture coordinate channel %i is existing, "
|
||||
"although the previous channel was NULL.",i);
|
||||
this->ReportError("The mesh contains no vertices");
|
||||
}
|
||||
}
|
||||
// the same for the vertex colors
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||
{
|
||||
if (!pMesh->HasVertexColors(i))break;
|
||||
}
|
||||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||
if (pMesh->HasVertexColors(i))
|
||||
|
||||
// faces, too
|
||||
if (!pMesh->mNumFaces || !pMesh->mFaces)
|
||||
{
|
||||
this->ReportError("Vertex color channel %i is existing, "
|
||||
"although the previous channel was NULL.",i);
|
||||
this->ReportError("The mesh contains no faces");
|
||||
}
|
||||
|
||||
// now check whether the face indexing layout is correct:
|
||||
// unique vertices, pseudo-indexed.
|
||||
std::vector<bool> abRefList;
|
||||
abRefList.resize(pMesh->mNumVertices,false);
|
||||
for (unsigned int i = 0; i < pMesh->mNumFaces;++i)
|
||||
{
|
||||
aiFace& face = pMesh->mFaces[i];
|
||||
if (!face.mIndices)this->ReportError("aiMesh::mFaces[%i].mIndices is NULL",i);
|
||||
if (face.mNumIndices < 3)this->ReportError(
|
||||
"aiMesh::mFaces[%i].mIndices is not a triangle or polygon",i);
|
||||
|
||||
for (unsigned int a = 0; a < face.mNumIndices;++a)
|
||||
{
|
||||
if (face.mIndices[a] >= pMesh->mNumVertices)
|
||||
{
|
||||
this->ReportError("aiMesh::mFaces[%i]::mIndices[%a] is out of range",i,a);
|
||||
}
|
||||
if (abRefList[face.mIndices[a]])
|
||||
{
|
||||
this->ReportError("aiMesh::mVertices[%i] is referenced twice - second "
|
||||
"time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
|
||||
}
|
||||
abRefList[face.mIndices[a]] = true;
|
||||
}
|
||||
}
|
||||
abRefList.clear();
|
||||
|
||||
// texture channel 2 may not be set if channel 1 is zero ...
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
{
|
||||
if (!pMesh->HasTextureCoords(i))break;
|
||||
}
|
||||
for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
|
||||
if (pMesh->HasTextureCoords(i))
|
||||
{
|
||||
this->ReportError("Texture coordinate channel %i is existing, "
|
||||
"although the previous channel was NULL.",i);
|
||||
}
|
||||
}
|
||||
// the same for the vertex colors
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||
{
|
||||
if (!pMesh->HasVertexColors(i))break;
|
||||
}
|
||||
for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i)
|
||||
if (pMesh->HasVertexColors(i))
|
||||
{
|
||||
this->ReportError("Vertex color channel %i is existing, "
|
||||
"although the previous channel was NULL.",i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,6 +336,13 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||
this->ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)",
|
||||
pMesh->mNumBones);
|
||||
}
|
||||
float* afSum = NULL;
|
||||
if (pMesh->mNumVertices)
|
||||
{
|
||||
afSum = new float[pMesh->mNumVertices];
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
||||
afSum[i] = 0.0f;
|
||||
}
|
||||
|
||||
// check whether there are duplicate bone names
|
||||
for (unsigned int i = 0; i < pMesh->mNumBones;++i)
|
||||
@@ -325,7 +352,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||
this->ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)",
|
||||
i,pMesh->mNumBones);
|
||||
}
|
||||
this->Validate(pMesh,pMesh->mBones[i]);
|
||||
this->Validate(pMesh,pMesh->mBones[i],afSum);
|
||||
|
||||
for (unsigned int a = i+1; a < pMesh->mNumBones;++a)
|
||||
{
|
||||
@@ -336,11 +363,22 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
||||
}
|
||||
}
|
||||
}
|
||||
// check whether all bone weights for a vertex sum to 1.0 ...
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
||||
{
|
||||
if (afSum[i] && (afSum[i] <= 0.995 || afSum[i] >= 1.005))
|
||||
{
|
||||
delete[] afSum;
|
||||
this->ReportError("aiMesh::mVertices[%i]: The sum of all bone "
|
||||
"weights isn't 1.0f (sum is %f)",i,afSum[i]);
|
||||
}
|
||||
}
|
||||
delete[] afSum;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiMesh* pMesh,
|
||||
const aiBone* pBone)
|
||||
const aiBone* pBone,float* afSum)
|
||||
{
|
||||
this->Validate(&pBone->mName);
|
||||
|
||||
@@ -355,8 +393,8 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh,
|
||||
{
|
||||
this->ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value",i);
|
||||
}
|
||||
afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight;
|
||||
}
|
||||
// TODO: check whether all bone weights for a vertex sum to 1.0 ...
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
|
||||
@@ -606,9 +644,10 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
|
||||
for (unsigned int a = 0; a < mesh->mNumBones;++a)
|
||||
{
|
||||
if (mesh->mBones[a]->mName == pBoneAnim->mBoneName)
|
||||
break;
|
||||
goto __break_out;
|
||||
}
|
||||
}
|
||||
__break_out:
|
||||
if (i == this->mScene->mNumMeshes)
|
||||
{
|
||||
this->ReportWarning("aiBoneAnim::mBoneName is %s. However, no bone with this name was found",
|
||||
|
||||
@@ -115,7 +115,7 @@ protected:
|
||||
* @param pMesh Input mesh
|
||||
* @param pBone Input bone
|
||||
*/
|
||||
void Validate( const aiMesh* pMesh,const aiBone* pBone);
|
||||
void Validate( const aiMesh* pMesh,const aiBone* pBone,float* afSum);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
/** Validates an animation
|
||||
|
||||
Reference in New Issue
Block a user