[Bf-blender-cvs] [4fce3c7ac07] master: Cycles: Speedup up tangent space calculation

Sergey Sharybin noreply at git.blender.org
Wed Oct 11 10:47:03 CEST 2017


Commit: 4fce3c7ac079923fb6d124e5c89590e0611b07b5
Author: Sergey Sharybin
Date:   Fri Aug 25 22:26:04 2017 +0200
Branches: master
https://developer.blender.org/rB4fce3c7ac079923fb6d124e5c89590e0611b07b5

Cycles: Speedup up tangent space calculation

This patch goes away form using C++ RNA during tangent space calculation which
avoids quite a bit of overhead. Now all calculation is done using data which
already exists in ccl::Mesh. This means, tangent space is now calculated from
triangles, which doesn't seem to be any different (at least as far as regression
tests are concerned).

One of the positive sides is that this change makes it possible to move tangent
space calculation from blender/ to render/ so we will have Cycles standalone
supporting tangent space.

Reviewers: brecht, lukasstockner97, campbellbarton

Differential Revision: https://developer.blender.org/D2810

===================================================================

M	intern/cycles/blender/blender_mesh.cpp

===================================================================

diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 4091c44d379..5ec3bd7a781 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -80,204 +80,195 @@ inline void face_split_tri_indices(const int face_flag,
 struct MikkUserData {
 	MikkUserData(const BL::Mesh& b_mesh,
 	             BL::MeshTextureFaceLayer *layer,
-	             int num_faces)
-	        : b_mesh(b_mesh),
-	          layer(layer),
-	          num_faces(num_faces)
+	             const Mesh *mesh,
+	             float3 *tangent,
+	             float *tangent_sign)
+	        : mesh(mesh),
+	          texface(NULL),
+	          orco(NULL),
+	          tangent(tangent),
+	          tangent_sign(tangent_sign)
 	{
-		tangent.resize(num_faces*4);
+		Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
+		vertex_normal = attr_vN->data_float3();
+
+		if(layer == NULL) {
+			Attribute *attr_orco = mesh->attributes.find(ATTR_STD_GENERATED);
+			orco = attr_orco->data_float3();
+			mesh_texture_space(*(BL::Mesh*)&b_mesh, orco_loc, orco_size);
+		}
+		else {
+			Attribute *attr_uv = mesh->attributes.find(ustring(layer->name()));
+			if(attr_uv != NULL) {
+				texface = attr_uv->data_float3();
+			}
+		}
 	}
 
-	BL::Mesh b_mesh;
-	BL::MeshTextureFaceLayer *layer;
+	const Mesh *mesh;
 	int num_faces;
-	vector<float4> tangent;
+
+	float3 *vertex_normal;
+	float3 *texface;
+	float3 *orco;
+	float3 orco_loc, orco_size;
+
+	float3 *tangent;
+	float *tangent_sign;
 };
 
 static int mikk_get_num_faces(const SMikkTSpaceContext *context)
 {
-	MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
-	return userdata->num_faces;
+	const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+	return userdata->mesh->num_triangles();
 }
 
-static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num)
+static int mikk_get_num_verts_of_face(const SMikkTSpaceContext * /*context*/,
+                                      const int /*face_num*/)
 {
-	MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
-	BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num];
-	int4 vi = get_int4(f.vertices_raw());
-
-	return (vi[3] == 0)? 3: 4;
+	return 3;
 }
 
-static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num)
+static void mikk_get_position(const SMikkTSpaceContext *context,
+                              float P[3],
+                              const int face_num, const int vert_num)
 {
-	MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
-	BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num];
-	int4 vi = get_int4(f.vertices_raw());
-	BL::MeshVertex v = userdata->b_mesh.vertices[vi[vert_num]];
-	float3 vP = get_float3(v.co());
+	const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+	const Mesh *mesh = userdata->mesh;
+	const int vert_index = mesh->triangles[face_num * 3 + vert_num];
+	const float3 vP = mesh->verts[vert_index];
 
 	P[0] = vP.x;
 	P[1] = vP.y;
 	P[2] = vP.z;
 }
 
