2
0
Эх сурвалжийг харах

- Changing LWO loader's VMAP selection strategy. Unassigned VMAPs (UVs and VColors) are now kept, if possible. Referenced VMAPs have higher priority so everything should be backward compatible.
- assimp_cmd writes vertex colors in 'Colors' elements now.
- assimp_cmd writes 'set=' attribute for UVs and vertex colors.
- Adding test files for the awesome new LWO capabilities.


git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@396 67173fc5-114c-0410-ac8e-9d2fd5bffc1f

aramis_acg 16 жил өмнө
parent
commit
bd196ea318

+ 8 - 5
code/LWOFileData.h

@@ -308,9 +308,10 @@ struct VMapEntry
 	//! allocates memory for the vertex map
 	virtual void Allocate(unsigned int num)
 	{
-		if (!rawData.empty())return; // return if already allocated
+		if (!rawData.empty())
+			return; // return if already allocated
 
-		register unsigned int m = num*dims;
+		const unsigned int m = num*dims;
 		rawData.reserve(m + (m>>2u)); // 25% as  extra storage for VMADs
 		rawData.resize(m,0.f);
 		abAssigned.resize(num,false);
@@ -318,8 +319,8 @@ struct VMapEntry
 
 	std::string name;
 	unsigned int dims;
-	std::vector<float> rawData;
 
+	std::vector<float> rawData;
 	std::vector<bool> abAssigned;
 };
 
@@ -336,14 +337,15 @@ struct VColorChannel : public VMapEntry
 	//! be initialized to 1.0 by default
 	virtual void Allocate(unsigned int num)
 	{
-		if (!rawData.empty())return; // return if already allocated
+		if (!rawData.empty())
+			return; // return if already allocated
 
 		register unsigned int m = num*dims;
 		rawData.reserve(m + (m>>2u)); // 25% as  extra storage for VMADs
 		rawData.resize(m);
 
 		for (aiColor4D* p = (aiColor4D*)&rawData[0]; p < (aiColor4D*)&rawData[m-1]; ++p)
-			*p = aiColor4D();
+			p->a = 1.f;
 
 		abAssigned.resize(num,false);
 	}
@@ -618,6 +620,7 @@ typedef std::vector	<	VColorChannel	>	VColorChannelList;
 typedef std::vector	<	UVChannel		>	UVChannelList;
 typedef std::vector	<	Clip			>	ClipList;
 typedef std::vector	<	Envelope		>	EnvelopeList;
+typedef std::vector <   unsigned int    >   SortedRep;
 
 // ---------------------------------------------------------------------------
 /** \brief Represents a layer in the file

+ 2 - 3
code/LWOLoader.cpp

@@ -208,7 +208,6 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 		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;
@@ -271,8 +270,8 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 					vVColorIndices[mui] = 0xffffffff;
 #endif
 
-				FindUVChannels(_mSurfaces[i],layer,vUVChannelIndices);
-				FindVCChannels(_mSurfaces[i],layer,vVColorIndices);
+				FindUVChannels(_mSurfaces[i],sorted,layer,vUVChannelIndices);
+				FindVCChannels(_mSurfaces[i],sorted,layer,vVColorIndices);
 
 				// allocate storage for UV and CV channels
 				aiVector3D* pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS];

+ 4 - 2
code/LWOLoader.h

@@ -289,15 +289,17 @@ private:
 	 *    UV/VC channel lists of the layer
 	*/
 	void FindUVChannels(/*const*/ LWO::Surface& surf, 
+		LWO::SortedRep& sorted,
 		/*const*/ LWO::Layer& layer,
 		unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]);
 
 	// -------------------------------------------------------------------
-	void FindUVChannels(LWO::TextureList& list, LWO::Layer& layer,
-		unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS], unsigned int& next);
+	char FindUVChannels(LWO::TextureList& list,
+		LWO::Layer& layer,LWO::UVChannel& uv, unsigned int next);
 
 	// -------------------------------------------------------------------
 	void FindVCChannels(const LWO::Surface& surf, 
+		LWO::SortedRep& sorted,  
 		const LWO::Layer& layer,
 		unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]);
 

+ 135 - 63
code/LWOMaterial.cpp

@@ -285,9 +285,12 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
 		}
 		else
 		{
-			if (16.0f >= surf.mGlossiness)fGloss = 6.0f;
-			else if (64.0f >= surf.mGlossiness)fGloss = 20.0f;
-			else if (256.0f >= surf.mGlossiness)fGloss = 50.0f;
+			if (16.0f >= surf.mGlossiness)
+				fGloss = 6.0f;
+			else if (64.0f >= surf.mGlossiness)
+				fGloss = 20.0f;
+			else if (256.0f >= surf.mGlossiness)
+				fGloss = 50.0f;
 			else fGloss = 80.0f;
 		}
 
