Changing 3DS parsing routines to work iteratively instead of recursively. This hopefully avoids unwanted stack overflowing with deeply-nested model hierarchies.

Updating revision number.

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@445 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
pull/1/head
aramis_acg 2009-06-23 12:25:35 +00:00
parent adb4ab602e
commit 2d994c514c
2 changed files with 45 additions and 74 deletions

View File

@ -58,13 +58,15 @@ using namespace Assimp;
// - Reads the current chunk and validates it // - Reads the current chunk and validates it
// - computes its length // - computes its length
#define ASSIMP_3DS_BEGIN_CHUNK() \ #define ASSIMP_3DS_BEGIN_CHUNK() \
if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)) \ while (true) { \
if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)){ \
return; \ return; \
} \
Discreet3DS::Chunk chunk; \ Discreet3DS::Chunk chunk; \
ReadChunk(&chunk); \ ReadChunk(&chunk); \
int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \ int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \
const int oldReadLimit = stream->GetReadLimit(); \ const int oldReadLimit = stream->GetReadLimit(); \
stream->SetReadLimit(stream->GetCurrentPos() + chunkSize); stream->SetReadLimit(stream->GetCurrentPos() + chunkSize); \
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -74,7 +76,8 @@ using namespace Assimp;
stream->SkipToReadLimit(); \ stream->SkipToReadLimit(); \
stream->SetReadLimit(oldReadLimit); \ stream->SetReadLimit(oldReadLimit); \
if (stream->GetRemainingSizeToLimit() == 0) \ if (stream->GetRemainingSizeToLimit() == 0) \
return; return; \
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
@ -284,8 +287,6 @@ void Discreet3DSImporter::ParseEditorChunk()
break; break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseEditorChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -348,8 +349,6 @@ void Discreet3DSImporter::ParseObjectChunk()
break; break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseObjectChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -443,18 +442,17 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
// Read the lense angle // Read the lense angle
camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() ); camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() );
if (camera->mHorizontalFOV < 0.001f) if (camera->mHorizontalFOV < 0.001f) {
camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f); camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f);
} }
// Now check for further subchunks // Now check for further subchunks
if (!bIsPrj) /* fixme */ if (!bIsPrj) /* fixme */ {
ParseCameraChunk(); ParseCameraChunk();
}}
break; break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseChunk(name,num);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -503,8 +501,6 @@ void Discreet3DSImporter::ParseLightChunk()
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseLightChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -524,8 +520,6 @@ void Discreet3DSImporter::ParseCameraChunk()
} }
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseCameraChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -549,9 +543,6 @@ void Discreet3DSImporter::ParseKeyframeChunk()
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseKeyframeChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -564,9 +555,9 @@ void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCur
} }
if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos) { if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos) {
if(pcCurrent->mParent) if(pcCurrent->mParent) {
pcCurrent->mParent->push_back(pcNode); pcCurrent->mParent->push_back(pcNode);
}
else pcCurrent->push_back(pcNode); else pcCurrent->push_back(pcNode);
return; return;
} }
@ -609,16 +600,21 @@ void Discreet3DSImporter::SkipTCBInfo()
DefaultLogger::get()->warn("3DS: Skipping TCB animation info"); DefaultLogger::get()->warn("3DS: Skipping TCB animation info");
} }
if (flags & Discreet3DS::KEY_USE_TENS) if (flags & Discreet3DS::KEY_USE_TENS) {
stream->IncPtr(4); stream->IncPtr(4);
if (flags & Discreet3DS::KEY_USE_BIAS) }
if (flags & Discreet3DS::KEY_USE_BIAS) {
stream->IncPtr(4); stream->IncPtr(4);
if (flags & Discreet3DS::KEY_USE_CONT) }
if (flags & Discreet3DS::KEY_USE_CONT) {
stream->IncPtr(4); stream->IncPtr(4);
if (flags & Discreet3DS::KEY_USE_EASE_FROM) }
if (flags & Discreet3DS::KEY_USE_EASE_FROM) {
stream->IncPtr(4); stream->IncPtr(4);
if (flags & Discreet3DS::KEY_USE_EASE_TO) }
if (flags & Discreet3DS::KEY_USE_EASE_TO) {
stream->IncPtr(4); stream->IncPtr(4);
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -664,20 +660,19 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
pcNode->mHierarchyIndex = mLastNodeIndex; pcNode->mHierarchyIndex = mLastNodeIndex;
// And find a proper position in the graph for it // And find a proper position in the graph for it
if (mCurrentNode && mCurrentNode->mHierarchyPos == hierarchy) if (mCurrentNode && mCurrentNode->mHierarchyPos == hierarchy) {
{
// add to the parent of the last touched node // add to the parent of the last touched node
mCurrentNode->mParent->push_back(pcNode); mCurrentNode->mParent->push_back(pcNode);
mLastNodeIndex++; mLastNodeIndex++;
} }
else if(hierarchy >= mLastNodeIndex) else if(hierarchy >= mLastNodeIndex) {
{
// place it at the current position in the hierarchy // place it at the current position in the hierarchy
mCurrentNode->push_back(pcNode); mCurrentNode->push_back(pcNode);
mLastNodeIndex = hierarchy; mLastNodeIndex = hierarchy;
} }
else else {
{
// need to go back to the specified position in the hierarchy. // need to go back to the specified position in the hierarchy.
InverseNodeSearch(pcNode,mCurrentNode); InverseNodeSearch(pcNode,mCurrentNode);
mLastNodeIndex++; mLastNodeIndex++;
@ -729,15 +724,13 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
// This could also be meant as the target position for // This could also be meant as the target position for
// (targeted) lights and cameras // (targeted) lights and cameras
std::vector<aiVectorKey>* l; std::vector<aiVectorKey>* l;
if ( Discreet3DS::CHUNK_TRACKCAMTGT == parent || Discreet3DS::CHUNK_TRACKLIGTGT == parent) if ( Discreet3DS::CHUNK_TRACKCAMTGT == parent || Discreet3DS::CHUNK_TRACKLIGTGT == parent) {
{
l = & mCurrentNode->aTargetPositionKeys; l = & mCurrentNode->aTargetPositionKeys;
} }
else l = & mCurrentNode->aPositionKeys; else l = & mCurrentNode->aPositionKeys;
l->reserve(numFrames); l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i) for (unsigned int i = 0; i < numFrames;++i) {
{
const unsigned int fidx = stream->GetI4(); const unsigned int fidx = stream->GetI4();
// Setup a new position key // Setup a new position key
@ -758,8 +751,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
} }
// Sort all keys with ascending time values and remove duplicates? // Sort all keys with ascending time values and remove duplicates?
if (sortKeys) if (sortKeys) {
{
std::stable_sort(l->begin(),l->end()); std::stable_sort(l->begin(),l->end());
l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() ); l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() );
}} }}
@ -771,8 +763,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
case Discreet3DS::CHUNK_TRACKROLL: case Discreet3DS::CHUNK_TRACKROLL:
{ {
// roll keys are accepted for cameras only // roll keys are accepted for cameras only
if (parent != Discreet3DS::CHUNK_TRACKCAMERA) if (parent != Discreet3DS::CHUNK_TRACKCAMERA) {
{
DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object"); DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object");
break; break;
} }
@ -782,8 +773,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
stream->IncPtr(10); stream->IncPtr(10);
const unsigned int numFrames = stream->GetI4(); const unsigned int numFrames = stream->GetI4();
l->reserve(numFrames); l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i) for (unsigned int i = 0; i < numFrames;++i) {
{
const unsigned int fidx = stream->GetI4(); const unsigned int fidx = stream->GetI4();
// Setup a new position key // Setup a new position key
@ -803,8 +793,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
} }
// Sort all keys with ascending time values and remove duplicates? // Sort all keys with ascending time values and remove duplicates?
if (sortKeys) if (sortKeys) {
{
std::stable_sort(l->begin(),l->end()); std::stable_sort(l->begin(),l->end());
l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiFloatKey>), l->end() ); l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiFloatKey>), l->end() );
}} }}
@ -832,8 +821,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys; std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys;
l->reserve(numFrames); l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i) for (unsigned int i = 0; i < numFrames;++i) {
{
const unsigned int fidx = stream->GetI4(); const unsigned int fidx = stream->GetI4();
SkipTCBInfo(); SkipTCBInfo();
@ -861,8 +849,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
l->push_back(v); l->push_back(v);
} }
// Sort all keys with ascending time values and remove duplicates? // Sort all keys with ascending time values and remove duplicates?
if (sortKeys) if (sortKeys) {
{
std::stable_sort(l->begin(),l->end()); std::stable_sort(l->begin(),l->end());
l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiQuatKey>), l->end() ); l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiQuatKey>), l->end() );
}} }}
@ -880,8 +867,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
std::vector<aiVectorKey>* l = &mCurrentNode->aScalingKeys; std::vector<aiVectorKey>* l = &mCurrentNode->aScalingKeys;
l->reserve(numFrames); l->reserve(numFrames);
for (unsigned int i = 0; i < numFrames;++i) for (unsigned int i = 0; i < numFrames;++i) {
{
const unsigned int fidx = stream->GetI4(); const unsigned int fidx = stream->GetI4();
SkipTCBInfo(); SkipTCBInfo();
@ -898,16 +884,15 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
if (!l->empty() && v.mTime <= l->back().mTime) if (!l->empty() && v.mTime <= l->back().mTime)
sortKeys = true; sortKeys = true;
// Remove zero-scalings // Remove zero-scalings on singular axes - they've been reported to be there erroneously in some strange files
if (!v.mValue.x)v.mValue.x = 1.f; if (!v.mValue.x) v.mValue.x = 1.f;
if (!v.mValue.y)v.mValue.y = 1.f; if (!v.mValue.y) v.mValue.y = 1.f;
if (!v.mValue.z)v.mValue.z = 1.f; if (!v.mValue.z) v.mValue.z = 1.f;
l->push_back(v); l->push_back(v);
} }
// Sort all keys with ascending time values and remove duplicates? // Sort all keys with ascending time values and remove duplicates?
if (sortKeys) if (sortKeys) {
{
std::stable_sort(l->begin(),l->end()); std::stable_sort(l->begin(),l->end());
l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() ); l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() );
}} }}
@ -915,8 +900,6 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseHierarchyChunk(parent);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -975,8 +958,6 @@ void Discreet3DSImporter::ParseFaceChunk()
break; break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseFaceChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1065,8 +1046,6 @@ void Discreet3DSImporter::ParseMeshChunk()
break; break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseMeshChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1225,8 +1204,6 @@ void Discreet3DSImporter::ParseMaterialChunk()
break; break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseMaterialChunk();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1311,8 +1288,6 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
// recursively continue processing this hierarchy level
return ParseTextureChunk(pcOut);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1353,8 +1328,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
bGamma = true; bGamma = true;
case Discreet3DS::CHUNK_RGBF: case Discreet3DS::CHUNK_RGBF:
if (sizeof(float) * 3 > diff) if (sizeof(float) * 3 > diff) {
{
*out = clrError; *out = clrError;
return; return;
} }
@ -1366,8 +1340,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
case Discreet3DS::CHUNK_LINRGBB: case Discreet3DS::CHUNK_LINRGBB:
bGamma = true; bGamma = true;
case Discreet3DS::CHUNK_RGBB: case Discreet3DS::CHUNK_RGBB:
if (sizeof(char) * 3 > diff) if (sizeof(char) * 3 > diff) {
{
*out = clrError; *out = clrError;
return; return;
} }
@ -1378,8 +1351,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
// Percentage chunks are accepted, too. // Percentage chunks are accepted, too.
case Discreet3DS::CHUNK_PERCENTF: case Discreet3DS::CHUNK_PERCENTF:
if (acceptPercent && 4 <= diff) if (acceptPercent && 4 <= diff) {
{
out->g = out->b = out->r = stream->GetF4(); out->g = out->b = out->r = stream->GetF4();
break; break;
} }
@ -1387,8 +1359,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
return; return;
case Discreet3DS::CHUNK_PERCENTW: case Discreet3DS::CHUNK_PERCENTW:
if (acceptPercent && 1 <= diff) if (acceptPercent && 1 <= diff) {
{
out->g = out->b = out->r = (float)(uint8_t)stream->GetI1() / 255.0f; out->g = out->b = out->r = (float)(uint8_t)stream->GetI1() / 255.0f;
break; break;
} }

View File

@ -1 +1 @@
#define SVNRevision 423 #define SVNRevision 433