//reads the gun information for a model //fills in arrays gun_points & gun_dirs, returns the number of guns read int read_model_guns(char *filename,vms_vector *gun_points, vms_vector *gun_dirs, int *gun_submodels) { PHYSFS_file *ifile; short version; int id,len; int n_guns=0; 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); Assert(version >= 7); //must be 7 or higher for this data 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); if (id == ID_GUNS) { //List of guns on this object int i; n_guns = pof_read_int(model_buf); for (i=0;i<n_guns;i++) { int id,sm; id = pof_read_short(model_buf); sm = pof_read_short(model_buf); if (gun_submodels) gun_submodels[id] = sm; else if (sm!=0) Error("Invalid gun submodel in file <%s>",filename); pof_read_vecs(&gun_points[id],1,model_buf); pof_read_vecs(&gun_dirs[id],1,model_buf); } } else pof_cfseek(model_buf,len,SEEK_CUR); } return n_guns; }
//reads a binary file containing a 3d model static polymodel *read_model_file(polymodel *pm,const char *filename,robot_info *r) { short version; int len, next_chunk; ubyte model_buf[MODEL_BUF_SIZE]; auto ifile = PHYSFSX_openReadBuffered(filename); if (!ifile) 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)); ifile.reset(); const int model_id = pof_read_int(model_buf); if (model_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); int pof_id; while (new_pof_read_int(pof_id, model_buf) == 1) { pof_id = INTEL_INT(pof_id); //id = pof_read_int(model_buf); len = pof_read_int(model_buf); next_chunk = Pof_addr + len; switch (pof_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) { vms_vector gun_dir; r->n_guns = pof_read_int(model_buf); Assert(r->n_guns <= MAX_GUNS); for (int i=0;i<r->n_guns;i++) { const uint_fast32_t gun_id = pof_read_short(model_buf); /* * D1 v1.0 boss02.pof has id=4 and r->n_guns==4. * Relax the assert to check only for memory * corruption. */ Assert(gun_id < sizeof(r->gun_submodels) / sizeof(r->gun_submodels[0])); auto &submodel = r->gun_submodels[gun_id]; submodel = pof_read_short(model_buf); Assert(submodel != 0xff); pof_read_vecs(&r->gun_points[gun_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) { unsigned n_frames; n_frames = pof_read_short(model_buf); Assert(n_frames == N_ANIM_STATES); for (int m=0;m<pm->n_models;m++) range_for (auto &f, partial_range(anim_angs, n_frames)) pof_read_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_size = len; pm->model_data = make_unique<ubyte[]>(pm->model_data_size); pof_cfread(pm->model_data.get(),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); }
//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 the gun information for a model //fills in arrays gun_points & gun_dirs, returns the number of guns read int read_model_guns(char *filename,vms_vector *gun_points, vms_vector *gun_dirs, int *gun_submodels) { CFILE *ifile; short version; int id,len; int n_guns=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, ifile->size, 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); Assert(version >= 7); //must be 7 or higher for this data 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); if (id == ID_GUNS) { //List of guns on this object //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len); int i; n_guns = pof_read_int(model_buf); for (i=0;i<n_guns;i++) { int id,sm; id = pof_read_short(model_buf); sm = pof_read_short(model_buf); if (gun_submodels) gun_submodels[id] = sm; else if (sm!=0) Error("Invalid gun submodel in file <%s>",filename); pof_read_vecs(&gun_points[id],1,model_buf); pof_read_vecs(&gun_dirs[id],1,model_buf); } } else pof_cfseek(model_buf,len,SEEK_CUR); } d_free(model_buf); return n_guns; }
//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; }
//------------------------------------------------------------------------------ //reads a binary file containing a 3d model polymodel *ReadModelFile (polymodel *pm, char *filename, robot_info *r) { CFILE *ifile; short version; int id, len, next_chunk; int anim_flag = 0; ubyte *model_buf; if (!(model_buf = (ubyte *)d_malloc (MODEL_BUF_SIZE * sizeof (ubyte)))) Error ("Can't allocate space to read model %s\n", filename); if (!(ifile=CFOpen (filename, gameFolders.szDataDir, "rb", 0))) Error ("Can't open file <%s>", filename); Assert (CFLength (ifile, 0) <= MODEL_BUF_SIZE); Pof_addr = 0; Pof_file_end = (int) CFRead (model_buf, 1, CFLength (ifile, 0), 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; 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; VmVecSub (&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 = pof_read_short (model_buf); Assert (n < MAX_SUBMODELS); anim_flag++; pm->submodel_parents [n] = (char) 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; 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 = pof_read_short (model_buf); Assert (id < r->n_guns); Assert (gun_used [id] == 0); gun_used [id] = 1; r->gun_submodels [id] = (char) 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 anim_flag++; if (r) { int 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 char name_buf [128]; int 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); } // 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 G3AlignPolyModelData (pm); #endif #if defined (WORDS_BIGENDIAN) || defined (__BIG_ENDIAN__) G3SwapPolyModelData (pm->model_data); #endif //verify (pm->model_data); return pm; }
//------------------------------------------------------------------------------ //reads the gun information for a model //fills in arrays gunPoints & gun_dirs, returns the number of guns read int read_model_guns (char *filename, vmsVector *gunPoints, vmsVector *gun_dirs, int *gunSubModels) { CFILE *ifile; short version; int id, len; int nGuns=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, gameFolders.szDataDir, "rb", 0))==NULL) Error ("Can't open file <%s>", filename); Assert (CFLength (ifile, 0) <= MODEL_BUF_SIZE); Pof_addr = 0; Pof_file_end = (int) CFRead (model_buf, 1, CFLength (ifile, 0), 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); Assert (version >= 7); //must be 7 or higher for this data 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); if (id == ID_GUNS) { //List of guns on this tObject int i; nGuns = pof_read_int (model_buf); for (i=0;i<nGuns;i++) { int id, sm; id = pof_read_short (model_buf); sm = pof_read_short (model_buf); if (gunSubModels) gunSubModels [id] = sm; else if (sm!=0) Error ("Invalid gun submodel in file <%s>", filename); pof_read_vecs (&gunPoints [id], 1, model_buf); pof_read_vecs (&gun_dirs [id], 1, model_buf); } } else pof_CFSeek (model_buf, len, SEEK_CUR); } d_free (model_buf); return nGuns; }