From 48d768f15fe23d1b6ed48382dc047d6ff3c3b1c8 Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Thu, 26 Mar 2009 22:05:56 +0000 Subject: [PATCH] LWO - added workaround for LWOB's with ill-formed SURF chunks - layer hierarchy is now correct - fixed & simplified transparency handling FindDegenerates - fixed seldom crashes with RemoveDegenerates=1. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@369 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/FindDegenerates.cpp | 15 +- code/Importer.cpp | 3 +- code/LWOBLoader.cpp | 28 ++- code/LWOFileData.h | 6 +- code/LWOLoader.cpp | 245 ++++++++++---------- code/LWOLoader.h | 2 +- code/LWOMaterial.cpp | 81 ++----- test/models/LWO/LWO2/hierarchy.lwo | Bin 13388 -> 13390 bytes test/models/LWO/LWO2/hierarchy_smoothed.lwo | Bin 0 -> 13400 bytes test/models/LWO/LWO2/transparency.lwo | Bin 0 -> 9078 bytes tools/assimp_view/assimp_view.cpp | 1 + 11 files changed, 171 insertions(+), 210 deletions(-) create mode 100644 test/models/LWO/LWO2/hierarchy_smoothed.lwo create mode 100644 test/models/LWO/LWO2/transparency.lwo diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index c1d7f134b..74860f9ad 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -142,13 +142,6 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) } // We need to update the primitive flags array of the mesh. - // Unfortunately it is not possible to execute - // FindDegenerates before DeterminePType. The latter does - // nothing if the primitive flags have already been set by - // the loader - our changes would be ignored. Although - // we could use some tricks regarding - i.e setting - // mPrimitiveTypes to 0 in every case - but this is the cleanest - // way and causes no additional dependencies in the pipeline. switch (face.mNumIndices) { case 1u: @@ -181,9 +174,11 @@ evil_jump_outside: face_dest.mNumIndices = face_src.mNumIndices; face_dest.mIndices = face_src.mIndices; - // clear source - face_src.mNumIndices = 0; - face_src.mIndices = NULL; + if (&face_src != &face_dest) { + // clear source + face_src.mNumIndices = 0; + face_src.mIndices = NULL; + } } else { // Otherwise delete it if we don't need this face diff --git a/code/Importer.cpp b/code/Importer.cpp index 385236f49..14549aa09 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -379,11 +379,11 @@ Importer::Importer() mPostProcessingSteps.push_back( new FindInstancesProcess()); #endif - #if (!defined AI_BUILD_NO_FINDDEGENERATES_PROCESS) mPostProcessingSteps.push_back( new FindDegeneratesProcess()); #endif + #ifndef AI_BUILD_NO_GENUVCOORDS_PROCESS mPostProcessingSteps.push_back( new ComputeUVMappingProcess()); @@ -398,6 +398,7 @@ Importer::Importer() #if (!defined AI_BUILD_NO_TRIANGULATE_PROCESS) mPostProcessingSteps.push_back( new TriangulateProcess()); #endif + #if (!defined AI_BUILD_NO_SORTBYPTYPE_PROCESS) mPostProcessingSteps.push_back( new SortByPTypeProcess()); #endif diff --git a/code/LWOBLoader.cpp b/code/LWOBLoader.cpp index 48a6e41ec..63316ee3d 100644 --- a/code/LWOBLoader.cpp +++ b/code/LWOBLoader.cpp @@ -229,14 +229,23 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) LWO::Texture* pTex = NULL; GetS0(surf.mName,size); - while (true) - { - if (mFileBuffer + 6 > end)break; + while (true) { + if (mFileBuffer + 6 >= end) + break; - LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); + IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); - if (mFileBuffer + head->length > end) - throw new ImportErrorException("LWOB: Invalid surface chunk length"); + /* A single test file (sonycam.lwo) seems to have invalid surface chunks. + * I'm assuming it's the fault of a single, unknown exporter so there are + * probably THOUSANDS of them. Here's a dirty workaround: + * + * We don't break if the chunk limit is exceeded. Instead, we're computing + * how much storage is actually left and work with this value from now on. + */ + if (mFileBuffer + head->length > end) { + DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue."); + head->length = end - mFileBuffer; + } uint8_t* const next = mFileBuffer+head->length; switch (head->type) @@ -340,8 +349,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) // texture path case AI_LWO_TIMG: { - if (pTex) - { + if (pTex) { GetS0(pTex->mFileName,head->length); } else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk"); @@ -351,7 +359,9 @@ void LWOImporter::LoadLWOBSurface(unsigned int size) case AI_LWO_TVAL: { AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1); - if (pTex)pTex->mStrength = (float)GetU1()/ 255.f; + if (pTex) { + pTex->mStrength = (float)GetU1()/ 255.f; + } else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk"); break; } diff --git a/code/LWOFileData.h b/code/LWOFileData.h index b0a2e9ba3..f13e32f86 100644 --- a/code/LWOFileData.h +++ b/code/LWOFileData.h @@ -550,7 +550,7 @@ struct Surface , mIOR (1.f) // vakuum , mBumpIntensity (1.f) , mWireframe (false) - , mAdditiveTransparency (10e10f) + , mAdditiveTransparency (0.f) {} //! Name of the surface @@ -628,6 +628,7 @@ struct Layer : mFaceIDXOfs (0) , mPointIDXOfs (0) , mParent (0x0) + , mIndex (0xffff) , skip (false) {} @@ -663,6 +664,9 @@ struct Layer /** Parent index */ uint16_t mParent; + /** Index of the layer */ + uint16_t mIndex; + /** Name of the layer */ std::string mName; diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index 2446a6a6a..3a23f23be 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -145,8 +145,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, mCurLayer->mName = ""; // old lightwave file format (prior to v6) - if (AI_LWO_FOURCC_LWOB == fileType) - { + if (AI_LWO_FOURCC_LWOB == fileType) { DefaultLogger::get()->info("LWO file format: LWOB (<= LightWave 5.5)"); mIsLWO2 = false; @@ -154,13 +153,11 @@ void LWOImporter::InternReadFile( const std::string& pFile, } // New lightwave format - else if (AI_LWO_FOURCC_LWO2 == fileType) - { + else if (AI_LWO_FOURCC_LWO2 == fileType) { DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)"); } // MODO file format - else if (AI_LWO_FOURCC_LXOB == fileType) - { + else if (AI_LWO_FOURCC_LXOB == fileType) { DefaultLogger::get()->info("LWO file format: LXOB (Modo)"); } // we don't know this format @@ -174,8 +171,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, throw new ImportErrorException(std::string("Unknown LWO sub format: ") + szBuff); } - if (AI_LWO_FOURCC_LWOB != fileType) - { + if (AI_LWO_FOURCC_LWOB != fileType) { mIsLWO2 = true; LoadLWO2File(); @@ -185,8 +181,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, if (0xffffffff != configLayerIndex && configLayerIndex > mLayers->size()) throw new ImportErrorException("LWO2: The requested layer was not found"); - if (configLayerName.length() && !hasNamedLayer) - { + if (configLayerName.length() && !hasNamedLayer) { throw new ImportErrorException("LWO2: Unable to find the requested layer: " + configLayerName); } @@ -203,24 +198,21 @@ void LWOImporter::InternReadFile( const std::string& pFile, apcMeshes.reserve(mLayers->size()*std::min(((unsigned int)mSurfaces->size()/2u), 1u)); unsigned int iDefaultSurface = 0xffffffff; // index of the default surface - for (LayerList::iterator lit = mLayers->begin(), lend = mLayers->end(); - lit != lend;++lit) - { + for (LayerList::iterator lit = mLayers->begin(), lend = mLayers->end();lit != lend;++lit) { LWO::Layer& layer = *lit; - if (layer.skip)continue; + if (layer.skip) + continue; // I don't know whether there could be dummy layers, but it would be possible const unsigned int meshStart = (unsigned int)apcMeshes.size(); - if (!layer.mFaces.empty() && !layer.mTempPoints.empty()) - { + if (!layer.mFaces.empty() && !layer.mTempPoints.empty()) { + // now sort all faces by the surfaces assigned to them typedef std::vector SortedRep; std::vector pSorted(mSurfaces->size()+1); unsigned int i = 0; - for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end(); - it != end;++it,++i) - { + for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end();it != end;++it,++i) { // Check whether we support this face's type if ((*it).type != AI_LWO_FACE && (*it).type != AI_LWO_PTCH) { continue; @@ -232,10 +224,8 @@ void LWOImporter::InternReadFile( const std::string& pFile, DefaultLogger::get()->warn("LWO: Invalid face surface index"); idx = 0xffffffff; } - if(0xffffffff == idx || 0xffffffff == (idx = _mMapping[idx])) - { - if (0xffffffff == iDefaultSurface) - { + if(0xffffffff == idx || 0xffffffff == (idx = _mMapping[idx])) { + if (0xffffffff == iDefaultSurface) { iDefaultSurface = (unsigned int)mSurfaces->size(); mSurfaces->push_back(LWO::Surface()); LWO::Surface& surf = mSurfaces->back(); @@ -246,11 +236,13 @@ void LWOImporter::InternReadFile( const std::string& pFile, } pSorted[idx].push_back(i); } - if (0xffffffff == iDefaultSurface)pSorted.erase(pSorted.end()-1); - for (unsigned int p = 0,i = 0;i < mSurfaces->size();++i) - { + if (0xffffffff == iDefaultSurface) { + pSorted.erase(pSorted.end()-1); + } + for (unsigned int p = 0,i = 0;i < mSurfaces->size();++i) { SortedRep& sorted = pSorted[i]; - if (sorted.empty())continue; + if (sorted.empty()) + continue; // generate the mesh aiMesh* mesh = new aiMesh(); @@ -259,8 +251,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, // count the number of vertices SortedRep::const_iterator it = sorted.begin(), end = sorted.end(); - for (;it != end;++it) - { + for (;it != end;++it) { mesh->mNumVertices += layer.mFaces[*it].mNumIndices; } @@ -285,13 +276,13 @@ void LWOImporter::InternReadFile( const std::string& pFile, // allocate storage for UV and CV channels aiVector3D* pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) - { - if (0xffffffff == vUVChannelIndices[mui])break; + for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) { + if (0xffffffff == vUVChannelIndices[mui]) + break; + pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices]; // LightWave doesn't support more than 2 UV components (?) - // so we can directly setup this value mesh->mNumUVComponents[0] = 2; } @@ -299,15 +290,12 @@ void LWOImporter::InternReadFile( const std::string& pFile, nrm = mesh->mNormals = new aiVector3D[mesh->mNumVertices]; aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS]; - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui) - { + for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui) { if (0xffffffff == vVColorIndices[mui])break; pvVC[mui] = mesh->mColors[mui] = new aiColor4D[mesh->mNumVertices]; } // we would not need this extra array, but the code is much cleaner if we use it - // FIX: we can use the referrer ID array here. invalidate its contents - // before we resize it to avoid a unnecessary memcpy std::vector& smoothingGroups = layer.mPointReferrers; smoothingGroups.erase (smoothingGroups.begin(),smoothingGroups.end()); smoothingGroups.resize(mesh->mNumFaces,0); @@ -322,8 +310,7 @@ void LWOImporter::InternReadFile( const std::string& pFile, // copy all vertices for (unsigned int q = 0; q < face.mNumIndices;++q,++vert) { register unsigned int idx = face.mIndices[q]; - *pv = layer.mTempPoints[idx] + layer.mPivot; - pv++; + *pv++ = layer.mTempPoints[idx] /*- layer.mPivot*/; // process UV coordinates for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS;++w) { @@ -338,7 +325,9 @@ void LWOImporter::InternReadFile( const std::string& pFile, // process normals (MODO extension) if (nrm) { - *nrm++ = ((aiVector3D*)&layer.mNormals.rawData[0])[idx]; + *nrm = ((aiVector3D*)&layer.mNormals.rawData[0])[idx]; + nrm->z *= -1.f; + ++nrm; } // process vertex colors @@ -365,15 +354,14 @@ void LWOImporter::InternReadFile( const std::string& pFile, } pf->mIndices = face.mIndices; pf->mNumIndices = face.mNumIndices; - unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // make sure it won't be deleted + unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // HACK: make sure it won't be deleted pf++; } - if (!mesh->mNormals) - { + if (!mesh->mNormals) { // Compute normal vectors for the mesh - we can't use our GenSmoothNormal- // Step here since it wouldn't handle smoothing groups correctly for LWO. - // So we use a separate implementation. + // So we use a separate implementation. ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]); } else DefaultLogger::get()->debug("LWO2: No need to compute normals, they're already there"); @@ -381,16 +369,21 @@ void LWOImporter::InternReadFile( const std::string& pFile, } } - // Generate nodes to render the mesh. Store the parent index - // in the mParent member of the nodes - aiNode* pcNode = new aiNode(); - apcNodes.push_back(pcNode); - pcNode->mName.Set(layer.mName); - pcNode->mParent = (aiNode*)(uintptr_t)(layer.mParent); - pcNode->mNumMeshes = (unsigned int)apcMeshes.size() - meshStart; - pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - for (unsigned int p = 0; p < pcNode->mNumMeshes;++p) - pcNode->mMeshes[p] = p + meshStart; + // Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes + unsigned int num = apcMeshes.size() - meshStart; + if (layer.mName != "" || num > 0) { + aiNode* pcNode = new aiNode(); + apcNodes.push_back(pcNode); + pcNode->mName.Set(layer.mName); + pcNode->mParent = (aiNode*)&layer; + pcNode->mNumMeshes = num; + + if (pcNode->mNumMeshes) { + pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; + for (unsigned int p = 0; p < pcNode->mNumMeshes;++p) + pcNode->mMeshes[p] = p + meshStart; + } + } } if (apcNodes.empty() || apcMeshes.empty()) @@ -398,19 +391,16 @@ void LWOImporter::InternReadFile( const std::string& pFile, // The RemoveRedundantMaterials step will clean this up later pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = (unsigned int)mSurfaces->size()]; - for (unsigned int mat = 0; mat < pScene->mNumMaterials;++mat) - { + for (unsigned int mat = 0; mat < pScene->mNumMaterials;++mat) { MaterialHelper* pcMat = new MaterialHelper(); pScene->mMaterials[mat] = pcMat; ConvertMaterial((*mSurfaces)[mat],pcMat); } // copy the meshes to the output structure - if (apcMeshes.size()) // shouldn't happen, just to be sure we don't crash - { - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = (unsigned int)apcMeshes.size() ]; - ::memcpy(pScene->mMeshes,&apcMeshes[0],pScene->mNumMeshes*sizeof(void*)); - } + pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = (unsigned int)apcMeshes.size() ]; + ::memcpy(pScene->mMeshes,&apcMeshes[0],pScene->mNumMeshes*sizeof(void*)); + // generate the final node graph GenerateNodeGraph(apcNodes); @@ -523,29 +513,36 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector& } // ------------------------------------------------------------------------------------------------ -void LWOImporter::AddChildren(aiNode* node, uintptr_t parent, std::vector& apcNodes) +void LWOImporter::AddChildren(aiNode* node, uint16_t parent, std::vector& apcNodes) { - for (uintptr_t i = 0; i < (uintptr_t)apcNodes.size();++i) - { - if (i == parent)continue; - if (apcNodes[i] && (uintptr_t)apcNodes[i]->mParent == parent)++node->mNumChildren; + for (std::vector::iterator it = apcNodes.begin(); it != apcNodes.end(); ++it) { + if (*it) { + LWO::Layer* layer = (LWO::Layer*)(*it)->mParent; + if (layer->mParent == parent && layer->mIndex != parent) + ++node->mNumChildren; + } } - if (node->mNumChildren) - { + if (node->mNumChildren) { + unsigned int p = 0; + node->mChildren = new aiNode* [ node->mNumChildren ]; - for (uintptr_t i = 0, p = 0; i < (uintptr_t)apcNodes.size();++i) - { - if (i == parent)continue; + for (std::vector::iterator it = apcNodes.begin(); it != apcNodes.end(); ++it) { + if (*it) { + LWO::Layer* layer = (LWO::Layer*)(*it)->mParent; + if (layer->mParent == parent && layer->mIndex != parent) { + aiNode* nd = node->mChildren[p++] = *it; + nd->mParent = node; - if (apcNodes[i] && parent == (uintptr_t)(apcNodes[i]->mParent)) - { - node->mChildren[p++] = apcNodes[i]; - apcNodes[i]->mParent = node; + // fixme: ignore pivot points for the moment + //nd->mTransformation.a4 = layer->mPivot.x; + //nd->mTransformation.b4 = layer->mPivot.y; + //nd->mTransformation.c4 = layer->mPivot.z; - // recursively add more children - AddChildren(apcNodes[i],i,apcNodes); - apcNodes[i] = NULL; + // recursively add more children + (*it) = NULL; + AddChildren(nd,layer->mIndex,apcNodes); + } } } } @@ -554,43 +551,44 @@ void LWOImporter::AddChildren(aiNode* node, uintptr_t parent, std::vector& apcNodes) { - // now generate the final nodegraph - generate a root node - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set(""); - AddChildren(pScene->mRootNode,0,apcNodes); + // now generate the final nodegraph - generate a root node and attach children + aiNode* root = pScene->mRootNode = new aiNode(); + root->mName.Set(""); + AddChildren(root,0,apcNodes); + // check whether we added all layers with meshes assigned to the output graph. + // if not, add them to the root node unsigned int extra = 0; - for (unsigned int i = 0; i < apcNodes.size();++i) - if (apcNodes[i] && apcNodes[i]->mNumMeshes)++extra; + for (std::vector::iterator it = apcNodes.begin(); it != apcNodes.end(); ++it) { + if ((*it) && (*it)->mNumMeshes) + ++extra; + } if (extra) { - // we need to add extra nodes to the root const unsigned int newSize = extra + pScene->mRootNode->mNumChildren; aiNode** const apcNewNodes = new aiNode*[newSize]; - if((extra = pScene->mRootNode->mNumChildren)) - ::memcpy(apcNewNodes,pScene->mRootNode->mChildren,extra*sizeof(void*)); + if((extra = root->mNumChildren)) + ::memcpy(apcNewNodes,root->mChildren,extra*sizeof(void*)); aiNode** cc = apcNewNodes+extra; - for (unsigned int i = 0; i < apcNodes.size();++i) - { - if (apcNodes[i] && apcNodes[i]->mNumMeshes) - { - *cc++ = apcNodes[i]; - apcNodes[i]->mParent = pScene->mRootNode; + for (std::vector::iterator it = apcNodes.begin(); it != apcNodes.end(); ++it) { + if ((*it) && (*it)->mNumMeshes) { + aiNode* nd = *cc++ = *it; + nd->mParent = pScene->mRootNode; // recursively add more children - AddChildren(apcNodes[i],i,apcNodes); - apcNodes[i] = NULL; + (*it) = NULL; + AddChildren(nd,((LWO::Layer*)nd->mParent)->mIndex,apcNodes); } } - delete[] pScene->mRootNode->mChildren; - pScene->mRootNode->mChildren = apcNewNodes; - pScene->mRootNode->mNumChildren = newSize; + delete[] root->mChildren; + root->mChildren = apcNewNodes; + root->mNumChildren = newSize; } if (!pScene->mRootNode->mNumChildren) throw new ImportErrorException("LWO: Unable to build a valid node graph"); - // Remove a single root node with no meshes assigned ... + // Remove a single root node with no meshes assigned to it ... if (1 == pScene->mRootNode->mNumChildren) { aiNode* pc = pScene->mRootNode->mChildren[0]; pc->mParent = pScene->mRootNode->mChildren[0] = NULL; @@ -802,7 +800,7 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it, } } } - else DefaultLogger::get()->warn("LWO2: face has 0 indices"); + else throw new ImportErrorException("LWO2: face has 0 indices"); } } @@ -845,9 +843,7 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length) template VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPoly) { - for (typename std::vector< T >::iterator it = list.begin(), end = list.end(); - it != end; ++it) - { + for (typename std::vector< T >::iterator it = list.begin(), end = list.end();it != end; ++it) { if ((*it).name == name) { if (!perPoly) @@ -880,10 +876,7 @@ inline void CreateNewEntry(T& chan, unsigned int srcIdx) template inline void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx) { - for (typename std::vector< T >::iterator - it = list.begin(), end = list.end(); - it != end;++it) - { + for (typename std::vector< T >::iterator it = list.begin(), end = list.end();it != end;++it) { CreateNewEntry( *it, srcIdx ); } } @@ -907,8 +900,7 @@ inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int // ------------------------------------------------------------------------------------------------ inline void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, unsigned int destIdx) { - if(0xffffffff == refList[srcIdx]) - { + if(0xffffffff == refList[srcIdx]) { refList[srcIdx] = destIdx; return; } @@ -992,20 +984,16 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) while (mFileBuffer < end) { unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs; - if (idx >= numPoints) - { + if (idx >= numPoints) { DefaultLogger::get()->warn("LWO2: vertex index in vmap/vmad is out of range"); mFileBuffer += base->dims*4;continue; } - if (perPoly) - { + if (perPoly) { unsigned int polyIdx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs; - if (base->abAssigned[idx]) - { + if (base->abAssigned[idx]) { // we have already a VMAP entry for this vertex - thus // we need to duplicate the corresponding polygon. - if (polyIdx >= numFaces) - { + if (polyIdx >= numFaces) { DefaultLogger::get()->warn("LWO2: VMAD polygon index is out of range"); mFileBuffer += base->dims*4; continue; @@ -1015,10 +1003,10 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) // generate a new unique vertex for the corresponding index - but only // if we can find the index in the face - for (unsigned int i = 0; i < src.mNumIndices;++i) - { + for (unsigned int i = 0; i < src.mNumIndices;++i) { register unsigned int srcIdx = src.mIndices[i]; - if (idx != srcIdx)continue; + if (idx != srcIdx) + continue; refList.resize(refList.size()+1, 0xffffffff); @@ -1245,22 +1233,24 @@ void LWOImporter::LoadLWO2File() LWO::Layer& layer = mLayers->back(); mCurLayer = &layer; - // load this layer or ignore it? Check the layer index property - // NOTE: The first layer is the default layer, so the layer - // index is one-based now + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16); + + // Continue loading this layer or ignore it? Check the layer index property + // NOTE: The first layer is the default layer, so the layer index is one-based now if (0xffffffff != configLayerIndex && configLayerIndex != mLayers->size()-1) { skip = true; } else skip = false; - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16); + // layer index. that's just for internal parenting, from the scope of a LWS file + // all layers are numbered in the oder in which they appear in the file + layer.mIndex = GetU2(); - // and parse its properties, e.g. the pivot point - mFileBuffer += 2; + // pivot point + mFileBuffer += 2; /* unknown */ mCurLayer->mPivot.x = GetF4(); mCurLayer->mPivot.y = GetF4(); mCurLayer->mPivot.z = GetF4(); - mFileBuffer += 2; GetS0(layer.mName,head->length-16); // if the name is empty, generate a default name @@ -1276,6 +1266,7 @@ void LWOImporter::LoadLWO2File() } else hasNamedLayer = true; + // optional: parent of this layer if (mFileBuffer + 2 <= next) layer.mParent = GetU2(); diff --git a/code/LWOLoader.h b/code/LWOLoader.h index 9e308599e..e88013ace 100644 --- a/code/LWOLoader.h +++ b/code/LWOLoader.h @@ -314,7 +314,7 @@ private: * @param parent Index of the node * @param apcNodes Flat list of nodes - used nodes are set to NULL. */ - void AddChildren(aiNode* node, uintptr_t parent, + void AddChildren(aiNode* node, uint16_t parent, std::vector& apcNodes); // ------------------------------------------------------------------- diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index 907c779f3..5c3123f3f 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -90,10 +90,9 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, a aiString s; bool ret = false; - for (TextureList::const_iterator it = in.begin(), end = in.end(); - it != end;++it) - { - if (!(*it).enabled || !(*it).bCanUse)continue; + for (TextureList::const_iterator it = in.begin(), end = in.end();it != end;++it) { + if (!(*it).enabled || !(*it).bCanUse) + continue; ret = true; // Convert lightwave's mapping modes to ours. We let them @@ -121,8 +120,7 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, a break; case LWO::Texture::UV: { - if( 0xffffffff == (*it).mRealUVIndex ) - { + if( 0xffffffff == (*it).mRealUVIndex ) { // We have no UV index for this texture, so we can't display it continue; } @@ -166,13 +164,11 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, a // 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) - { + if (mIsLWO2) { // find the corresponding clip ClipList::iterator clip = mClips.begin(); temp = (*it).mClipIdx; - for (ClipList::iterator end = mClips.end(); clip != end; ++clip) - { + for (ClipList::iterator end = mClips.end(); clip != end; ++clip) { if ((*clip).idx == temp) break; @@ -284,8 +280,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat if (surf.mSpecularValue && surf.mGlossiness) { float fGloss; - if (mIsLWO2) - { + if (mIsLWO2) { fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f); } else @@ -314,7 +309,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_EMISSIVE); // opacity ... either additive or default-blended, please - if (10e10f != surf.mAdditiveTransparency) + if (0.f != surf.mAdditiveTransparency) { const int add = aiBlendMode_Additive; pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY); @@ -437,12 +432,9 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, const LWO::Layer& lay unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]) { out[0] = 0xffffffff; - if (surf.mVCMap.length()) - { - for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) - { - if (surf.mVCMap == layer.mVColorChannels[i].name) - { + if (surf.mVCMap.length()) { + for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) { + if (surf.mVCMap == layer.mVColorChannels[i].name) { out[0] = i; out[1] = 0xffffffff; return; @@ -598,11 +590,8 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsi } // now attach the texture to the parent surface - sort by ordinal string - for (TextureList::iterator it = listRef->begin(); - it != listRef->end(); ++it) - { - if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) - { + for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) { + if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { listRef->insert(it,tex); return; } @@ -652,9 +641,7 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head, unsig } // now attach the shader to the parent surface - sort by ordinal string - for (ShaderList::iterator it = surf.mShaders.begin(); - it != surf.mShaders.end(); ++it) - { + for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) { if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { surf.mShaders.insert(it,shader); return; @@ -676,26 +663,23 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) // check whether this surface was derived from any other surface std::string derived; GetS0(derived,(unsigned int)(end - mFileBuffer)); - if (derived.length()) - { - + if (derived.length()) { // yes, find this surface - for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; - it != end; ++it) - { + for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) { if ((*it).mName == derived) { // we have it ... surf = *it; - derived.clear(); + derived.clear();break; } } - if (!derived.size()) + if (derived.size()) DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived); } while (true) { - if (mFileBuffer + 6 >= end)break; + if (mFileBuffer + 6 >= end) + break; LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); if (mFileBuffer + head->length > end) @@ -738,31 +722,6 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) surf.mTransparency = GetF4(); break; } - // transparency mode - case AI_LWO_ALPH: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ALPH,6); - uint16_t mode = GetU2(); - switch (mode) - { - // The surface has no effect on the alpha channel when rendered - case 0: - surf.mTransparency = 10e10f; - break; - - // The alpha channel will be written with the constant value - // following the mode in the subchunk. - case 1: - surf.mTransparency = GetF4(); - break; - - // The alpha value comes from the shadow density - case 3: - DefaultLogger::get()->error("LWO2: Unsupported alpha mode: shadow_density"); - surf.mTransparency = 10e10f; - } - break; - } // additive transparency case AI_LWO_ADTR: { diff --git a/test/models/LWO/LWO2/hierarchy.lwo b/test/models/LWO/LWO2/hierarchy.lwo index acd06840f5098df7c9bf93d3298f9b70d5f664d7..8e7176bba0b0fb8a5ababcfd3b34ef4ea3b631aa 100644 GIT binary patch delta 153 zcmX?;aV~?y%|FPOfx*OWB8Ry=GXn~6&dAJ3@lOlN&o40mO0aC6!zj&%v9#&x z_&7!e0fki3xBea@T(>9t>T=B#^BVqOZWUgpgYm=uAU85j1Rwzf_BUtFa?Z%iN%2n$%Fiz`1PU>4E;5i{ zRP%9+3FERt#i28NAs@{Fn~42%p6`+;&`HEC&S?nQ}tDX0pW WHXG?HGBPr6ZeVQF-P~n(gb4sTtSX5B diff --git a/test/models/LWO/LWO2/hierarchy_smoothed.lwo b/test/models/LWO/LWO2/hierarchy_smoothed.lwo new file mode 100644 index 0000000000000000000000000000000000000000..95d681ff69741ea2f78b1197e83fc961f0be6544 GIT binary patch literal 13400 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 R&-`5_v;VI@|CfHQ{|2#YY=8g& literal 0 HcmV?d00001 diff --git a/test/models/LWO/LWO2/transparency.lwo b/test/models/LWO/LWO2/transparency.lwo new file mode 100644 index 0000000000000000000000000000000000000000..367216b90701b4b45901edee5514c606fc572fea GIT binary patch literal 9078 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 literal 0 HcmV?d00001 diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index 242164fcf..b5fb34cf1 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -129,6 +129,7 @@ DWORD WINAPI LoadThreadProc(LPVOID lpParameter) double fCur = (double)timeGetTime(); aiSetImportPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS,1); + //aiSetImportPropertyInteger(AI_CONFIG_PP_FD_REMOVE,1); //aiSetImportPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,1); // Call ASSIMPs C-API to load the file