-static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num)
+static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context,
+                                        float uv[2],
+                                        const int face_num, const int vert_num)
 {
-	MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
-	if(userdata->layer != NULL) {
-		BL::MeshTextureFace tf = userdata->layer->data[face_num];
-		float3 tfuv;
-
-		switch(vert_num) {
-			case 0:
-				tfuv = get_float3(tf.uv1());
-				break;
-			case 1:
-				tfuv = get_float3(tf.uv2());
-				break;
-			case 2:
-				tfuv = get_float3(tf.uv3());
-				break;
-			default:
-				tfuv = get_float3(tf.uv4());
-				break;
-		}
-
+	const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+	if(userdata->texface != NULL) {
+		const size_t corner_index = face_num * 3 + vert_num;
+		float3 tfuv = userdata->texface[corner_index];
 		uv[0] = tfuv.x;
 		uv[1] = tfuv.y;
 	}
-	else {
-		int vert_idx = userdata->b_mesh.tessfaces[face_num].vertices()[vert_num];
-		float3 orco =
-			get_float3(userdata->b_mesh.vertices[vert_idx].undeformed_co());
-		float2 tmp = map_to_sphere(make_float3(orco[0], orco[1], orco[2]));
+	else if(userdata->orco != NULL) {
+		const Mesh *mesh = userdata->mesh;
+		const size_t vertex_index = mesh->triangles[face_num * 3 + vert_num];
+		const float3 orco_loc = userdata->orco_loc;
+		const float3 orco_size = userdata->orco_size;
+		const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size;
+
+		const float2 tmp = map_to_sphere(orco);
 		uv[0] = tmp.x;
 		uv[1] = tmp.y;
 	}
+	else {
+		uv[0] = 0.0f;
+		uv[1] = 0.0f;
+	}
 }
 
-static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num)
+static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3],
+                            const int face_num, const int vert_num)
 {
-	MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
-	BL::MeshTessFace f = userdata->b_mesh.tessfaces[face_num];
+	const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData;
+	const Mesh *mesh = userdata->mesh;
 	float3 vN;
-
-	if(f.use_smooth()) {
-		int4 vi = get_int4(f.vertices_raw());
-		BL::MeshVertex v = userdata->b_mesh.vertices[vi[vert_num]];
-		vN = get_float3(v.normal());
+	if(mesh->smooth[face_num]) {
+		const size_t vert_index = mesh->triangles[face_num * 3 + vert_num];
+		vN = userdata->vertex_normal[vert_index];
 	}
 	else {
-		vN = get_float3(f.normal());
+		const Mesh::Triangle tri = mesh->get_triangle(face_num);
+		vN = tri.compute_normal(&mesh->verts[0]);
 	}
-
 	N[0] = vN.x;
 	N[1] = vN.y;
 	N[2] = vN.z;
 }
 
-static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, const int face, const int vert)
+static void mikk_set_tangent_space(const SMikkTSpaceContext *context,
+                                   const float T[],
+                                   const float sign,
+                                   const int face_num, const int vert_num)
 {
-	MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
-
-	userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign);
+	MikkUserData *userdata = (MikkUserData *)context->m_pUserData;
+	const size_t corner_index = face_num * 3 + vert_num;
+	userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]);
+	if(userdata->tangent_sign != NULL) {
+		userdata->tangent_sign[corner_index] = sign;
+	}
 }
 
-static void mikk_compute_tangents(BL::Mesh& b_mesh,
+static void mikk_compute_tangents(const BL::Mesh& b_mesh,
                                   BL::MeshTextureFaceLayer *b_layer,
                                   Mesh *mesh,
-                                  const vector<int>& nverts,
-                                  const vector<int>& face_flags,
                                   bool need_sign,
                                   bool active_render)
 {
-	/* setup userdata */
-	MikkUserData userdata(b_mesh, b_layer, nverts.size());
-
-	/* setup interface */
-	SMikkTSpaceInterface sm_interface;
-	memset(&sm_interface, 0, sizeof(sm_interface));
-	sm_interface.m_getNumFaces = mikk_get_num_faces;
-	sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face;
-	sm_interface.m_getPosition = mikk_get_position;
-	sm_interface.m_getTexCoord = mikk_get_texture_coordinate;
-	sm_interface.m_getNormal = mikk_get_normal;
-	sm_interface.m_setTSpaceBasic = mikk_set_tangent_space;
-
-	/* setup context */
-	SMikkTSpaceContext context;
-	memset(&context, 0, sizeof(context));
-	context.m_pUserData = &userdata;
-	context.m_pInterface = &sm_interface;
-
-	/* compute tangents */
-	genTangSpaceDefault(&context);
-
-	/* create tangent attributes */
+	/* Create tangent attributes. */
 	Attribute *attr;
 	ustring name;
-	if(b_layer != NULL)
+	if(b_layer != NULL) {
 		name = ustring((string(b_layer->name().c_str()) + ".tangent").c_str());
-	else
+	}
+	else {
 		name = ustring("orco.tangent");
-
-	if(active_render)
+	}
+	if(active_render) {
 		attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
-	else
-		attr = mesh->attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
-
+	}
+	else {
+		attr = mesh->attributes.add(name,
+		                            TypeDesc::TypeVector,
+		                            ATTR_ELEMENT_CORNER);
+	}
 	float3 *tangent = attr->data_float3();
-
-	/* create bitangent sign attribute */
+	/* Create bitangent sign attribute. */
 	float *tangent_sign = NULL;
-
 	if(need_sign) {
 		Attribute *attr_sign;
 		ustring name_sign;
-		if(b_layer != NULL)
-			name_sign = ustring((string(b_layer->name().c_str()) + ".tangent_sign").c_str());
-		else
+		if(b_layer != NULL) {
+			name_sign = ustring((string(b_layer->name().c_str()) +
+			                           ".tangent_sign").c_str());
+		}
+		else {
 			name_sign = ustring("orco.tangent_sign");
-
-		if(active_render)
-			attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
-		else
-			attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
-
-		tangent_sign = attr_sign->data_float();
-	}
-
-	for(int i = 0; i < nverts.size(); i++) {
-		int tri_a[3], tri_b[3];
-		face_split_tri_indices(face_flags[i], tri_a, tri_b);
-
-		tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_a[0]]);
-		tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_a[1]]);
-		tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_a[2]]);
-		tangent += 3;
-
-		if(tangent_sign) {
-			tangent_sign[0] = userdata.tangent[i*4 + tri_a[0]].w;
-			tangent_sign[1] = userdata.tangent[i*4 + tri_a[1]].w;
-			tangent_sign[2] = userdata.tangent[i*4 + tri_a[2]].w;
-			tangent_sign += 3;
 		}
 
-		if(nverts[i] == 4) {
-			tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_b[0]]);
-			tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_b[1]]);
-			tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_b[2]]);
-			tangent += 3;
-
-			if(tangent_sign) {
-				tangent_sign[0] = use

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list