@@ -303,20 +306,19 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
 	pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
 
 	// emissive color
-	// (luminosity is not really the same but it affects the surface in 
-	//  a similar way. However, some scalings seems to be necessary)
+	// luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good.
 	clr.g = clr.b = clr.r = surf.mLuminosity*0.8f;
 	pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
 
 	// opacity ... either additive or default-blended, please
-	if (0.f != surf.mAdditiveTransparency)
-	{
+	if (0.f != surf.mAdditiveTransparency)	{
+
 		const int add = aiBlendMode_Additive;
 		pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
 		pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC);
 	}
-	else if (10e10f != surf.mTransparency)
-	{
+
+	else if (10e10f != surf.mTransparency)	{
 		const int def = aiBlendMode_Default;
 		const float f = 1.0f-surf.mTransparency;
 		pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY);
@@ -334,23 +336,19 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
 	HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
 	HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION);
 
-	// Now we need to know which shader we must use
-	// iterate through the shader list of the surface and 
-	// search for a name which we know ... 
-	for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();
-		 it != end;++it)
-	{
+	// Now we need to know which shader to use .. iterate through the shader list of
+	// the surface and  search for a name which we know ... 
+	for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();it != end;++it)	{
 		//if (!(*it).enabled)continue;
+
 		if ((*it).functionName == "LW_SuperCelShader" || (*it).functionName == "AH_CelShader")	{
-			DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader "
-				"to aiShadingMode_Toon");
+			DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
 
 			m = aiShadingMode_Toon;
 			break;
 		}
 		else if ((*it).functionName == "LW_RealFresnel" || (*it).functionName == "LW_FastFresnel")	{
-			DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel "
-				"to aiShadingMode_Fresnel");
+			DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
 
 			m = aiShadingMode_Fresnel;
 			break;
@@ -374,74 +372,148 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat
 }
 
 // ------------------------------------------------------------------------------------------------
-void LWOImporter::FindUVChannels(LWO::TextureList& list, LWO::Layer& layer,
-	unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS],
-	unsigned int& next)
+char LWOImporter::FindUVChannels(LWO::TextureList& list,
+	LWO::Layer& layer,LWO::UVChannel& uv, unsigned int next)
 {
+	char ret = 0;
 	for (TextureList::iterator it = list.begin(), end = list.end();it != end;++it)	{
 
 		// Ignore textures with non-UV mappings for the moment.
 		if (!(*it).enabled || !(*it).bCanUse || (*it).mapMode != LWO::Texture::UV)	{
 			continue;
 		}
-		for (unsigned int i = 0; i < layer.mUVChannels.size();++i)	{
-
-			bool found = false;
-			if ((*it).mUVChannelIndex == layer.mUVChannels[i].name)	{
-				// check whether we have this channel already
-				for (unsigned int m = 0; m < next;++m)	{
-
-					if (i == out[m])	{
-						(*it).mRealUVIndex = m;
-						found = true;
-						break;
-					}
-				}
+		
+		if ((*it).mUVChannelIndex == uv.name) {
+			ret = 1;
+		
+			// got it.
+			if ((*it).mRealUVIndex == 0xffffffff || (*it).mRealUVIndex == next)
+			{
+				(*it).mRealUVIndex = next;
+			}
+			else {
+				// channel mismatch. need to duplicate the material.
+				DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]");
 
-				if (!found)	{
-					(*it).mRealUVIndex = next;
-					out[next++] = i;
-					if (AI_MAX_NUMBER_OF_TEXTURECOORDS != next)
-						out[next] = 0xffffffff;
-					break;
-				}
+				// TODO
 			}
 		}
-		if (0xffffffff == (*it).mRealUVIndex)
-			DefaultLogger::get()->error("LWO2: Unable to find matching UV channel for texture");
 	}
+	return ret;
 }
 
 // ------------------------------------------------------------------------------------------------
-void LWOImporter::FindUVChannels(LWO::Surface& surf, LWO::Layer& layer,
+void LWOImporter::FindUVChannels(LWO::Surface& surf, 
+	LWO::SortedRep& sorted,LWO::Layer& layer,
 	unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
 {
-	out[0] = 0xffffffff;
-	unsigned int next = 0;
+	unsigned int next = 0, extra = 0, num_extra = 0;
+
+	// Check whether we have an UV entry != 0 for one of the faces in 'sorted'
+	for (unsigned int i = 0; i < layer.mUVChannels.size();++i)	{
+		LWO::UVChannel& uv = layer.mUVChannels[i];
+
+		for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it)	{
+			
+			LWO::Face& face = layer.mFaces[*it];
+
+			for (unsigned int n = 0; n < face.mNumIndices; ++n) {
+				unsigned int idx = face.mIndices[n];
+
+				if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) {
+
+					if (next >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
 
-	FindUVChannels(surf.mColorTextures,layer,out,next);
-	FindUVChannels(surf.mDiffuseTextures,layer,out,next);
-	FindUVChannels(surf.mSpecularTextures,layer,out,next);
-	FindUVChannels(surf.mGlossinessTextures,layer,out,next);
-	FindUVChannels(surf.mOpacityTextures,layer,out,next);
-	FindUVChannels(surf.mBumpTextures,layer,out,next);
-	FindUVChannels(surf.mReflectionTextures,layer,out,next);
+						DefaultLogger::get()->error("LWO: Maximum number of UV channels for "
+							"this mesh reached. Skipping channel \'" + uv.name + "\'");
+
+					}
+					else {
+						// Search through all textures assigned to 'surf' and look for this UV channel
+						char had = 0;
+						had |= FindUVChannels(surf.mColorTextures,layer,uv,next);
+						had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next);
+						had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next);
+						had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next);
+						had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next);
+						had |= FindUVChannels(surf.mBumpTextures,layer,uv,next);
+						had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next);
+
+						if (had != 0) {
+							
+							// We have a texture referencing this UV channel so we have to take special care of it
+							if (num_extra) {
+							
+								for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) {								
+									out[a+1] = out[a];
+								}
+							}
+							++extra;
+							out[next++] = i;
+						}
+						else {
+						
+							// Bäh ... seems not to be used at all. Push to end if enough space is available.
+							out[extra++] = i;
+							++num_extra;
+						}
+					}
+					it = sorted.end()-1;
+					break;
+				}
+			}
+		}
+	}
+	if (next != AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+		out[extra] = 0xffffffff;
+	}
 }
 
 // ------------------------------------------------------------------------------------------------
