/* * routine which allocates, reads, and inits a polymodel's model_data */ void polygon_model_data_read(polymodel *pm, PHYSFS_file *fp) { pm->model_data = d_malloc(pm->model_data_size); Assert(pm->model_data != NULL); PHYSFS_read(fp, pm->model_data, sizeof(ubyte), pm->model_data_size); #ifdef WORDS_NEED_ALIGNMENT align_polygon_model_data(pm); #endif #ifdef WORDS_BIGENDIAN swap_polygon_model_data(pm->model_data); #endif }
/* * routine which allocates, reads, and inits a polymodel's model_data */ void polygon_model_data_read(polymodel *pm, CFILE *fp) { pm->model_data = d_malloc(pm->model_data_size); Assert(pm->model_data != NULL); cfread(pm->model_data, sizeof(ubyte), pm->model_data_size, fp ); #ifdef WORDS_NEED_ALIGNMENT align_polygon_model_data(pm); #endif #ifdef WORDS_BIGENDIAN swap_polygon_model_data(pm->model_data); #endif //verify(pm->model_data); g3_init_polygon_model(pm->model_data); }
void swap_polygon_model_data(ubyte *data) { int i; short n; g3s_uvl *uvl_val; ubyte *p = data; short_swap(wp(p)); while (w(p) != OP_EOF) { switch (w(p)) { case OP_DEFPOINTS: short_swap(wp(p + 2)); n = w(p+2); for (i = 0; i < n; i++) vms_vector_swap(vp((p + 4) + (i * sizeof(vms_vector)))); p += n*sizeof(struct vms_vector) + 4; break; case OP_DEFP_START: short_swap(wp(p + 2)); short_swap(wp(p + 4)); n = w(p+2); for (i = 0; i < n; i++) vms_vector_swap(vp((p + 8) + (i * sizeof(vms_vector)))); p += n*sizeof(struct vms_vector) + 8; break; case OP_FLATPOLY: short_swap(wp(p+2)); n = w(p+2); vms_vector_swap(vp(p + 4)); vms_vector_swap(vp(p + 16)); short_swap(wp(p+28)); for (i=0; i < n; i++) short_swap(wp(p + 30 + (i * 2))); p += 30 + ((n&~1)+1)*2; break; case OP_TMAPPOLY: short_swap(wp(p+2)); n = w(p+2); vms_vector_swap(vp(p + 4)); vms_vector_swap(vp(p + 16)); for (i=0;i<n;i++) { uvl_val = (g3s_uvl *)((p+30+((n&~1)+1)*2) + (i * sizeof(g3s_uvl))); fix_swap(&uvl_val->u); fix_swap(&uvl_val->v); } short_swap(wp(p+28)); for (i=0;i<n;i++) short_swap(wp(p + 30 + (i * 2))); p += 30 + ((n&~1)+1)*2 + n*12; break; case OP_SORTNORM: vms_vector_swap(vp(p + 4)); vms_vector_swap(vp(p + 16)); short_swap(wp(p + 28)); short_swap(wp(p + 30)); swap_polygon_model_data(p + w(p+28)); swap_polygon_model_data(p + w(p+30)); p += 32; break; case OP_RODBM: vms_vector_swap(vp(p + 20)); vms_vector_swap(vp(p + 4)); short_swap(wp(p+2)); fix_swap(fp(p + 16)); fix_swap(fp(p + 32)); p+=36; break; case OP_SUBCALL: short_swap(wp(p+2)); vms_vector_swap(vp(p+4)); short_swap(wp(p+16)); swap_polygon_model_data(p + w(p+16)); p += 20; break; case OP_GLOW: short_swap(wp(p + 2)); p += 4; break; default: Error("invalid polygon model\n"); //Int3(); } short_swap(wp(p)); } }
void swap_polygon_model_data(ubyte *data) { int i; short n; g3s_uvl *uvl_val; ubyte *p = data; short_swap(wp(p)); while (w(p) != OP_EOF) { switch (w(p)) { case OP_DEFPOINTS: short_swap(wp(p + 2)); n = w(p + 2); for (i = 0; i < n; i++) vms_vector_swap(vp((p + 4) + (i * sizeof(vms_vector)))); p += n*sizeof(struct vms_vector) + 4; break; case OP_DEFP_START: short_swap(wp(p + 2)); short_swap(wp(p + 4)); n = w(p + 2); for (i = 0; i < n; i++) vms_vector_swap(vp((p + 8) + (i * sizeof(vms_vector)))); p += n*sizeof(struct vms_vector) + 8; break; case OP_FLATPOLY: short_swap(wp(p + 2)); n = w(p + 2); vms_vector_swap(vp(p + 4)); vms_vector_swap(vp(p + 16)); short_swap(wp(p + 28)); // swap the colors 0 and 255 here!!!! if (w(p + 28) == 0) w(p + 28) = 255; else if (w(p + 28) == 255) w(p + 28) = 0; for (i = 0; i < n; i++) short_swap(wp(p + 30 + (i * 2))); p += 30 + ((n&~1) + 1) * 2; break; case OP_TMAPPOLY: short_swap(wp(p + 2)); n = w(p + 2); vms_vector_swap(vp(p + 4)); vms_vector_swap(vp(p + 16)); for (i = 0; i<n; i++) { uvl_val = (g3s_uvl *)((p + 30 + ((n&~1) + 1) * 2) + (i * sizeof(g3s_uvl))); uvl_val->u = (fix)swapint((int)uvl_val->u); uvl_val->v = (fix)swapint((int)uvl_val->v); } short_swap(wp(p + 28)); for (i = 0; i<n; i++) short_swap(wp(p + 30 + (i * 2))); p += 30 + ((n&~1) + 1) * 2 + n * 12; break; case OP_SORTNORM: vms_vector_swap(vp(p + 4)); vms_vector_swap(vp(p + 16)); short_swap(wp(p + 28)); short_swap(wp(p + 30)); swap_polygon_model_data(p + w(p + 28)); swap_polygon_model_data(p + w(p + 30)); p += 32; break; case OP_RODBM: vms_vector_swap(vp(p + 20)); vms_vector_swap(vp(p + 4)); short_swap(wp(p + 2)); *((int *)(p + 16)) = swapint(*((int *)(p + 16))); *((int *)(p + 32)) = swapint(*((int *)(p + 32))); p += 36; break; case OP_SUBCALL: short_swap(wp(p + 2)); vms_vector_swap(vp(p + 4)); short_swap(wp(p + 16)); swap_polygon_model_data(p + w(p + 16)); p += 20; break; case OP_GLOW: short_swap(wp(p + 2)); p += 4; break; default: Int3(); } short_swap(wp(p)); } }
//reads a binary file containing a 3d model polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r) { PHYSFS_file *ifile; short version; int id,len, next_chunk; ubyte model_buf[MODEL_BUF_SIZE]; if ((ifile=PHYSFSX_openReadBuffered(filename))==NULL) Error("Can't open file <%s>",filename); Assert(PHYSFS_fileLength(ifile) <= MODEL_BUF_SIZE); Pof_addr = 0; Pof_file_end = PHYSFS_read(ifile, model_buf, 1, PHYSFS_fileLength(ifile)); PHYSFS_close(ifile); id = pof_read_int(model_buf); if (id!=0x4f505350) /* 'OPSP' */ Error("Bad ID in model file <%s>",filename); version = pof_read_short(model_buf); if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION) Error("Bad version (%d) in model file <%s>",version,filename); while (new_pof_read_int(id,model_buf) == 1) { id = INTEL_INT(id); //id = pof_read_int(model_buf); len = pof_read_int(model_buf); next_chunk = Pof_addr + len; switch (id) { case ID_OHDR: { //Object header vms_vector pmmin,pmmax; pm->n_models = pof_read_int(model_buf); pm->rad = pof_read_int(model_buf); Assert(pm->n_models <= MAX_SUBMODELS); pof_read_vecs(&pmmin,1,model_buf); pof_read_vecs(&pmmax,1,model_buf); break; } case ID_SOBJ: { //Subobject header int n; n = pof_read_short(model_buf); Assert(n < MAX_SUBMODELS); pm->submodel_parents[n] = pof_read_short(model_buf); pof_read_vecs(&pm->submodel_norms[n],1,model_buf); pof_read_vecs(&pm->submodel_pnts[n],1,model_buf); pof_read_vecs(&pm->submodel_offsets[n],1,model_buf); pm->submodel_rads[n] = pof_read_int(model_buf); //radius pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset break; } #ifndef DRIVE case ID_GUNS: { //List of guns on this object if (r) { int i; vms_vector gun_dir; r->n_guns = pof_read_int(model_buf); Assert(r->n_guns <= MAX_GUNS); for (i=0;i<r->n_guns;i++) { int id; id = pof_read_short(model_buf); r->gun_submodels[id] = pof_read_short(model_buf); Assert(r->gun_submodels[id] != 0xff); pof_read_vecs(&r->gun_points[id],1,model_buf); if (version >= 7) pof_read_vecs(&gun_dir,1,model_buf); } } else pof_cfseek(model_buf,len,SEEK_CUR); break; } case ID_ANIM: //Animation data if (r) { int n_frames,f,m; n_frames = pof_read_short(model_buf); Assert(n_frames == N_ANIM_STATES); for (m=0;m<pm->n_models;m++) for (f=0;f<n_frames;f++) pof_read_angvecs(&anim_angs[f][m], 1, model_buf); robot_set_angles(r,pm,anim_angs); } else pof_cfseek(model_buf,len,SEEK_CUR); break; #endif case ID_TXTR: { //Texture filename list int n; char name_buf[128]; n = pof_read_short(model_buf); while (n--) { pof_read_string(name_buf,128,model_buf); } break; } case ID_IDTA: //Interpreter data pm->model_data = d_malloc(len); pm->model_data_size = len; pof_cfread(pm->model_data,1,len,model_buf); break; default: pof_cfseek(model_buf,len,SEEK_CUR); break; } if ( version >= 8 ) // Version 8 needs 4-byte alignment!!! pof_cfseek(model_buf,next_chunk,SEEK_SET); } #ifdef WORDS_NEED_ALIGNMENT align_polygon_model_data(pm); #endif #ifdef WORDS_BIGENDIAN swap_polygon_model_data(pm->model_data); #endif return pm; }
//reads a binary file containing a 3d model polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r) { CFILE *ifile; short version; int id,len, next_chunk; int anim_flag = 0; ubyte *model_buf; model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) ); if (!model_buf) Error("Can't allocate space to read model %s\n", filename); if ((ifile=cfopen(filename,"rb"))==NULL) Error("Can't open file <%s>",filename); Assert(ifile->size <= MODEL_BUF_SIZE); Pof_addr = 0; Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile); cfclose(ifile); id = pof_read_int(model_buf); if (id!=0x4f505350) /* 'OPSP' */ Error("Bad ID in model file <%s>",filename); version = pof_read_short(model_buf); if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION) Error("Bad version (%d) in model file <%s>",version,filename); if ( FindArg( "-bspgen" )) printf( "bspgen -c1" ); while (new_pof_read_int(id,model_buf) == 1) { id = INTEL_INT(id); //id = pof_read_int(model_buf); len = pof_read_int(model_buf); next_chunk = Pof_addr + len; switch (id) { case ID_OHDR: { //Object header vms_vector pmmin,pmmax; //con_printf(DEBUG_LEVEL, "Got chunk OHDR, len=%d\n",len); pm->n_models = pof_read_int(model_buf); pm->rad = pof_read_int(model_buf); Assert(pm->n_models <= MAX_SUBMODELS); pof_read_vecs(&pmmin,1,model_buf); pof_read_vecs(&pmmax,1,model_buf); if ( FindArg( "-bspgen" )) { vms_vector v; fix l; vm_vec_sub(&v, &pmmax, &pmmin ); l = v.x; if ( v.y > l ) l = v.y; if ( v.z > l ) l = v.z; printf( " -l%.3f", f2fl(l) ); } break; } case ID_SOBJ: { //Subobject header int n; anim_flag++; //con_printf(DEBUG_LEVEL, "Got chunk SOBJ, len=%d\n",len); n = pof_read_short(model_buf); Assert(n < MAX_SUBMODELS); pm->submodel_parents[n] = pof_read_short(model_buf); pof_read_vecs(&pm->submodel_norms[n],1,model_buf); pof_read_vecs(&pm->submodel_pnts[n],1,model_buf); pof_read_vecs(&pm->submodel_offsets[n],1,model_buf); pm->submodel_rads[n] = pof_read_int(model_buf); //radius pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset break; } #ifndef DRIVE case ID_GUNS: { //List of guns on this object //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len); if (r) { int i; vms_vector gun_dir; ubyte gun_used[MAX_GUNS]; r->n_guns = pof_read_int(model_buf); if ( r->n_guns ) anim_flag++; Assert(r->n_guns <= MAX_GUNS); for (i=0;i<r->n_guns;i++) gun_used[i] = 0; for (i=0;i<r->n_guns;i++) { int id; id = pof_read_short(model_buf); Assert(id < r->n_guns); Assert(gun_used[id] == 0); gun_used[id] = 1; r->gun_submodels[id] = pof_read_short(model_buf); Assert(r->gun_submodels[id] != 0xff); pof_read_vecs(&r->gun_points[id],1,model_buf); if (version >= 7) pof_read_vecs(&gun_dir,1,model_buf); } } else pof_cfseek(model_buf,len,SEEK_CUR); break; } case ID_ANIM: //Animation data //con_printf(DEBUG_LEVEL, "Got chunk ANIM, len=%d\n",len); anim_flag++; if (r) { int n_frames,f,m; n_frames = pof_read_short(model_buf); Assert(n_frames == N_ANIM_STATES); for (m=0;m<pm->n_models;m++) for (f=0;f<n_frames;f++) pof_read_angs(&anim_angs[f][m], 1, model_buf); robot_set_angles(r,pm,anim_angs); } else pof_cfseek(model_buf,len,SEEK_CUR); break; #endif case ID_TXTR: { //Texture filename list int n; char name_buf[128]; //con_printf(DEBUG_LEVEL, "Got chunk TXTR, len=%d\n",len); n = pof_read_short(model_buf); //con_printf(DEBUG_LEVEL, " num textures = %d\n",n); while (n--) { pof_read_string(name_buf,128,model_buf); //con_printf(DEBUG_LEVEL, "<%s>\n",name_buf); } break; } case ID_IDTA: //Interpreter data //con_printf(DEBUG_LEVEL, "Got chunk IDTA, len=%d\n",len); pm->model_data = d_malloc(len); pm->model_data_size = len; pof_cfread(pm->model_data,1,len,model_buf); break; default: //con_printf(DEBUG_LEVEL, "Unknown chunk <%c%c%c%c>, len = %d\n",id,id>>8,id>>16,id>>24,len); pof_cfseek(model_buf,len,SEEK_CUR); break; } if ( version >= 8 ) // Version 8 needs 4-byte alignment!!! pof_cfseek(model_buf,next_chunk,SEEK_SET); } // for (i=0;i<pm->n_models;i++) // pm->submodel_ptrs[i] += (int) pm->model_data; if ( FindArg( "-bspgen" )) { char *p = strchr( filename, '.' ); *p = 0; if ( anim_flag > 1 ) printf( " -a" ); printf( " %s.3ds\n", filename ); *p = '.'; } d_free(model_buf); #ifdef WORDS_NEED_ALIGNMENT align_polygon_model_data(pm); #endif #ifdef WORDS_BIGENDIAN swap_polygon_model_data(pm->model_data); #endif //verify(pm->model_data); return pm; }