#pragma warning (disable: 4305) #pragma warning (disable: 4244) // warning C4244: '=' : conversion from 'double ' to 'float ', possible loss of data #pragma warning (disable: 4101) // unreferenced local variable // function in here will calculate a tangent vector from teh u,v offsets // relating to the direction of the x,y,z object space vertex position // this code is actually very broken, but your just going to want to use // the compute_tangent_vector function in your code base.. #include #include #include #include #include "vecutil.h" typedef float vec3f[3]; typedef float vec2f[2]; struct poly { vec3f *vertex_buffer; vec2f *texcoord_buffer; int triangle_count; int vert_count; int *vert_indices; int *texcoord_indices; // we don't use indices for this in this code... vec3f *normals; // ortho normal space vec3f *tangents; vec3f *binormals; }; struct poly test_case; #define SET_VERT(a,b,c,d) {a[0]=b;a[1]=c;a[2]=d;} #define SET_VEC(a,b,c,d) {a[0]=b;a[1]=c;a[2]=d;} #define set2dvert(a,b,c) { a[0]=b;a[1]=c;} #define SUB_VEC(a,b,c) {a[0] = b[0]-c[0];a[1]=b[1]-c[1];a[2]=b[2]-c[2];} #define dot_p(a,b, c){ c = (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);} #define MUL_VEC_SCALAR(a,b) { a[0]*=b;a[1]*=b;a[2]*=b;} #define MUL_VEC(a,b,c) {a[0] = b[0]*c[0];a[1] = b[1]*c[1]; a[2] = b[2]*c[2];} void normalize(vec3f dat) { float tmp, clump; int i = 0; clump = (dat[0]*dat[0]) + (dat[1]*dat[1]) + (dat[2]*dat[2]); tmp = sqrt(clump); for (i; i < 3; i++) dat[i] /= tmp; } typedef float vec4f[4]; #include "invsqrt.h" typedef struct { vec3f point; vec3f norm; float tu, tv; float tu2, tv2; }vertex; void compute_tangent_vector(vertex pA, vertex pB, vertex pC, vec3f tangent); void compile_test() { vertex pa, pb, pc; vec3f t; compute_tangent_vector(pa, pb, pc, t); } void compute_tangent_vector(vertex pA, vertex pB, vertex pC, vec3f tangent) { vec3f vAB; vec3f vAC; vec3f n; vec3f _tangent; vec3f temp_norm0, temp_norm1; vec3f vProjAB, vProjAC; vec3f sh0, sh1; float dot_tmp0, dot_tmp1; float duAB, duAC, dvAB, dvAC; vec3f cross_tmp0, cross_tmp1; // set data from program to check.. /* pA.tu = 1.9932; pA.tv = 1.00260; SET_VEC(pA.point, -9.56567, -15.2101, -2.75456); SET_VEC(pA.norm, -0.707108, 0.707106, 0.000000); SET_VEC(pB.point, -9.56567, -15.2101, -3.82122); SET_VEC(pB.norm, -0.707108, 0.707106, 0.000000); pB.tu = 1.99392; pB.tv = 0.00260401; SET_VEC(pC.point, -10.3657, -16.0101, -2.75456); SET_VEC(pC.norm, -0.707108, 0.707106, 0.000000); pC.tu = 0.993923; pC.tv = 1.00260; */ SUB_VEC(vAB, pB.point, pA.point); SUB_VEC(vAC, pC.point, pA.point); memcpy(n, pA.norm, sizeof(vec3f)); dot_p(n, vAB, dot_tmp0); dot_p(n, vAC, dot_tmp1); memcpy(temp_norm0, n, sizeof(vec3f)); memcpy(temp_norm1, n, sizeof(vec3f)); MUL_VEC_SCALAR(temp_norm0, dot_tmp0); MUL_VEC_SCALAR(temp_norm1, dot_tmp1); SUB_VEC(vProjAB, vAB, temp_norm0); SUB_VEC(vProjAC, vAC, temp_norm1); // tu and tv texture cordinate differences duAB = pB.tu - pA.tu; duAC = pC.tu - pA.tu; dvAB = pB.tv - pA.tv; dvAC = pC.tv - pA.tv; if (duAC * dvAB > duAB * dvAC) { duAC = -duAC; duAB = -duAB; } MUL_VEC_SCALAR(vProjAB, duAC); MUL_VEC_SCALAR(vProjAC, duAB); SUB_VEC(_tangent, vProjAB, vProjAC); normalize(_tangent); memcpy(tangent, _tangent, sizeof(vec3f)); } void build_ortho_normal_space(struct poly *dat) { vec4f vec0, vec1; vec3f points[3]; vec2f uv_vecs[3]; vec3f tmp_vectors[2]; vec3f tmp_cross; float error_check; float pxpt, pypt, pzpt; float invlen; int i = 0; for (i; i < dat->triangle_count*3; i++) { memcpy(points[0], dat->vertex_buffer[dat->vert_indices[i]], sizeof(vec3f)); memcpy(uv_vecs[0], dat->texcoord_buffer[dat->texcoord_indices[i]], sizeof(vec2f)); i++; memcpy(points[1], dat->vertex_buffer[dat->vert_indices[i]], sizeof(vec3f)); memcpy(uv_vecs[1], dat->texcoord_buffer[dat->texcoord_indices[i]], sizeof(vec2f)); i++; memcpy(points[2], dat->vertex_buffer[dat->vert_indices[i]], sizeof(vec3f)); memcpy(uv_vecs[2], dat->texcoord_buffer[dat->texcoord_indices[i]], sizeof(vec2f)); i++; // SUB_VEC(vecX[2], points[2], points[1]); // SET_VEC(tmp_vectors[0], edges[0][0], uv_vecs[0][0], uv_vecs[0][1]); // SET_VEC(tmp_vectors[1], edges[1][0], uv_vecs[1][0], uv_vecs[1][1]); //< E0.x, E0.u, E0.v > X < E1.x, E1.u, E1.v > vcross(tmp_vectors[0], tmp_vectors[1], tmp_cross); /* The cross product of the two edge vectors yields a normal vector to the plane in which they lie. This vector defines a plane equation */ normalize(tmp_cross); } } void init_geometry() { int tc; int i = 0; test_case.triangle_count = 1; tc = test_case.triangle_count; test_case.vertex_buffer = malloc(sizeof(vec3f)*tc*3); test_case.vert_indices = (int *)malloc(sizeof(int)*tc*3); test_case.texcoord_buffer = malloc(sizeof(vec2f)*tc*3); test_case.texcoord_indices = (int *)malloc(sizeof(int)*tc*3); // since this is just 1 polygon, i'm going to set the normals here.. test_case.normals = malloc(sizeof(vec3f)*tc*3); // we can't set these just yet.. test_case.binormals = malloc(sizeof(vec3f)*tc*3); test_case.tangents = malloc(sizeof(vec3f)*tc*3); SET_VERT(test_case.vertex_buffer[0], -2, 0, 0); SET_VERT(test_case.vertex_buffer[1], 2, 0, 0); SET_VERT(test_case.vertex_buffer[2], 1, 2, 0); for (i = 0; i < tc*3; i++) SET_VERT(test_case.normals[i], 0, 0, 1); set2dvert(test_case.texcoord_buffer[0], 0, 0); set2dvert(test_case.texcoord_buffer[1], 1, 0); set2dvert(test_case.texcoord_buffer[2], .50, 1); for (i = 0; i < tc*3; i++) { test_case.vert_indices[i] = i; test_case.texcoord_indices[i] = i; } } void main() { init_geometry(); compile_test(); build_ortho_normal_space(&test_case); }