-void LWOImporter::FindVCChannels(const LWO::Surface& surf, const LWO::Layer& layer,
+void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorted, const LWO::Layer& layer,
 	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)	{
-				out[0] = i;
-				out[1] = 0xffffffff;
-				return;
+	unsigned int next = 0;
+
+	// Check whether we have an vc entry != 0 for one of the faces in 'sorted'
+	for (unsigned int i = 0; i < layer.mVColorChannels.size();++i)	{
+		const LWO::VColorChannel& vc = layer.mVColorChannels[i];
+
+		if (surf.mVCMap == vc.name) {
+			// The vertex color map is explicitely requested by the surface so we need to take special care of it
+			for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) {
+				out[a+1] = out[a];
 			}
+			out[0] = i;
+			++next;
 		}
-		DefaultLogger::get()->warn("LWO2: Unable to find vertex color channel: " + surf.mVCMap);
+		else {
+
+			for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it)	{
+				const LWO::Face& face = layer.mFaces[*it];
+
+				for (unsigned int n = 0; n < face.mNumIndices; ++n) {
+					unsigned int idx = face.mIndices[n];
+
+					if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.f,0.f,0.f,1.f)) {
+						if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
+
+							DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for "
+								"this mesh reached. Skipping channel \'" + vc.name + "\'");
+
+						}
+						else {
+							out[next++] = i;
+						}
+						it = sorted.end()-1;
+						break;
+					}
+				}
+			}
+		}
+	}
+	if (next != AI_MAX_NUMBER_OF_COLOR_SETS) {
+		out[next] = 0xffffffff;
 	}
 }
 

+ 1 - 1
mkutil/revision.h

@@ -1 +1 @@
-#define SVNRevision  387 
+#define SVNRevision  394 

BIN
test/models/LWO/LWO2/box_2uv_1unused.lwo


BIN
test/models/LWO/LWO2/box_2vc_1unused.lwo


BIN
test/models/LWO/LWO2/white.bmp


+ 2 - 2
tools/assimp_cmd/WriteDumb.cpp

@@ -890,7 +890,7 @@ void WriteDump(const aiScene* scene, FILE* out, const char* src, const char* cmd
 			if (!mesh->mTextureCoords[a])
 				break;
 
-			::fprintf(out,"\t\t<TextureCoords num_components=\"%i\"> \n",mesh->mNumUVComponents[a]);
+			::fprintf(out,"\t\t<TextureCoords set=\"%i\" num_components=\"%i\"> \n",a,mesh->mNumUVComponents[a]);
 			if (!shortened) {
 				for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
 					::fprintf(out,"\t\t%0 8f %0 8f %0 8f\n",
@@ -908,7 +908,7 @@ void WriteDump(const aiScene* scene, FILE* out, const char* src, const char* cmd
 		for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
 			if (!mesh->mColors[a])
 				break;
-			::fprintf(out,"\t\t<Color> \n");
+			//::fprintf(out,"\t\t<Colors set=\"%i\"> \n",a);
 			if (!shortened) {
 				for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
 					::fprintf(out,"\t\t%0 8f %0 8f %0 8f %0 8f\n",