[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [26630] branches/soc-2009-chingachgook/ source/blender/collada/DocumentExporter.cpp: COLLADA branch: exporter takes face smoothness flag into account.

Arystanbek Dyussenov arystan.d at gmail.com
Fri Feb 5 18:37:22 CET 2010


Revision: 26630
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=26630
Author:   kazanbas
Date:     2010-02-05 18:36:41 +0100 (Fri, 05 Feb 2010)

Log Message:
-----------
COLLADA branch: exporter takes face smoothness flag into account.

Previously only smooth normals were written for each mesh. Now proper normals are written for flat faces too. Since smooth faces may share normals, writing of duplicate normals is avoided.

Modified Paths:
--------------
    branches/soc-2009-chingachgook/source/blender/collada/DocumentExporter.cpp

Modified: branches/soc-2009-chingachgook/source/blender/collada/DocumentExporter.cpp
===================================================================
--- branches/soc-2009-chingachgook/source/blender/collada/DocumentExporter.cpp	2010-02-05 15:55:45 UTC (rev 26629)
+++ branches/soc-2009-chingachgook/source/blender/collada/DocumentExporter.cpp	2010-02-05 17:36:41 UTC (rev 26630)
@@ -322,7 +322,18 @@
 // TODO: optimize UV sets by making indexed list with duplicates removed
 class GeometryExporter : COLLADASW::LibraryGeometries
 {
+	struct Face
+	{
+		unsigned int v1, v2, v3, v4;
+	};
+
+	struct Normal
+	{
+		float x, y, z;
+	};
+
 	Scene *mScene;
+
 public:
 	GeometryExporter(COLLADASW::StreamWriter *sw) : COLLADASW::LibraryGeometries(sw) {}
 
@@ -345,7 +356,11 @@
 #endif
 		Mesh *me = (Mesh*)ob->data;
 		std::string geom_id = get_geometry_id(ob);
-		
+		std::vector<Normal> nor;
+		std::vector<Face> norind;
+
+		create_normals(nor, norind, me);
+
 		// openMesh(geoId, geoName, meshId)
 		openMesh(geom_id);
 		
@@ -353,7 +368,7 @@
 		createVertsSource(geom_id, me);
 		
 		// writes <source> for normal coords
-		createNormalsSource(geom_id, me);
+		createNormalsSource(geom_id, me, nor);
 
 		int has_uvs = CustomData_has_layer(&me->fdata, CD_MTFACE);
 		
@@ -374,11 +389,11 @@
 			for(int a = 0; a < ob->totcol; a++)	{
 				// account for NULL materials, this should not normally happen?
 				Material *ma = give_current_material(ob, a + 1);
-				createPolylist(ma != NULL, a, has_uvs, ob, geom_id);
+				createPolylist(ma != NULL, a, has_uvs, ob, geom_id, norind);
 			}
 		}
 		else {
-			createPolylist(false, 0, has_uvs, ob, geom_id);
+			createPolylist(false, 0, has_uvs, ob, geom_id, norind);
 		}
 		
 		closeMesh();
@@ -394,7 +409,8 @@
 						int material_index,
 						bool has_uvs,
 						Object *ob,
-						std::string& geom_id)
+						std::string& geom_id,
+						std::vector<Face>& norind)
 	{
 #if 0
 		MFace *mfaces = dm->getFaceArray(dm);
@@ -443,12 +459,10 @@
 		COLLADASW::InputList &til = polylist.getInputList();
 			
 		// creates <input> in <polylist> for vertices 
-		COLLADASW::Input input1(COLLADASW::VERTEX, getUrlBySemantics
-								(geom_id, COLLADASW::VERTEX), 0);
+		COLLADASW::Input input1(COLLADASW::VERTEX, getUrlBySemantics(geom_id, COLLADASW::VERTEX), 0);
 			
 		// creates <input> in <polylist> for normals
-		COLLADASW::Input input2(COLLADASW::NORMAL, getUrlBySemantics
-								(geom_id, COLLADASW::NORMAL), 0);
+		COLLADASW::Input input2(COLLADASW::NORMAL, getUrlBySemantics(geom_id, COLLADASW::NORMAL), 1);
 			
 		til.push_back(input1);
 		til.push_back(input2);
@@ -460,7 +474,7 @@
 			char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
 			COLLADASW::Input input3(COLLADASW::TEXCOORD,
 									makeUrl(makeTexcoordSourceId(geom_id, i)),
-									1, // offset always 1, this is only until we have optimized UV sets
+									2, // offset always 2, this is only until we have optimized UV sets
 									i  // set number equals UV layer index
 									);
 			til.push_back(input3);
@@ -480,8 +494,10 @@
 			if ((has_material && f->mat_nr == material_index) || !has_material) {
 
 				unsigned int *v = &f->v1;
+				unsigned int *n = &norind[i].v1;
 				for (int j = 0; j < (f->v4 == 0 ? 3 : 4); j++) {
 					polylist.appendValues(v[j]);
+					polylist.appendValues(n[j]);
 
 					if (has_uvs)
 						polylist.appendValues(texindex + j);
@@ -596,21 +612,18 @@
 
 
 	//creates <source> for normals
-	void createNormalsSource(std::string geom_id, Mesh *me)
+	void createNormalsSource(std::string geom_id, Mesh *me, std::vector<Normal>& nor)
 	{
 #if 0
 		int totverts = dm->getNumVerts(dm);
 		MVert *verts = dm->getVertArray(dm);
 #endif
 
-		int totverts = me->totvert;
-		MVert *verts = me->mvert;
-
 		COLLADASW::FloatSourceF source(mSW);
 		source.setId(getIdBySemantics(geom_id, COLLADASW::NORMAL));
 		source.setArrayId(getIdBySemantics(geom_id, COLLADASW::NORMAL) +
 						  ARRAY_ID_SUFFIX);
-		source.setAccessorCount(totverts);
+		source.setAccessorCount(nor.size());
 		source.setAccessorStride(3);
 		COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
 		param.push_back("X");
@@ -618,18 +631,65 @@
 		param.push_back("Z");
 		
 		source.prepareToAppendValues();
-		
-		int i = 0;
-		
-		for( i = 0; i < totverts; ++i ){
-			
-			source.appendValues(float(verts[i].no[0]/32767.0),
-								float(verts[i].no[1]/32767.0),
-								float(verts[i].no[2]/32767.0));
-				
+
+		std::vector<Normal>::iterator it;
+		for (it = nor.begin(); it != nor.end(); it++) {
+			Normal& n = *it;
+			source.appendValues(n.x, n.y, n.z);
 		}
+
 		source.finish();
 	}
+
+	void create_normals(std::vector<Normal> &nor, std::vector<Face> &ind, Mesh *me)
+	{
+		int i, j, v;
+		MVert *vert = me->mvert;
+		std::map<unsigned int, unsigned int> nshar;
+
+		for (i = 0; i < me->totface; i++) {
+			MFace *fa = &me->mface[i];
+			Face f;
+			Normal n;
+			unsigned int *nn = &f.v1;
+			unsigned int *vv = &fa->v1;
+
+			memset(&f, 0, sizeof(f));
+			v = fa->v4 == 0 ? 3 : 4;
+
+			if (!(fa->flag & ME_SMOOTH)) {
+				if (v == 4)
+					normal_quad_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co, vert[fa->v4].co);
+				else
+					normal_tri_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co);
+			}
+
+			for (j = 0; j < v; j++) {
+				if (fa->flag & ME_SMOOTH) {
+					if (nshar.find(*vv) != nshar.end())
+						*nn = nshar[*vv];
+					else {
+						Normal n = {
+							vert[*vv].no[0]/32767.0,
+							vert[*vv].no[1]/32767.0,
+							vert[*vv].no[2]/32767.0
+						};
+						nor.push_back(n);
+						*nn = nor.size() - 1;
+						nshar[*vv] = *nn;
+					}
+					vv++;
+				}
+				else {
+					nor.push_back(n);
+					*nn = nor.size() - 1;
+				}
+				nn++;
+			}
+
+			ind.push_back(f);
+		}
+	}
 	
 	std::string getIdBySemantics(std::string geom_id, COLLADASW::Semantics type, std::string other_suffix = "") {
 		return geom_id + getSuffixBySemantic(type) + other_suffix;





More information about the Bf-blender-cvs mailing list