瀏覽代碼

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

aramis_acg 16 年之前
父節點
當前提交
48d768f15f

+ 5 - 10
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

+ 2 - 1
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

+ 20 - 10
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;
-
-		LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
+	while (true)	{
+		if (mFileBuffer + 6 >= end)
+			break;
 
-		if (mFileBuffer + head->length > end)
-			throw new ImportErrorException("LWOB: Invalid surface chunk length");
+		IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
+
+		/*  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;
 			}

+ 5 - 1
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;
 

+ 120 - 129
code/LWOLoader.cpp

@@ -145,8 +145,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 	mCurLayer->mName = "<LWODefault>";
 
 	// 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<unsigned int> SortedRep;
 			std::vector<SortedRep> 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<unsigned int>& 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 != "<LWODefault>" || 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<unsigned int>&
 }
 
 // ------------------------------------------------------------------------------------------------
-void LWOImporter::AddChildren(aiNode* node, uintptr_t parent, std::vector<aiNode*>& apcNodes)
+void LWOImporter::AddChildren(aiNode* node, uint16_t parent, std::vector<aiNode*>& 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<aiNode*>::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)
-	{
-		node->mChildren = new aiNode* [ node->mNumChildren ];
-		for (uintptr_t i = 0, p = 0; i < (uintptr_t)apcNodes.size();++i)
-		{
-			if (i == parent)continue;
-
-			if (apcNodes[i] && parent == (uintptr_t)(apcNodes[i]->mParent))
-			{
-				node->mChildren[p++] = apcNodes[i];
-				apcNodes[i]->mParent = node;
+	if (node->mNumChildren)	{
+		unsigned int p = 0;
 
-				// recursively add more children
-				AddChildren(apcNodes[i],i,apcNodes);
-				apcNodes[i] = NULL;
+		node->mChildren = new aiNode* [ node->mNumChildren ];
+		for (std::vector<aiNode*>::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;
+
+					// 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
+					(*it) = NULL;
+					AddChildren(nd,layer->mIndex,apcNodes);
+				}
 			}
 		}
 	}
@@ -554,43 +551,44 @@ void LWOImporter::AddChildren(aiNode* node, uintptr_t parent, std::vector<aiNode
 // ------------------------------------------------------------------------------------------------
 void LWOImporter::GenerateNodeGraph(std::vector<aiNode*>& apcNodes)
 {
-	// now generate the final nodegraph - generate a root node
-	pScene->mRootNode = new aiNode();
-	pScene->mRootNode->mName.Set("<LWORoot>");
-	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("<LWORoot>");
+	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<aiNode*>::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<aiNode*>::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 <class T>
 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 <class T>
 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();
 

+ 1 - 1
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<aiNode*>& apcNodes);
 
 	// -------------------------------------------------------------------

+ 20 - 61
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<aiColor3D>(&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:
 			{

二進制
test/models/LWO/LWO2/hierarchy.lwo


二進制
test/models/LWO/LWO2/hierarchy_smoothed.lwo


二進制
test/models/LWO/LWO2/transparency.lwo


+ 1 - 0
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