From 9fc698bb2fe1a8f0caa04c22269a19c72aac7be0 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Wed, 26 Nov 2008 22:03:14 +0000 Subject: [PATCH] Fixed a bug in the validation step - animation channels weren't validated correctly in every case. Further work on LWO materials, writes wrap amount to UV transform property now. NFFLoader generates spherical UV coordinates now (for spheres and all platonic solids except hexahedrons) Importer doesn't catch exceptions in debug builds. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@252 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/3DSConverter.cpp | 60 ++++++++++++++++---------------- code/ComputeUVMappingProcess.cpp | 1 - code/ComputeUVMappingProcess.h | 2 +- code/Importer.cpp | 9 +++-- code/LWOMaterial.cpp | 10 +++++- code/NFFLoader.cpp | 16 +++++++++ code/NFFLoader.h | 6 ++++ code/TargetAnimation.cpp | 45 ++++++++++-------------- code/ValidateDataStructure.cpp | 12 +++---- 9 files changed, 93 insertions(+), 68 deletions(-) diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index f2333de7a..fdc80dc89 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -548,43 +548,43 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, } } - //if (pcIn->aTargetPositionKeys.size() > 1) - //{ - // DefaultLogger::get()->debug("3DS: Converting target track ..."); + if (pcIn->aTargetPositionKeys.size() > 1) + { + DefaultLogger::get()->debug("3DS: Converting target track ..."); - // // Camera or spot light - need to convert the separate - // // target position channel to our representation - // TargetAnimationHelper helper; + // Camera or spot light - need to convert the separate + // target position channel to our representation + TargetAnimationHelper helper; - // if (pcIn->aPositionKeys.empty()) - // { - // // We can just pass zero here ... - // helper.SetFixedMainAnimationChannel(aiVector3D()); - // } - // else helper.SetMainAnimationChannel(&pcIn->aPositionKeys); - // helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys); + if (pcIn->aPositionKeys.empty()) + { + // We can just pass zero here ... + helper.SetFixedMainAnimationChannel(aiVector3D()); + } + else helper.SetMainAnimationChannel(&pcIn->aPositionKeys); + helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys); - // // Do the conversion - // std::vector distanceTrack; - // helper.Process(&distanceTrack); + // Do the conversion + std::vector distanceTrack; + helper.Process(&distanceTrack); - // // Now add a new node as child, name it .Target - // // and assign the distance track to it. This is that the - // // information where the target is and how it moves is - // // not lost - // D3DS::Node* nd = new D3DS::Node(); - // pcIn->push_back(nd); + // Now add a new node as child, name it .Target + // and assign the distance track to it. This is that the + // information where the target is and how it moves is + // not lost + D3DS::Node* nd = new D3DS::Node(); + pcIn->push_back(nd); - // nd->mName = pcIn->mName + ".Target"; + nd->mName = pcIn->mName + ".Target"; - // aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); - // nda->mNodeName.Set(nd->mName); + aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); + nda->mNodeName.Set(nd->mName); - // nda->mNumPositionKeys = (unsigned int)distanceTrack.size(); - // nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys]; - // ::memcpy(nda->mPositionKeys,&distanceTrack[0], - // sizeof(aiVectorKey)*nda->mNumPositionKeys); - //} + nda->mNumPositionKeys = (unsigned int)distanceTrack.size(); + nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys]; + ::memcpy(nda->mPositionKeys,&distanceTrack[0], + sizeof(aiVectorKey)*nda->mNumPositionKeys); + } // Allocate a new nda, increment the nda index aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); diff --git a/code/ComputeUVMappingProcess.cpp b/code/ComputeUVMappingProcess.cpp index e179a85a5..4ad0a7add 100644 --- a/code/ComputeUVMappingProcess.cpp +++ b/code/ComputeUVMappingProcess.cpp @@ -334,7 +334,6 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,aiAxis axis, aiVe { DefaultLogger::get()->error("Can't compute plane mapping, the mesh is " "flat in the requested axis"); - return; } diff --git a/code/ComputeUVMappingProcess.h b/code/ComputeUVMappingProcess.h index bf5bf1c6e..36a77fa7c 100644 --- a/code/ComputeUVMappingProcess.h +++ b/code/ComputeUVMappingProcess.h @@ -129,7 +129,7 @@ private: { MappingInfo(aiTextureMapping _type) : type (_type) - , axis (aiAxis_X) + , axis (aiAxis_Y) , uv (0u) {} diff --git a/code/Importer.cpp b/code/Importer.cpp index 21cb2a441..18de76b1b 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -547,8 +547,10 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags // put a large try block around everything to catch all std::exception's // that might be thrown by STL containers or by new(). // ImportErrorException's are throw by ourselves and caught elsewhere. +#ifndef _DEBUG try { +#endif // check whether this Importer instance has already loaded // a scene. In this case we need to delete the old one if (this->mScene) @@ -648,11 +650,11 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags // clear any data allocated by post-process steps mPPShared->Clean(); - - } +#ifndef _DEBUG + } catch (std::exception &e) { -#if (defined _MSC_VER) && (defined _CPPRTTI) && (defined _DEBUG) +#if (defined _MSC_VER) && (defined _CPPRTTI) // if we have RTTI get the full name of the exception that occured mErrorString = std::string(typeid( e ).name()) + ": " + e.what(); @@ -663,6 +665,7 @@ const aiScene* Importer::ReadFile( const std::string& pFile, unsigned int pFlags DefaultLogger::get()->error(mErrorString); delete mScene;mScene = NULL; } +#endif // either successful or failure - the pointer expresses it anyways return mScene; diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index d255b3976..d1124613d 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -138,11 +138,19 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, a if (mapping != aiTextureMapping_UV) { // Setup the main axis (the enum values map one to one) + ai_assert(aiAxis_X == Texture::AXIS_X); pcMat->AddProperty((int*)&(*it).majorAxis,1,AI_MATKEY_TEXMAP_AXIS(type,cur)); + + // Setup UV scalings for cylindric and spherical projections + if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) + { + aiUVTransform trafo; + trafo.mScaling.x = (*it).wrapAmountW; + trafo.mScaling.y = (*it).wrapAmountH; + } DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping"); } - // The older LWOB format does not use indirect references to clips. // The file name of a texture is directly specified in the tex chunk. if (mIsLWO2) diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index 50a3b606d..ff99015d5 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -835,6 +835,11 @@ void NFFImporter::InternReadFile( const std::string& pFile, currentMeshWithUVCoords->shader = s; } } + // 'shader' - other way to specify a texture + else if (TokenMatch(sz,"shader",6)) + { + // todo + } // 'l' - light source else if (TokenMatch(sz,"l",1)) { @@ -851,6 +856,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); MeshInfo& currentMesh = meshesLocked.back(); currentMesh.shader = s; + s.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); @@ -867,6 +873,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); MeshInfo& currentMesh = meshesLocked.back(); currentMesh.shader = s; + s.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); @@ -884,6 +891,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); MeshInfo& currentMesh = meshesLocked.back(); currentMesh.shader = s; + s.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); @@ -901,6 +909,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); MeshInfo& currentMesh = meshesLocked.back(); currentMesh.shader = s; + s.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); @@ -918,6 +927,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); MeshInfo& currentMesh = meshesLocked.back(); currentMesh.shader = s; + s.mapping = aiTextureMapping_SPHERE; AI_NFF_PARSE_SHAPE_INFORMATION(); @@ -934,6 +944,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); MeshInfo& currentMesh = meshes.back(); currentMesh.shader = s; + s.mapping = aiTextureMapping_CYLINDER; aiVector3D center1, center2; float radius1, radius2; AI_NFF_PARSE_TRIPLE(center1); @@ -1207,6 +1218,11 @@ void NFFImporter::InternReadFile( const std::string& pFile, pcMat->AddProperty(&s,AI_MATKEY_NAME); } + if (aiTextureMapping_UV != src.shader.mapping) + { + pcMat->AddProperty((int*)&src.shader.mapping, 1,AI_MATKEY_MAPPING_DIFFUSE(0)); + } + // setup some more material properties that are specific to NFF2 int i; if (src.shader.twoSided) diff --git a/code/NFFLoader.h b/code/NFFLoader.h index 2c3b50ed1..762dda1dc 100644 --- a/code/NFFLoader.h +++ b/code/NFFLoader.h @@ -109,6 +109,7 @@ private: , shaded (true) // for NFF2 , opacity (1.f) , shininess (0.f) + , mapping (aiTextureMapping_UV) {} aiColor3D color,diffuse,specular,ambient,emissive; @@ -123,6 +124,11 @@ private: std::string name; + // texture mapping to be generated for the mesh - uv is the default + // it means: use UV if there, nothing otherwise. This property is + // used for locked meshes. + aiTextureMapping mapping; + // shininess is ignored for the moment bool operator == (const ShadingInfo& other) const { diff --git a/code/TargetAnimation.cpp b/code/TargetAnimation.cpp index 940834a14..641fc9b52 100644 --- a/code/TargetAnimation.cpp +++ b/code/TargetAnimation.cpp @@ -82,7 +82,7 @@ KeyIterator::KeyIterator(const std::vector* _objPos, // ------------------------------------------------------------------------------------------------ template -T Interpolate(const T& one, const T& two, float val) +inline T Interpolate(const T& one, const T& two, float val) { return one + (two-one)*val; } @@ -93,20 +93,14 @@ void KeyIterator::operator ++() // If we are already at the end of all keyframes, return if (reachedEnd)return; - int breakThisUglyStuff = 0; // Now search in all arrays for the time value closest // to our current position on the time line double d0,d1; - d0 = objPos->at(nextObjPos).mTime; - if (nextObjPos == objPos->size()-1) - ++breakThisUglyStuff; - - d1 = targetObjPos->at(nextTargetObjPos).mTime; - if (nextTargetObjPos == targetObjPos->size()-1) - ++breakThisUglyStuff; - + d0 = objPos->at ( std::min ( nextObjPos, objPos->size()-1) ).mTime; + d1 = targetObjPos->at( std::min ( nextTargetObjPos, targetObjPos->size()-1) ).mTime; + // Easiest case - all are identical. In this // case we don't need to interpolate so we can // return earlier @@ -116,11 +110,14 @@ void KeyIterator::operator ++() curPosition = objPos->at(nextObjPos).mValue; curTargetPosition = targetObjPos->at(nextTargetObjPos).mValue; - // Increment all counters, regardless whether - // the corresponding arrays are there - ++nextObjPos; - ++nextTargetObjPos; + // increment counters + if (objPos->size() != nextObjPos-1) + ++nextObjPos; + + if (targetObjPos->size() != nextTargetObjPos-1) + ++nextTargetObjPos; } + // An object position key is closest to us else if (d0 < d1) { @@ -140,12 +137,8 @@ void KeyIterator::operator ++() (curTime-first.mTime) / (last.mTime-first.mTime) )); } - // increment counters if (objPos->size() != nextObjPos-1) ++nextObjPos; - - if (targetObjPos->size() != nextTargetObjPos-1) - ++nextTargetObjPos; } // A target position key is closest to us else @@ -165,9 +158,13 @@ void KeyIterator::operator ++() curPosition = Interpolate(first.mValue, last.mValue, (float) ( (curTime-first.mTime) / (last.mTime-first.mTime))); } + + if (targetObjPos->size() != nextTargetObjPos-1) + ++nextTargetObjPos; } - if (2 == breakThisUglyStuff) + if (nextObjPos >= objPos->size()-1 && + nextTargetObjPos >= targetObjPos->size()-1) { // We reached the very last keyframe reachedEnd = true; @@ -226,13 +223,7 @@ void TargetAnimationHelper::Process(std::vector* distanceTrack) // diff vector aiVector3D diff = tposition - position; - float f = diff.SquareLength(); - if (!f) - { - DefaultLogger::get()->error("Target position equals object position"); - continue; - } - f = ::sqrt(f); + float f = diff.Length(); // output distance vector if (fill) @@ -243,6 +234,8 @@ void TargetAnimationHelper::Process(std::vector* distanceTrack) v.mValue = aiVector3D (0.f,0.f,f); } diff /= f; + + // diff is now the vector in which our camera is pointing } if (real.size()) diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 2738292ed..4b7900b67 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -869,7 +869,7 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, this->ReportError("aiNodeAnim::mPositionKeys is NULL (aiNodeAnim::mNumPositionKeys is %i)", pNodeAnim->mNumPositionKeys); } - double dLast = -0.1; + double dLast = -10e10; for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys;++i) { if (pNodeAnim->mPositionKeys[i].mTime > pAnimation->mDuration) @@ -879,7 +879,7 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, (float)pNodeAnim->mPositionKeys[i].mTime, (float)pAnimation->mDuration); } - if (pNodeAnim->mPositionKeys[i].mTime <= dLast) + if (i && pNodeAnim->mPositionKeys[i].mTime <= dLast) { ReportWarning("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is smaller " "than aiAnimation::mPositionKeys[%i] (which is %.5f)",i, @@ -897,7 +897,7 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, this->ReportError("aiNodeAnim::mRotationKeys is NULL (aiNodeAnim::mNumRotationKeys is %i)", pNodeAnim->mNumRotationKeys); } - double dLast = -0.1; + double dLast = -10e10; for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys;++i) { if (pNodeAnim->mRotationKeys[i].mTime > pAnimation->mDuration) @@ -907,7 +907,7 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, (float)pNodeAnim->mRotationKeys[i].mTime, (float)pAnimation->mDuration); } - if (pNodeAnim->mRotationKeys[i].mTime <= dLast) + if (i && pNodeAnim->mRotationKeys[i].mTime <= dLast) { ReportWarning("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is smaller " "than aiAnimation::mRotationKeys[%i] (which is %.5f)",i, @@ -925,7 +925,7 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, this->ReportError("aiNodeAnim::mScalingKeys is NULL (aiNodeAnim::mNumScalingKeys is %i)", pNodeAnim->mNumScalingKeys); } - double dLast = -0.1; + double dLast = -10e10; for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys;++i) { if (pNodeAnim->mScalingKeys[i].mTime > pAnimation->mDuration) @@ -935,7 +935,7 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation, (float)pNodeAnim->mScalingKeys[i].mTime, (float)pAnimation->mDuration); } - if (pNodeAnim->mScalingKeys[i].mTime <= dLast) + if (i && pNodeAnim->mScalingKeys[i].mTime <= dLast) { ReportWarning("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is smaller " "than aiAnimation::mScalingKeys[%i] (which is %.5f)",i,