Преглед изворни кода

Ogre: Support for multiple texcoords

git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1248 67173fc5-114c-0410-ac8e-9d2fd5bffc1f
jonathanklein пре 13 година
родитељ
комит
d9d57804fa
4 измењених фајлова са 88 додато и 44 уклоњено
  1. 3 3
      code/OgreImporter.hpp
  2. 26 1
      code/OgreMaterial.cpp
  3. 50 40
      code/OgreMesh.cpp
  4. 9 0
      code/OgreXmlHelper.hpp

+ 3 - 3
code/OgreImporter.hpp

@@ -38,14 +38,14 @@ struct SubMesh
 	std::vector<aiVector3D> Positions; bool HasPositions;
 	std::vector<aiVector3D> Normals; bool HasNormals;
 	std::vector<aiVector3D> Tangents; bool HasTangents;
-	std::vector<aiVector3D> Uvs; unsigned int NumUvs;//nearly always 2d, but assimp has always 3d texcoords
+	std::vector<std::vector<aiVector3D> > Uvs;//arbitrary number of texcoords, they are nearly always 2d, but assimp has always 3d texcoords, n vectors(outer) with texcoords for each vertex(inner)
 
-	std::vector< std::vector<Weight> > Weights;//a list of bones for each vertex
+	std::vector< std::vector<Weight> > Weights;//a list(inner) of bones for each vertex(outer)
 	int MaterialIndex;///< The Index in the Assimp Materialarray from the material witch is attached to this submesh
 	unsigned int BonesUsed;//the highest index of a bone from a bone weight, this is needed to create the assimp bone structur (converting from Vertex-Bones to Bone-Vertices)
 
 	SubMesh(): SharedData(false), HasPositions(false), HasNormals(false), HasTangents(false),
-		NumUvs(0), MaterialIndex(-1), BonesUsed(0) {}//initialize everything
+		MaterialIndex(-1), BonesUsed(0) {}//initialize everything
 };
 
 

+ 26 - 1
code/OgreMaterial.cpp

@@ -282,6 +282,9 @@ aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const
 
 void OgreImporter::ReadTechnique(stringstream &ss, aiMaterial* NewMaterial)
 {
+	unsigned int CurrentTextureId=0;
+
+
 	string RestOfLine;
 	getline(ss, RestOfLine);//ignore the rest of the line
 
@@ -349,11 +352,33 @@ void OgreImporter::ReadTechnique(stringstream &ss, aiMaterial* NewMaterial)
 						{
 							ss >> Line;
 							aiString ts(Line.c_str());
-							NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
+							NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, CurrentTextureId));
+						}
+						else if(Line=="tex_coord_set")
+						{
+							int UvSet;
+							ss >> UvSet;
+							NewMaterial->AddProperty(&UvSet, 1, AI_MATKEY_UVWSRC(0, CurrentTextureId));
 						}
+						else if(Line=="colour_op")
+						{
+							ss >> Line;
+							if("replace"==Line)//I don't think, assimp has something for this...
+							{
+							}
+							else if("modulate"==Line)
+							{
+								//TODO: set value
+								//NewMaterial->AddProperty(aiTextureOp_Multiply)
+							}
+						}
+						
 					}//end of texture unit
+					Line="";//clear the } that would end the outer loop
+					CurrentTextureId++;//new Id for the next texture
 				}
 			}
+			Line="";//clear the } that would end the outer loop
 		}
 	}//end of technique
 }

+ 50 - 40
code/OgreMesh.cpp

@@ -111,8 +111,11 @@ void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
 			if(theSubMesh.HasTangents && theSubMesh.Tangents.size() != NumVertices)
 				throw DeadlyImportError("Wrong Number of Tangents loaded!");
 
-			if(theSubMesh.NumUvs==1 && theSubMesh.Uvs.size() != NumVertices)
-				throw DeadlyImportError("Wrong Number of Uvs loaded!");
+			for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i)
+			{
+				if(theSubMesh.Uvs[i].size() != NumVertices)
+					throw DeadlyImportError("Wrong Number of Uvs loaded!");
+			}
 
 		}//end of "geometry
 
