[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51265] trunk/blender/intern/cycles/ blender/blender_mesh.cpp: Cycles: make anistropic BSDF / tangent work without UV map, based on generated

Brecht Van Lommel brechtvanlommel at pandora.be
Wed Oct 10 16:21:58 CEST 2012


Revision: 51265
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51265
Author:   blendix
Date:     2012-10-10 14:21:58 +0000 (Wed, 10 Oct 2012)
Log Message:
-----------
Cycles: make anistropic BSDF / tangent work without UV map, based on generated
coordinates map to a sphere.

Modified Paths:
--------------
    trunk/blender/intern/cycles/blender/blender_mesh.cpp

Modified: trunk/blender/intern/cycles/blender/blender_mesh.cpp
===================================================================
--- trunk/blender/intern/cycles/blender/blender_mesh.cpp	2012-10-10 14:19:35 UTC (rev 51264)
+++ trunk/blender/intern/cycles/blender/blender_mesh.cpp	2012-10-10 14:21:58 UTC (rev 51265)
@@ -33,8 +33,24 @@
 
 /* Find/Add */
 
-static float3 tri_calc_tangent(float3 v0, float3 v1, float3 v2, float3 tx0, float3 tx1, float3 tx2)
+static float3 tangent_uv_from_generated(float3 P)
 {
+	float length = len(P);
+
+	if(length == 0.0f)
+		return make_float3(0.0f, 0.0f, 0.0f);
+
+	float u = 0.0f;
+	if(!(P.x == 0.0f && P.y == 0.0f))
+		u = (1.0f - atan2f(P.x, P.y))/(2.0f*M_PI_F);
+	
+	float v = 1.0f - acosf(clamp(P.z/length, -1.0f, 1.0f))/M_PI_F;
+
+	return make_float3(u, v, 0.0f);
+}
+
+static float3 tangent_from_triangle(float3 v0, float3 v1, float3 v2, float3 tx0, float3 tx1, float3 tx2)
+{
 	float3 duv1 = tx2 - tx0;
 	float3 duv2 = tx2 - tx1;
 	float3 dp1 = v2 - v0;
@@ -89,27 +105,6 @@
 		nverts.push_back(n);
 	}
 
-	/* create generated coordinates. todo: we should actually get the orco
-	 * coordinates from modifiers, for now we use texspace loc/size which
-	 * is available in the api. */
-	if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
-		Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
-		float3 loc = get_float3(b_mesh.texspace_location());
-		float3 size = get_float3(b_mesh.texspace_size());
-
-		if(size.x != 0.0f) size.x = 0.5f/size.x;
-		if(size.y != 0.0f) size.y = 0.5f/size.y;
-		if(size.z != 0.0f) size.z = 0.5f/size.z;
-
-		loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
-
-		float3 *fdata = attr->data_float3();
-		size_t i = 0;
-
-		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
-			fdata[i++] = get_float3(v->co())*size - loc;
-	}
-
 	/* create vertex color attributes */
 	{
 		BL::Mesh::tessface_vertex_colors_iterator l;
@@ -181,16 +176,16 @@
 	}
 
 	/* create texcoord-based tangent attributes */
