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 acd06840f..8e7176bba 100644 Binary files a/test/models/LWO/LWO2/hierarchy.lwo and b/test/models/LWO/LWO2/hierarchy.lwo differ diff --git a/test/models/LWO/LWO2/hierarchy_smoothed.lwo b/test/models/LWO/LWO2/hierarchy_smoothed.lwo new file mode 100644 index 000000000..95d681ff6 Binary files /dev/null and b/test/models/LWO/LWO2/hierarchy_smoothed.lwo differ diff --git a/test/models/LWO/LWO2/transparency.lwo b/test/models/LWO/LWO2/transparency.lwo new file mode 100644 index 000000000..367216b90 Binary files /dev/null and b/test/models/LWO/LWO2/transparency.lwo differ 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