Tangent troubles (solved)

Started by
2 comments, last by Slather 16 years, 2 months ago
Hello, I having problems trying to implement Eric Lengyel's tangent generation code. I'm using my own model format, and I can successfully bump-map a quad because the tangents behave when its just a quad facing the positive-z direction. In the lower-left of the image is an isolated quad facing the positive z direction, and to the right of that is a tri-strip that curves. You can see the funky rotated tangents on that curve. By the way, my coord system is [x:right, y:up, z:facing camera]. I'd appreciate any suggestions and can provide more screenshots/code if it helps. If you'd like to see the problem in any kind of test model let me know!! I'm a 3d artist, so creating test models is no issue. Below is my tangent generation code. I'd be happy to answer any questions.

        num_vertex = vertex_vector.size() / const_vertex_floats;	// get the actual number of vertices
	vec3df *tan1 = new vec3df[num_index];
	vec3df *tan2 = new vec3df[num_index];
	uint cur_tan = 0;

	for(uint j=0; j<num_vertex-3; j+=3)		//// ***** j<num_vertex caused a vector bounds error
	{
		const vec3df v1( vertex_vector[j*const_vertex_floats], vertex_vector[j*const_vertex_floats+1], vertex_vector[j*const_vertex_floats+2]);
		const vec3df v2( vertex_vector[(j+1)*const_vertex_floats], vertex_vector[(j+1)*const_vertex_floats+1], vertex_vector[(j+1)*const_vertex_floats+2]);
		const vec3df v3( vertex_vector[(j+2)*const_vertex_floats], vertex_vector[(j+2)*const_vertex_floats+1], vertex_vector[(j+2)*const_vertex_floats+2]);
        
		const vec2df w1( vertex_vector[j*const_vertex_floats+6], vertex_vector[j*const_vertex_floats+7]);
		const vec2df w2( vertex_vector[(j+1)*const_vertex_floats+6], vertex_vector[(j+1)*const_vertex_floats+7]);
		const vec2df w3( vertex_vector[(j+2)*const_vertex_floats+6], vertex_vector[(j+2)*const_vertex_floats+7]);

		float x1 = v2.x - v1.x;
		float x2 = v3.x - v1.x;
		float y1 = v2.y - v1.y;
		float y2 = v3.y - v1.y;
		float z1 = v2.z - v1.z;
		float z2 = v3.z - v1.z;
        
		float s1 = w2.x - w1.x;
		float s2 = w3.x - w1.x;
		float t1 = w2.y - w1.y;
		float t2 = w3.y - w1.y;
        
		float r = 1.0f / (s1 * t2 - s2 * t1);
		vec3df sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
		vec3df tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
        
		tan1[cur_tan]   += sdir.normalize();
		tan1[cur_tan+1] += sdir.normalize();
		tan1[cur_tan+2] += sdir.normalize();
        
		tan2[cur_tan]	+= tdir.normalize();
		tan2[cur_tan+1] += tdir.normalize();
		tan2[cur_tan+2] += tdir.normalize();

		cur_tan += 3;
	}
	
	
    vec3df n;
    vec3df t;
    vec3df temp;
    float sign;

    for (uint c = 0; c < num_vertex; c++)
    {
	t = tan1[c];
        n = vec3df( vertex_vector[c*const_vertex_floats+3], 
		vertex_vector[c*const_vertex_floats+4], 
		vertex_vector[c*const_vertex_floats+5] );

	// Gram-Schmidt orthogonalize
        temp = (t - n * n.dot(t)).normalize();
        
        // Calculate handedness of the bitangent
		sign = ( (n.cross(t)).dot(tan2[c]) < 0.0f ) ? -1.0f : 1.0f;

		vertex_vector[c*const_vertex_floats+8] = temp.x;
		vertex_vector[c*const_vertex_floats+9] = temp.y;
		vertex_vector[c*const_vertex_floats+10] = temp.z;
		vertex_vector[c*const_vertex_floats+11] = sign;
/*
		log_write("tangent[%d]: [%f, %f, %f]", c, 
			vertex_vector[c*const_vertex_floats+8],
			vertex_vector[c*const_vertex_floats+9], 
			vertex_vector[c*const_vertex_floats+10]);*/
     }


Thank you [Edited by - sneakyrobot on February 6, 2008 4:37:11 PM]
Advertisement
I am guessing due to you flip the windings...
Thanks for the reply, but I don't think its the way the triangles are wound because no matter how the triangles are tessellated, Max will export the indices in CCW order. I've checked this in the exporter and my app when importing. Your suggestion has made me think about what the tangent code assumes about the mesh. Before calculating the tangents, it collects the s and t direction vectors, and my mesh is split into render-ready form (uv edges create additional verts) when this happens, so nothing is really being added together! I'm going to change it and see if that's the problem...

That was it! I just needed to change how the mesh was iterated when adding the s and t direction vectors to the tangent array. Thank you Mars, your comment made me think about the problem a little differently.

This topic is closed to new replies.

Advertisement