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:
aramis_acg
2008-07-10 16:49:01 +00:00
parent 600cd7a8f0
commit fc8a8b54f9
67 changed files with 8043 additions and 701 deletions

View File

@@ -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>");
}
}
// ------------------------------------------------------------------------------------------------

View File

@@ -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)

View File

@@ -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);
}
// ------------------------------------------------------------------------------------------------

View File

@@ -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

View 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,

View File

@@ -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;

View File

@@ -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>

View File

@@ -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)");

View File

@@ -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;
}

View File

@@ -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
View 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
View 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

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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",

View File

@@ -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