-	{
+	bool need_tangent = mesh->need_attribute(scene, ATTR_STD_TANGENT);
+
+	if(need_tangent) {
 		BL::Mesh::tessface_uv_textures_iterator l;
 
 		for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
-			AttributeStandard std = (l->active_render())? ATTR_STD_TANGENT: ATTR_STD_NONE;
-
-			if(!mesh->need_attribute(scene, std))
+			if(!l->active_render())
 				continue;
 
-			Attribute *attr = mesh->attributes.add(std, ustring("Tangent"));
+			Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent"));
 
 			/* compute average tangents per vertex */
 			float3 *tangents = attr->data_float3();
@@ -214,13 +209,13 @@
 				/* calculate tangent for the triangle;
 				 * get vertex positions, and find change in position with respect
 				 * to the texture coords in the first texture coord dimension */
-				float3 tangent0 = tri_calc_tangent(v0, v1, v2, tx0, tx1, tx2);
+				float3 tangent0 = tangent_from_triangle(v0, v1, v2, tx0, tx1, tx2);
 
 				if(nverts[fi] == 4) {
 					/* quad tangent */
 					float3 tx3 = get_float3(t->uv4());
 					float3 v3 = mesh->verts[vi[3]];
-					float3 tangent1 = tri_calc_tangent(v0, v2, v3, tx0, tx2, tx3);
+					float3 tangent1 = tangent_from_triangle(v0, v2, v3, tx0, tx2, tx3);
 
 					tangents[vi[0]] += 0.5f*(tangent0 + tangent1);
 					tangents[vi[1]] += tangent0;
@@ -238,8 +233,80 @@
 			/* normalize tangent vectors */
 			for(int i = 0; i < mesh->verts.size(); i++)
 				tangents[i] = normalize(tangents[i]);
+
+			need_tangent = false;
 		}
 	}
+
+	/* create generated coordinates. todo: we should actually get the orco
+	 * coordinates from modifiers, for now we use texspace loc/size which
+	 * is available in the api. */
+	if(mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_tangent) {
+		Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
+		float3 loc = get_float3(b_mesh.texspace_location());
+		float3 size = get_float3(b_mesh.texspace_size());
+
+		if(size.x != 0.0f) size.x = 0.5f/size.x;
+		if(size.y != 0.0f) size.y = 0.5f/size.y;
+		if(size.z != 0.0f) size.z = 0.5f/size.z;
+
+		loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
+
+		float3 *generated = attr->data_float3();
+		size_t i = 0;
+
+		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
+			generated[i++] = get_float3(v->co())*size - loc;
+
+		/* if there is no UV map, we generated tangents from generated coordinates */
+		if(need_tangent) {
+			Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent"));
+
+			/* compute average tangents per vertex */
+			float3 *tangents = attr->data_float3();
+			memset(tangents, 0, sizeof(float3)*mesh->verts.size());
+
+			size_t fi = 0; /* face index */
+			for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++fi, ++f) {
+				int4 vi = get_int4(f->vertices_raw());
+
+				float3 tx0 = tangent_uv_from_generated(generated[vi[0]]);
+				float3 tx1 = tangent_uv_from_generated(generated[vi[1]]);
+				float3 tx2 = tangent_uv_from_generated(generated[vi[2]]);
+
+				float3 v0 = mesh->verts[vi[0]];
+				float3 v1 = mesh->verts[vi[1]];
+				float3 v2 = mesh->verts[vi[2]];
+
+				/* calculate tangent for the triangle;
+				 * get vertex positions, and find change in position with respect
+				 * to the texture coords in the first texture coord dimension */
+				float3 tangent0 = tangent_from_triangle(v0, v1, v2, tx0, tx1, tx2);
+
+				if(nverts[fi] == 4) {
+					/* quad tangent */
+					float3 tx3 = tangent_uv_from_generated(generated[vi[3]]);
+					float3 v3 = mesh->verts[vi[3]];
+					float3 tangent1 = tangent_from_triangle(v0, v2, v3, tx0, tx2, tx3);
+
+					tangents[vi[0]] += 0.5f*(tangent0 + tangent1);
+					tangents[vi[1]] += tangent0;
+					tangents[vi[2]] += 0.5f*(tangent0 + tangent1);
+					tangents[vi[3]] += tangent1;
+				}
+				else {
+					/* triangle tangent */
+					tangents[vi[0]] += tangent0;
+					tangents[vi[1]] += tangent0;
+					tangents[vi[2]] += tangent0;
+				}
+			}
+
+			/* normalize tangent vectors */
+			for(int i = 0; i < mesh->verts.size(); i++)
+				tangents[i] = normalize(tangents[i]);
+		}
+	}
 }
 
 static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, const vector<uint>& used_shaders)




More information about the Bf-blender-cvs mailing list