// 设置摄像机 void matrix_set_lookat(matrix_t *m, const vector_t *eye, const vector_t *at, const vector_t *up) { vector_t xaxis, yaxis, zaxis; vector_sub(&zaxis, at, eye); vector_normalize(&zaxis); vector_crossproduct(&xaxis, up, &zaxis); vector_normalize(&xaxis); vector_crossproduct(&yaxis, &zaxis, &xaxis); m->m[0][0] = xaxis.x; m->m[1][0] = xaxis.y; m->m[2][0] = xaxis.z; m->m[3][0] = -vector_dotproduct(&xaxis, eye); m->m[0][1] = yaxis.x; m->m[1][1] = yaxis.y; m->m[2][1] = yaxis.z; m->m[3][1] = -vector_dotproduct(&yaxis, eye); m->m[0][2] = zaxis.x; m->m[1][2] = zaxis.y; m->m[2][2] = zaxis.z; m->m[3][2] = -vector_dotproduct(&zaxis, eye); m->m[0][3] = m->m[1][3] = m->m[2][3] = 0.0f; m->m[3][3] = 1.0f; }
void generate_normals(object *obj){ unsigned int mesh,i; unsigned short *face; if(!obj) return; for(i=0;i<obj->vertex_count;i++) obj->vertices[i].normal = vector_make(0,0,0); for(mesh=0;mesh<obj->submesh_count;mesh++){ face = obj->submeshes[mesh].triangles; for(i=0;i<obj->submeshes[mesh].triangle_count;i++){ vector facenormal = vector_scale( vector_crossproduct( vector_sub( obj->vertices[face[i*3+2]].vertex, obj->vertices[face[i*3+0]].vertex ), vector_sub( obj->vertices[face[i*3+1]].vertex, obj->vertices[face[i*3+0]].vertex ) ),-1 ); obj->vertices[face[i*3+0]].normal = vector_add( obj->vertices[face[i*3+0]].normal, facenormal ); obj->vertices[face[i*3+1]].normal = vector_add( obj->vertices[face[i*3+1]].normal, facenormal ); obj->vertices[face[i*3+2]].normal = vector_add( obj->vertices[face[i*3+2]].normal, facenormal ); } } // for(i=0;i<obj->vertex_count;i++) // obj->vertices[i].normal = vector_normalize(obj->vertices[i].normal); }
void matrix_lookat( matrix m, vector position, vector target, float roll ){ vector up, forward, right; matrix temp; up = vector_make( (float)sin(roll), (float)-cos(roll), 0 ); forward = vector_normalize(vector_sub(target,position)); right = vector_normalize(vector_crossproduct(up,forward)); up = vector_normalize(vector_crossproduct(right,forward)); m[0 ] = right.x; m[1 ] = up.x; m[2 ] = forward.x; m[3 ] = 0; m[4 ] = right.y; m[5 ] = up.y; m[6 ] = forward.y; m[7 ] = 0; m[8 ] = right.z; m[9 ] = up.z; m[10] = forward.z; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; matrix_translate( temp, vector_scale(position, -1.f) ); matrix_multiply( m, temp ); }
void matrix_from_vectors (VECTOR direction, VECTOR upvect, MATRIX *m) { VECTOR w; VECTOR v,u; float lambda; v = direction; u = upvect; vector_normalize( &v ); lambda = vector_dotproduct( u,v ); u.x -= lambda*v.x; u.y -= lambda*v.y; u.z -= lambda*v.z; vector_normalize( &u ); w = vector_crossproduct( v,u ); m->el[0][0] = w.x; m->el[0][1] = w.y; m->el[0][2] = w.z; m->el[1][0] = u.x; m->el[1][1] = u.y; m->el[1][2] = u.z; m->el[2][0] = v.x; m->el[2][1] = v.y; m->el[2][2] = v.z; };
int main(int argc, char *argv[]) { // Initialize randomness srand(time(NULL)); // 7 parameters are required. if (argc != 13) { fprintf(stderr, "Usage: %s obj-file sx sy sz tx ty tz rx ry rz focal-dist hiding\n", argv[0]); return 0; } unsigned int i, j; double sx = atof( argv[2] ); double sy = atof( argv[3] ); double sz = atof( argv[4] ); double tx = atof( argv[5] ); double ty = atof( argv[6] ); double tz = atof( argv[7] ); double rx = atof( argv[8] ); double ry = atof( argv[9] ); double rz = atof( argv[10] ); double fd = atof( argv[11] ); int hiding = atoi( argv[12] ); matrix_double scale = scale_by(sx, sy, sz); matrix_double tras = traslate(tx, ty, tz); matrix_double rot = rotate(rx, ry, rz); matrix_double proj = projection(fd); file_data vnf = readobj(argv[1]); // int p; // for (p = 0; p < vnf.vertices.num_elems; p++) { // point3d t = (vnf.vertices.data)[p]; // fprintf(stderr, "(%f,%f,%f)\n", t.x, t.y, t.z); // } // Join all the transformations in a single matrix // Operation order: Scaling, rotation, traslation and projection matrix_double t1 = product(proj, tras); matrix_double t2 = product(t1, rot); matrix_double t3 = product(t2, scale); apply_matrix(t3, vnf.vertices); dispose_matrix(&t3); dispose_matrix(&t2); dispose_matrix(&t1); dispose_matrix(&scale); dispose_matrix(&tras); dispose_matrix(&rot); dispose_matrix(&proj); // Projection sets w = z, so divide everything by w. for (i = 0; i < vnf.vertices.num_elems; i++) { point3d tmp = (vnf.vertices.data)[i]; tmp.x /= tmp.w; tmp.y /= tmp.w; tmp.z /= tmp.w; (vnf.vertices.data)[i] = tmp; } // The camera normal (taking advantage of perspective projection) vector camera_normal = new_vector( new_point3d(0.0, 0.0, 0.0, 1.0), new_point3d(0.0, 0.0, 1.0, 1.0) ); // The z-buffer double **zbuf = calloc(HEIGHT, sizeof *zbuf); for (i = 0; i < HEIGHT; i++) { zbuf[i] = calloc(WIDTH, sizeof **zbuf); for (j = 0; j < WIDTH; j++) zbuf[i][j] = DBL_MAX; } color c = new_color( 255, 255, 255 ); point center = { WIDTH >> 1, HEIGHT >> 1 }; int invertX = 0, invertY = 1; raster tmp = new_raster(WIDTH, HEIGHT, 3); for (i = 0; i < vnf.faces.num_elems; i++) { point3d v1 = (vnf.vertices.data)[((vnf.faces.data)[i].v1) - 1]; point3d v2 = (vnf.vertices.data)[((vnf.faces.data)[i].v2) - 1]; point3d v3 = (vnf.vertices.data)[((vnf.faces.data)[i].v3) - 1]; point pt[3] = { new_point(v1.x, v1.y), new_point(v2.x, v2.y), new_point(v3.x, v3.y) }; for (j = 0; j < 3; j++) pt[j] = raster_translate(pt[j], center, invertX, invertY); // Hiding faces using face normals if (hiding == 1) { vector va = new_vector( v1, v2 ); vector vb = new_vector( v1, v3 ); vector vn = vector_crossproduct( va, vb ); if ( abs(vector_angle(vn, camera_normal)) < 90.0 ) continue; } // Drawing the face for (j = 0; j < 3; j++) { int curr = j; int next = (j+1) % 3; point ps = pt[curr]; point pe = pt[next]; // Use z-buffering if allowed // if (hiding == 2) // put_line_z(tmp, new_line( ps, pe ), c, bresenham, zbuf, vertices[3][curr], vertices[3][next]); // else put_line(tmp, new_line( ps, pe ), c, bresenham); } // Filling the face using a random, eye-pleasing colour color cr = { ((rand() % 255) + 255) >> 1, ((rand() % 255) + 255) >> 1, ((rand() % 255) + 255) >> 1 }; // if (hiding == 2) // fill_face_z(tmp, pt[0], pt[1], pt[2], cr, zbuf, vertices[3][j], vertices[3][(j+1) % 3]); // elseelse fill_face(tmp, pt[0], pt[1], pt[2], cr); } raster_out(tmp); dispose_raster(tmp); for (i = 0; i < HEIGHT; i++) free(zbuf[i]); free(zbuf); free(vnf.vertices.data); free(vnf.faces.data); return 0; }