@@ -139,7 +142,7 @@ void OgreImporter::ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsi
 	bool ReadPositions=false;
 	bool ReadNormals=false;
 	bool ReadTangents=false;
-	bool ReadUvs=false;
+	unsigned int NumUvs=0;
 
 	//-------------------- check, what we need to read: --------------------------------
 	if(Reader->getAttributeValue("positions") && GetAttribute<bool>(Reader, "positions"))
@@ -161,26 +164,18 @@ void OgreImporter::ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsi
 		DefaultLogger::get()->debug("reading tangents");
 	}
 
-
-	//we can have 1 or 0 uv channels, and if the mesh has no uvs, it also doesn't have the attribute
-	if(!Reader->getAttributeValue("texture_coords"))
-		theSubMesh.NumUvs=0;
-	else
+	if(Reader->getAttributeValue("texture_coords"))
 	{
-		ReadUvs=!!(theSubMesh.NumUvs=GetAttribute<int>(Reader, "texture_coords"));
-		theSubMesh.Uvs.reserve(NumVertices);
+		NumUvs=GetAttribute<unsigned int>(Reader, "texture_coords");
+		theSubMesh.Uvs.resize(NumUvs);
+		for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i) theSubMesh.Uvs[i].reserve(NumVertices);
 		DefaultLogger::get()->debug("reading texture coords");
 	}
-	if(theSubMesh.NumUvs>1)
-	{
-		DefaultLogger::get()->warn("too many texcoords (just 1 supported!), just the first texcoords will be loaded!");
-		theSubMesh.NumUvs=1;
-	}
 	//___________________________________________________________________
 
 
 	//check if we will load anything
-	if(!(ReadPositions || ReadNormals || ReadTangents || ReadUvs))
+	if(!( ReadPositions || ReadNormals || ReadTangents || (NumUvs>0) ))
 		DefaultLogger::get()->warn("vertexbuffer seams to be empty!");
 	
 
@@ -230,17 +225,21 @@ void OgreImporter::ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsi
 		}
 
 		//Uv:
-		else if(ReadUvs && Reader->getNodeName()==string("texcoord"))
+		else if(NumUvs>0 && Reader->getNodeName()==string("texcoord"))
 		{
-			aiVector3D NewUv;
-			NewUv.x=GetAttribute<float>(Reader, "u");
-			NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
-			theSubMesh.Uvs.push_back(NewUv);
-
-			//skip all the following texcoords:
-			while(Reader->getNodeName()==string("texcoord"))
+			for(unsigned int i=0; i<NumUvs; ++i)
+			{
+				if(Reader->getNodeName()!=string("texcoord"))
+				{
+					DefaultLogger::get()->warn(string("Not enough UVs in Vertex: ")+Reader->getNodeName());
+				}
+				aiVector3D NewUv;
+				NewUv.x=GetAttribute<float>(Reader, "u");
+				NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
+				theSubMesh.Uvs[i].push_back(NewUv);
 				XmlRead(Reader);
-			continue;//don't read another line at the end of the loop
+			}
+			continue;//because we already read the next node...
 		}
 
 		//Color:
@@ -284,12 +283,20 @@ void OgreImporter::ProcessSubMesh(SubMesh &theSubMesh, SubMesh &theSharedGeometr
 	//---------------Make all Vertexes unique: (this is required by assimp)-----------------------
 	vector<Face> UniqueFaceList(theSubMesh.FaceList.size());
 	unsigned int UniqueVertexCount=theSubMesh.FaceList.size()*3;//*3 because each face consists of 3 vertexes, because we only support triangles^^
+
 	vector<aiVector3D> UniquePositions(UniqueVertexCount);
+
 	vector<aiVector3D> UniqueNormals(UniqueVertexCount);
+
 	vector<aiVector3D> UniqueTangents(UniqueVertexCount);
-	vector<aiVector3D> UniqueUvs(UniqueVertexCount);
+
 	vector< vector<Weight> > UniqueWeights(UniqueVertexCount);
 
+	vector< vector<aiVector3D> > UniqueUvs(theSubMesh.Uvs.size());
+	for(unsigned int i=0; i<UniqueUvs.size(); ++i)	UniqueUvs[i].resize(UniqueVertexCount);
+
+
+
 	//Support for shared data:
 	/*We can use this loop to copy vertex informations from the shared data pool. In order to do so
 	  we just use a reference to a submodel instead of our submodel itself*/
@@ -300,14 +307,11 @@ void OgreImporter::ProcessSubMesh(SubMesh &theSubMesh, SubMesh &theSharedGeometr
 		theSubMesh.HasPositions=theSharedGeometry.HasPositions;
 		theSubMesh.HasNormals=theSharedGeometry.HasNormals;
 		theSubMesh.HasTangents=theSharedGeometry.HasTangents;
-		theSubMesh.NumUvs=theSharedGeometry.NumUvs;
-		theSubMesh.BonesUsed=theSharedGeometry.BonesUsed;
-	}
 
+		theSubMesh.BonesUsed=theSharedGeometry.BonesUsed;
 
-	if(VertexSource.NumUvs > 0)
-	{
-		DefaultLogger::get()->error("Not all Uvs will be made unique!");
+		UniqueUvs.resize(theSharedGeometry.Uvs.size());
+		for(unsigned int i=0; i<UniqueUvs.size(); ++i)	UniqueUvs[i].resize(UniqueVertexCount);
 	}
 
 	for(unsigned int i=0; i<theSubMesh.FaceList.size(); ++i)
@@ -335,11 +339,14 @@ void OgreImporter::ProcessSubMesh(SubMesh &theSubMesh, SubMesh &theSharedGeometr
 			UniqueTangents[3*i+2]=VertexSource.Tangents[Vertex3];
 		}
 
-		if(VertexSource.NumUvs > 0)
+		if(UniqueUvs.size()>0)
 		{
-			UniqueUvs[3*i+0]=VertexSource.Uvs[Vertex1];
-			UniqueUvs[3*i+1]=VertexSource.Uvs[Vertex2];
-			UniqueUvs[3*i+2]=VertexSource.Uvs[Vertex3];
+			for(unsigned int j=0; j<UniqueUvs.size(); ++j)
+			{
+				UniqueUvs[j][3*i+0]=VertexSource.Uvs[j][Vertex1];
+				UniqueUvs[j][3*i+1]=VertexSource.Uvs[j][Vertex2];
+				UniqueUvs[j][3*i+2]=VertexSource.Uvs[j][Vertex3];
+			}
 		}
 
 		if(VertexSource.Weights.size() > 0)
@@ -425,11 +432,14 @@ aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vecto
 	*/
 
 	//Uvs
-	if(0!=theSubMesh.NumUvs)
+	if(theSubMesh.Uvs.size()>0)
 	{
-		NewAiMesh->mNumUVComponents[0]=2;
-		NewAiMesh->mTextureCoords[0]= new aiVector3D[theSubMesh.Uvs.size()];
-		memcpy(NewAiMesh->mTextureCoords[0], &theSubMesh.Uvs[0], theSubMesh.Uvs.size()*sizeof(aiVector3D));
+		for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i)
+		{
+			NewAiMesh->mNumUVComponents[i]=2;
+			NewAiMesh->mTextureCoords[i]=new aiVector3D[theSubMesh.Uvs[i].size()];
+			memcpy(NewAiMesh->mTextureCoords[i], &(theSubMesh.Uvs[i][0]), theSubMesh.Uvs[i].size()*sizeof(aiVector3D));
+		}
 	}
 
 

+ 9 - 0
code/OgreXmlHelper.hpp

@@ -29,6 +29,15 @@ template<> inline int GetAttribute<int>(XmlReader* Reader, std::string Name)
 		throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
 }
 
+template<> inline unsigned int GetAttribute<unsigned int>(XmlReader* Reader, std::string Name)
+{
+	const char* Value=Reader->getAttributeValue(Name.c_str());
+	if(Value)
+		return static_cast<unsigned int>(atoi(Value));//yes, ugly, but pfff
+	else
+		throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str());
+}
+
 template<> inline float GetAttribute<float>(XmlReader* Reader, std::string Name)
 {
 	const char* Value=Reader->getAttributeValue(Name.c_str());