void Build_CAM4DV1_Matrix_UVN(CAM4DV1_PTR cam, int mode) { MATRIX4X4 mt_inv; MATRIX4X4 mt_uvn; MATRIX4X4 mtmp; //Ïà»úƽÒƾØÕóµÄÄæ¾ØÕó Mat_Init_4X4(&mt_inv, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, -cam->pos.x, -cam->pos.y, -cam->pos.z, 1); if (UVN_MODE_SPHERICAL == mode) { float phi = cam->dir.x; float theta = cam->dir.y; float sin_phi = Fast_Sin(phi); float cos_phi = Fast_Cos(theta); float sin_theta = Fast_Sin(theta); float cos_theta = Fast_Cos(theta); cam->target.x = -1 * sin_phi * sin_theta; cam->target.y = 1 * cos_phi; cam->target.z = 1 * sin_phi * cos_theta; } VECTOR4D_Build(&cam->pos, &cam->target, &cam->n); VECTOR4D_INITXYZ(&cam->v, 0, 1, 0); VECTOR4D_Cross(&cam->v, &cam->n, &cam->u); VECTOR4D_Cross(&cam->n, &cam->u, &cam->v); VECTOR4D_Normalize(&cam->u); VECTOR4D_Normalize(&cam->v); VECTOR4D_Normalize(&cam->n); Mat_Init_4X4(&mt_uvn, cam->u.x, cam->v.x, cam->n.x, 0, cam->u.y, cam->v.y, cam->n.y, 0, cam->u.z, cam->v.z, cam->n.z, 0, 0, 0, 0, 1); Mat_Mul_4X4(&mt_inv, &mt_uvn, &cam->mcam); }
int Prepare_OBJECT4DV2_For_MD2(OBJECT4DV2_PTR obj, /* pointer to destination object */ MD2_CONTAINER_PTR obj_md2) /* md2 * object * to * extract * frame * from * */ { /* * this function prepares the OBJECT4DV2 to be used as a vessel to hold ; * frames from the md2 container, it allocated the memory needed, set fields ; * and pre-computes as much as possible since each new frame will change only ; * the vertex list */ Write_Error("\nPreparing MD2_CONTAINER_PTR %x for OBJECT4DV2_PTR %x", obj_md2, obj); /* clear out the object and initialize it a bit */ memset(obj, 0, sizeof(OBJECT4DV2)); /* set state of object to active and visible */ obj->state = OBJECT4DV2_STATE_ACTIVE | OBJECT4DV2_STATE_VISIBLE; /* set some information in object */ obj->num_frames = 1; /* always set to 1 */ obj->curr_frame = 0; obj->attr = OBJECT4DV2_ATTR_SINGLE_FRAME | OBJECT4DV2_ATTR_TEXTURES; obj->num_vertices = obj_md2->num_verts; obj->num_polys = obj_md2->num_polys; obj->texture = obj_md2->skin; /* set position of object */ obj->world_pos = obj_md2->world_pos; /* * allocate the memory for the vertices and number of polys ; * the call parameters are redundant in this case, but who cares */ if(!Init_OBJECT4DV2(obj, obj->num_vertices, obj->num_polys, obj->num_frames)) { Write_Error("\n(can't allocate memory)."); } /* end if */ /* * compute average and max radius using the vertices from frame 0, this isn't ; * totally accurate, but the volume of the object hopefully does vary wildly ; * during animation ; * reset incase there's any residu */ obj->avg_radius[0] = 0; obj->max_radius[0] = 0; /* loop thru and compute radius */ for(int vindex = 0; vindex < obj_md2->num_verts; vindex++) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* update the average and maximum radius (use frame 0) */ float dist_to_vertex = sqrt ( obj_md2->vlist[vindex].x * obj_md2->vlist[vindex].x + obj_md2->vlist[vindex].y * obj_md2->vlist[vindex].y + obj_md2->vlist[vindex].z * obj_md2->vlist[vindex].z ); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* accumulate total radius */ obj->avg_radius[0] += dist_to_vertex; /* update maximum radius */ if(dist_to_vertex > obj->max_radius[0]) obj->max_radius[0] = dist_to_vertex; } /* end for vertex */ /* finallize average radius computation */ obj->avg_radius[0] /= obj->num_vertices; Write_Error("\nMax radius=%f, Avg. Radius=%f", obj->max_radius[0], obj->avg_radius[0]); Write_Error("\nWriting texture coordinates..."); /* copy texture coordinate list always the same */ for(int tindex = 0; tindex < obj_md2->num_textcoords; tindex++) { /* now texture coordinates */ obj->tlist[tindex].x = obj_md2->tlist[tindex].x; obj->tlist[tindex].y = obj_md2->tlist[tindex].y; } /* end for tindex */ Write_Error("\nWriting polygons..."); /* generate the polygon index list, always the same */ for(int pindex = 0; pindex < obj_md2->num_polys; pindex++) { /* set polygon indices */ obj->plist[pindex].vert[0] = obj_md2->polys[pindex].vindex[0]; obj->plist[pindex].vert[1] = obj_md2->polys[pindex].vindex[1]; obj->plist[pindex].vert[2] = obj_md2->polys[pindex].vindex[2]; /* * point polygon vertex list to object's vertex list ; * note that this is redundant since the polylist is contained ; * within the object in this case and its up to the user to select ; * whether the local or transformed vertex list is used when building up ; * polygon geometry, might be a better idea to set to NULL in the context ; * of polygons that are part of an object */ obj->plist[pindex].vlist = obj->vlist_local; /* set attributes of polygon with sent attributes */ obj->plist[pindex].attr = obj_md2->attr; /* set color of polygon */ obj->plist[pindex].color = obj_md2->color; /* apply texture to this polygon */ obj->plist[pindex].texture = obj_md2->skin; /* assign the texture coordinates */ obj->plist[pindex].text[0] = obj_md2->polys[pindex].tindex[0]; obj->plist[pindex].text[1] = obj_md2->polys[pindex].tindex[1]; obj->plist[pindex].text[2] = obj_md2->polys[pindex].tindex[2]; /* set texture coordinate attributes */ SET_BIT(obj->vlist_local[obj->plist[pindex].vert[0]].attr, VERTEX4DTV1_ATTR_TEXTURE); SET_BIT(obj->vlist_local[obj->plist[pindex].vert[1]].attr, VERTEX4DTV1_ATTR_TEXTURE); SET_BIT(obj->vlist_local[obj->plist[pindex].vert[2]].attr, VERTEX4DTV1_ATTR_TEXTURE); /* set the material mode to ver. 1.0 emulation */ SET_BIT(obj->plist[pindex].attr, POLY4DV2_ATTR_DISABLE_MATERIAL); /* finally set the polygon to active */ obj->plist[pindex].state = POLY4DV2_STATE_ACTIVE; /* * point polygon vertex list to object's vertex list ; * note that this is redundant since the polylist is contained ; * within the object in this case and its up to the user to select ; * whether the local or transformed vertex list is used when building up ; * polygon geometry, might be a better idea to set to NULL in the context ; * of polygons that are part of an object */ obj->plist[pindex].vlist = obj->vlist_local; /* set texture coordinate list, this is needed */ obj->plist[pindex].tlist = obj->tlist; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* extract vertex indices */ int vindex_0 = obj_md2->polys[pindex].vindex[0]; int vindex_1 = obj_md2->polys[pindex].vindex[1]; int vindex_2 = obj_md2->polys[pindex].vindex[2]; /* * we need to compute the normal of this polygon face, and recall ; * that the vertices are in cw order, u=p0->p1, v=p0->p2, n=uxv */ VECTOR4D u, v, n; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* * build u, v ; * VECTOR4D_Build(&obj->vlist_local[ vindex_0 ].v, &obj->vlist_local[ vindex_1 * ].v, &u); * VECTOR4D_Build(&obj->vlist_local[ vindex_0 ].v, &obj->vlist_local[ vindex_2 * ].v, &v); */ u.x = obj_md2->vlist[vindex_1].x - obj_md2->vlist[vindex_0].x; u.y = obj_md2->vlist[vindex_1].y - obj_md2->vlist[vindex_0].y; u.z = obj_md2->vlist[vindex_1].z - obj_md2->vlist[vindex_0].z; u.w = 1; v.x = obj_md2->vlist[vindex_2].x - obj_md2->vlist[vindex_0].x; v.y = obj_md2->vlist[vindex_2].y - obj_md2->vlist[vindex_0].y; v.z = obj_md2->vlist[vindex_2].z - obj_md2->vlist[vindex_0].z; v.w = 1; /* compute cross product */ VECTOR4D_Cross(&u, &v, &n); /* * compute length of normal accurately and store in poly nlength ; * +- epsilon later to fix over/underflows */ obj->plist[pindex].nlength = VECTOR4D_Length(&n); } /* end for poly */ /* return success */ return(1); } /* end Prepare_OBJECT4DV2_For_MD2 */