1 /* $Id: polyobj.c,v 1.22 2005-07-30 07:46:03 chris Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Hacked-in polygon objects
27 static char rcsid[] = "$Id: polyobj.c,v 1.22 2005-07-30 07:46:03 chris Exp $";
34 // -- I hate this warning in make depend! -- #ifdef DRIVE
35 // -- I hate this warning in make depend! -- #include "drive.h"
36 // -- I hate this warning in make depend! -- #else
38 // -- I hate this warning in make depend! -- #endif
64 polymodel Polygon_models[MAX_POLYGON_MODELS]; // = {&bot11,&bot17,&robot_s2,&robot_b2,&bot11,&bot17,&robot_s2,&robot_b2};
66 int D1Share_Polymodel_map[] = {
72 108, 109, 110, 111, 112,
73 113, 114, 115, 116, 117,
74 118, 119, 120, 121, 122,
75 123, 124, 125, 126, 127,
76 128, 129, 130, 133, 134,
77 136, 137, 138, 139, 140,
86 int D1_Polymodel_map[] = {
96 110, 111, 112, 113, 114,
97 115, 116, 117, 118, 119,
98 120, 121, 122, 123, 124,
99 125, 126, 127, 128, 129,
100 130, 131, 132, 133, 134,
101 135, 136, 137, 138, 139,
102 140, 141, 142, -1, -1,
106 int D2Demo_Polymodel_map[] = {
111 97, 98, 107, 108, 109,
112 110, -1, -1, 111, 112,
113 113, 114, 115, 116, 117,
114 118, 119, 120, 121, 122,
115 123, 124, 125, 126, 127,
116 128, 129, 130, 133, 134,
117 136, 137, 138, 139, 140,
118 141, 143, 144, 145, 146,
119 147, 148, 149, 150, 151,
120 152, 155, 156, 157, 158,
126 int N_polygon_models = 0;
128 #define MAX_POLYGON_VECS 1000
129 g3s_point robot_points[MAX_POLYGON_VECS];
131 #define PM_COMPATIBLE_VERSION 6
132 #define PM_OBJFILE_VERSION 8
137 #define MODEL_BUF_SIZE 32768
139 void _pof_cfseek(int len,int type)
142 case SEEK_SET: Pof_addr = len; break;
143 case SEEK_CUR: Pof_addr += len; break;
145 Assert(len <= 0); // seeking from end, better be moving back.
146 Pof_addr = Pof_file_end + len;
150 if (Pof_addr > MODEL_BUF_SIZE)
154 #define pof_cfseek(_buf,_len,_type) _pof_cfseek((_len),(_type))
156 int pof_read_int(ubyte *bufp)
160 i = *((int *) &bufp[Pof_addr]);
164 // if (cfread(&i,sizeof(i),1,f) != 1)
165 // Error("Unexpected end-of-file while reading object");
170 size_t pof_cfread(void *dst, size_t elsize, size_t nelem, ubyte *bufp)
172 if (Pof_addr + nelem*elsize > Pof_file_end)
175 memcpy(dst, &bufp[Pof_addr], elsize*nelem);
177 Pof_addr += elsize*nelem;
179 if (Pof_addr > MODEL_BUF_SIZE)
185 // #define new_read_int(i,f) cfread(&(i),sizeof(i),1,(f))
186 #define new_pof_read_int(i,f) pof_cfread(&(i),sizeof(i),1,(f))
188 short pof_read_short(ubyte *bufp)
192 s = *((short *) &bufp[Pof_addr]);
194 return INTEL_SHORT(s);
195 // if (cfread(&s,sizeof(s),1,f) != 1)
196 // Error("Unexpected end-of-file while reading object");
201 void pof_read_string(char *buf,int max_char, ubyte *bufp)
205 for (i=0; i<max_char; i++) {
206 if ((*buf++ = bufp[Pof_addr++]) == 0)
210 // while (max_char-- && (*buf=cfgetc(f)) != 0) buf++;
214 void pof_read_vecs(vms_vector *vecs,int n,ubyte *bufp)
216 // cfread(vecs,sizeof(vms_vector),n,f);
218 memcpy(vecs, &bufp[Pof_addr], n*sizeof(*vecs));
219 Pof_addr += n*sizeof(*vecs);
221 #ifdef WORDS_BIGENDIAN
223 vms_vector_swap(&vecs[--n]);
226 if (Pof_addr > MODEL_BUF_SIZE)
230 void pof_read_angs(vms_angvec *angs,int n,ubyte *bufp)
232 memcpy(angs, &bufp[Pof_addr], n*sizeof(*angs));
233 Pof_addr += n*sizeof(*angs);
235 #ifdef WORDS_BIGENDIAN
237 vms_angvec_swap(&angs[--n]);
240 if (Pof_addr > MODEL_BUF_SIZE)
244 #define ID_OHDR 0x5244484f // 'RDHO' //Object header
245 #define ID_SOBJ 0x4a424f53 // 'JBOS' //Subobject header
246 #define ID_GUNS 0x534e5547 // 'SNUG' //List of guns on this object
247 #define ID_ANIM 0x4d494e41 // 'MINA' //Animation data
248 #define ID_IDTA 0x41544449 // 'ATDI' //Interpreter data
249 #define ID_TXTR 0x52545854 // 'RTXT' //Texture filename list
252 #define robot_info void
254 vms_angvec anim_angs[N_ANIM_STATES][MAX_SUBMODELS];
256 //set the animation angles for this robot. Gun fields of robot info must
258 void robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS]);
261 #define DEBUG_LEVEL CON_NORMAL
263 #ifdef WORDS_NEED_ALIGNMENT
264 ubyte * old_dest(chunk o) // return where chunk is (in unaligned struct)
266 return o.old_base + INTEL_SHORT(*((short *)(o.old_base + o.offset)));
268 ubyte * new_dest(chunk o) // return where chunk is (in aligned struct)
270 return o.new_base + INTEL_SHORT(*((short *)(o.old_base + o.offset))) + o.correction;
273 * find chunk with smallest address
275 int get_first_chunks_index(chunk *chunk_list, int no_chunks)
277 int i, first_index = 0;
278 Assert(no_chunks >= 1);
279 for (i = 1; i < no_chunks; i++)
280 if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index]))
284 #define SHIFT_SPACE 500 // increase if insufficent
286 void align_polygon_model_data(polymodel *pm)
289 int total_correction = 0;
290 ubyte *cur_old, *cur_new;
292 chunk ch_list[MAX_CHUNKS];
294 int tmp_size = pm->model_data_size + SHIFT_SPACE;
295 ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data
298 //start with first chunk (is always aligned!)
299 cur_old = pm->model_data;
301 chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
302 memcpy(cur_new, cur_old, chunk_len);
303 while (no_chunks > 0) {
304 int first_index = get_first_chunks_index(ch_list, no_chunks);
305 cur_ch = ch_list[first_index];
306 // remove first chunk from array:
308 for (i = first_index; i < no_chunks; i++)
309 ch_list[i] = ch_list[i + 1];
310 // if (new) address unaligned:
311 if ((u_int32_t)new_dest(cur_ch) % 4L != 0) {
312 // calculate how much to move to be aligned
313 short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L;
314 // correct chunks' addresses
315 cur_ch.correction += to_shift;
316 for (i = 0; i < no_chunks; i++)
317 ch_list[i].correction += to_shift;
318 total_correction += to_shift;
319 Assert((u_int32_t)new_dest(cur_ch) % 4L == 0);
320 Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE
322 //write (corrected) chunk for current chunk:
323 *((short *)(cur_ch.new_base + cur_ch.offset))
324 = INTEL_SHORT(cur_ch.correction
325 + INTEL_SHORT(*((short *)(cur_ch.old_base + cur_ch.offset))));
326 //write (correctly aligned) chunk:
327 cur_old = old_dest(cur_ch);
328 cur_new = new_dest(cur_ch);
329 chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
330 memcpy(cur_new, cur_old, chunk_len);
331 //correct submodel_ptr's for pm, too
332 for (i = 0; i < MAX_SUBMODELS; i++)
333 if (pm->model_data + pm->submodel_ptrs[i] >= cur_old
334 && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len)
335 pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data);
337 d_free(pm->model_data);
338 pm->model_data_size += total_correction;
339 pm->model_data = d_malloc(pm->model_data_size);
340 Assert(pm->model_data != NULL);
341 memcpy(pm->model_data, tmp, pm->model_data_size);
344 #endif //def WORDS_NEED_ALIGNMENT
346 //reads a binary file containing a 3d model
347 polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r)
351 int id,len, next_chunk;
355 model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) );
357 Error("Can't allocate space to read model %s\n", filename);
359 if ((ifile=cfopen(filename,"rb"))==NULL)
360 Error("Can't open file <%s>",filename);
362 Assert(cfilelength(ifile) <= MODEL_BUF_SIZE);
365 Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
368 id = pof_read_int(model_buf);
370 if (id!=0x4f505350) /* 'OPSP' */
371 Error("Bad ID in model file <%s>",filename);
373 version = pof_read_short(model_buf);
375 if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
376 Error("Bad version (%d) in model file <%s>",version,filename);
378 if ( FindArg( "-bspgen" ))
379 printf( "bspgen -c1" );
381 while (new_pof_read_int(id,model_buf) == 1) {
383 //id = pof_read_int(model_buf);
384 len = pof_read_int(model_buf);
385 next_chunk = Pof_addr + len;
389 case ID_OHDR: { //Object header
390 vms_vector pmmin,pmmax;
392 //con_printf(DEBUG_LEVEL, "Got chunk OHDR, len=%d\n",len);
394 pm->n_models = pof_read_int(model_buf);
395 pm->rad = pof_read_int(model_buf);
397 Assert(pm->n_models <= MAX_SUBMODELS);
399 pof_read_vecs(&pmmin,1,model_buf);
400 pof_read_vecs(&pmmax,1,model_buf);
402 if ( FindArg( "-bspgen" )) {
406 vm_vec_sub(&v, &pmmax, &pmmin );
408 if ( v.y > l ) l = v.y;
409 if ( v.z > l ) l = v.z;
411 printf( " -l%.3f", f2fl(l) );
417 case ID_SOBJ: { //Subobject header
422 //con_printf(DEBUG_LEVEL, "Got chunk SOBJ, len=%d\n",len);
424 n = pof_read_short(model_buf);
426 Assert(n < MAX_SUBMODELS);
428 pm->submodel_parents[n] = pof_read_short(model_buf);
430 pof_read_vecs(&pm->submodel_norms[n],1,model_buf);
431 pof_read_vecs(&pm->submodel_pnts[n],1,model_buf);
432 pof_read_vecs(&pm->submodel_offsets[n],1,model_buf);
434 pm->submodel_rads[n] = pof_read_int(model_buf); //radius
436 pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset
443 case ID_GUNS: { //List of guns on this object
445 //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len);
450 ubyte gun_used[MAX_GUNS];
452 r->n_guns = pof_read_int(model_buf);
457 Assert(r->n_guns <= MAX_GUNS);
459 for (i=0;i<r->n_guns;i++)
462 for (i=0;i<r->n_guns;i++) {
465 id = pof_read_short(model_buf);
466 Assert(id < r->n_guns);
467 Assert(gun_used[id] == 0);
469 r->gun_submodels[id] = pof_read_short(model_buf);
470 Assert(r->gun_submodels[id] != 0xff);
471 pof_read_vecs(&r->gun_points[id],1,model_buf);
474 pof_read_vecs(&gun_dir,1,model_buf);
478 pof_cfseek(model_buf,len,SEEK_CUR);
483 case ID_ANIM: //Animation data
484 //con_printf(DEBUG_LEVEL, "Got chunk ANIM, len=%d\n",len);
491 n_frames = pof_read_short(model_buf);
493 Assert(n_frames == N_ANIM_STATES);
495 for (m=0;m<pm->n_models;m++)
496 for (f=0;f<n_frames;f++)
497 pof_read_angs(&anim_angs[f][m], 1, model_buf);
500 robot_set_angles(r,pm,anim_angs);
504 pof_cfseek(model_buf,len,SEEK_CUR);
509 case ID_TXTR: { //Texture filename list
513 //con_printf(DEBUG_LEVEL, "Got chunk TXTR, len=%d\n",len);
515 n = pof_read_short(model_buf);
516 //con_printf(DEBUG_LEVEL, " num textures = %d\n",n);
518 pof_read_string(name_buf,128,model_buf);
519 //con_printf(DEBUG_LEVEL, "<%s>\n",name_buf);
525 case ID_IDTA: //Interpreter data
526 //con_printf(DEBUG_LEVEL, "Got chunk IDTA, len=%d\n",len);
528 pm->model_data = d_malloc(len);
529 pm->model_data_size = len;
531 pof_cfread(pm->model_data,1,len,model_buf);
536 //con_printf(DEBUG_LEVEL, "Unknown chunk <%c%c%c%c>, len = %d\n",id,id>>8,id>>16,id>>24,len);
537 pof_cfseek(model_buf,len,SEEK_CUR);
541 if ( version >= 8 ) // Version 8 needs 4-byte alignment!!!
542 pof_cfseek(model_buf,next_chunk,SEEK_SET);
545 // for (i=0;i<pm->n_models;i++)
546 // pm->submodel_ptrs[i] += (int) pm->model_data;
548 if ( FindArg( "-bspgen" )) {
549 char *p = strchr( filename, '.' );
555 printf( " %s.3ds\n", filename );
561 #ifdef WORDS_NEED_ALIGNMENT
562 align_polygon_model_data(pm);
564 #ifdef WORDS_BIGENDIAN
565 swap_polygon_model_data(pm->model_data);
567 //verify(pm->model_data);
572 //reads the gun information for a model
573 //fills in arrays gun_points & gun_dirs, returns the number of guns read
574 int read_model_guns(char *filename,vms_vector *gun_points, vms_vector *gun_dirs, int *gun_submodels)
582 model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) );
584 Error("Can't allocate space to read model %s\n", filename);
586 if ((ifile=cfopen(filename,"rb"))==NULL)
587 Error("Can't open file <%s>",filename);
589 Assert(cfilelength(ifile) <= MODEL_BUF_SIZE);
592 Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
595 id = pof_read_int(model_buf);
597 if (id!=0x4f505350) /* 'OPSP' */
598 Error("Bad ID in model file <%s>",filename);
600 version = pof_read_short(model_buf);
602 Assert(version >= 7); //must be 7 or higher for this data
604 if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
605 Error("Bad version (%d) in model file <%s>",version,filename);
607 while (new_pof_read_int(id,model_buf) == 1) {
609 //id = pof_read_int(model_buf);
610 len = pof_read_int(model_buf);
612 if (id == ID_GUNS) { //List of guns on this object
614 //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len);
618 n_guns = pof_read_int(model_buf);
620 for (i=0;i<n_guns;i++) {
623 id = pof_read_short(model_buf);
624 sm = pof_read_short(model_buf);
626 gun_submodels[id] = sm;
628 Error("Invalid gun submodel in file <%s>",filename);
629 pof_read_vecs(&gun_points[id],1,model_buf);
631 pof_read_vecs(&gun_dirs[id],1,model_buf);
636 pof_cfseek(model_buf,len,SEEK_CUR);
645 //free up a model, getting rid of all its memory
646 void free_model(polymodel *po)
648 d_free(po->model_data);
651 grs_bitmap *texture_list[MAX_POLYOBJ_TEXTURES];
652 bitmap_index texture_list_index[MAX_POLYOBJ_TEXTURES];
654 int Simple_model_threshhold_scale=5; //switch when this times radius far away
657 //draw a polygon model
659 void draw_polygon_model(vms_vector *pos,vms_matrix *orient,vms_angvec *anim_angles,int model_num,int flags,fix light,fix *glow_values,bitmap_index alt_textures[])
664 Assert(model_num < N_polygon_models);
666 po=&Polygon_models[model_num];
668 //check if should use simple model
669 if (po->simpler_model ) //must have a simpler model
670 if (flags==0) //can't switch if this is debris
671 //!!if (!alt_textures) { //alternate textures might not match
672 //alt textures might not match, but in the one case we're using this
673 //for on 11/14/94, they do match. So we leave it in.
678 depth = g3_calc_point_depth(pos); //gets 3d depth
680 while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad)
681 po = &Polygon_models[po->simpler_model-1];
686 for (i=0;i<po->n_textures;i++) {
687 texture_list_index[i] = alt_textures[i];
688 texture_list[i] = &GameBitmaps[alt_textures[i].index];
693 for (i=0;i<po->n_textures;i++) {
694 texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
695 texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index];
699 #ifdef PIGGY_USE_PAGING
700 // Make sure the textures for this object are paged in...
701 piggy_page_flushed = 0;
702 for (i=0;i<po->n_textures;i++)
703 PIGGY_PAGE_IN( texture_list_index[i] );
704 // Hmmm... cache got flushed in the middle of paging all these in,
705 // so we need to reread them all in.
706 if (piggy_page_flushed) {
707 piggy_page_flushed = 0;
708 for (i=0;i<po->n_textures;i++)
709 PIGGY_PAGE_IN( texture_list_index[i] );
711 // Make sure that they can all fit in memory.
712 Assert( piggy_page_flushed == 0 );
715 g3_start_instance_matrix(pos,orient);
717 g3_set_interp_points(robot_points);
719 if (flags == 0) //draw entire object
721 g3_draw_polygon_model(po->model_data,texture_list,anim_angles,light,glow_values);
726 for (i=0;flags;flags>>=1,i++)
730 Assert(i < po->n_models);
732 //if submodel, rotate around its center point, not pivot point
734 vm_vec_avg(&ofs,&po->submodel_mins[i],&po->submodel_maxs[i]);
736 g3_start_instance_matrix(&ofs,NULL);
738 g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]],texture_list,anim_angles,light,glow_values);
747 void free_polygon_models()
751 for (i=0;i<N_polygon_models;i++) {
752 free_model(&Polygon_models[i]);
757 void polyobj_find_min_max(polymodel *pm)
763 vms_vector *big_mn,*big_mx;
768 for (m=0;m<pm->n_models;m++) {
769 vms_vector *mn,*mx,*ofs;
771 mn = &pm->submodel_mins[m];
772 mx = &pm->submodel_maxs[m];
773 ofs= &pm->submodel_offsets[m];
775 data = (ushort *)&pm->model_data[pm->submodel_ptrs[m]];
779 Assert(type == 7 || type == 1);
784 data+=2; //skip start & pad
786 vp = (vms_vector *) data;
788 *mn = *mx = *vp++; nverts--;
791 *big_mn = *big_mx = *mn;
794 if (vp->x > mx->x) mx->x = vp->x;
795 if (vp->y > mx->y) mx->y = vp->y;
796 if (vp->z > mx->z) mx->z = vp->z;
798 if (vp->x < mn->x) mn->x = vp->x;
799 if (vp->y < mn->y) mn->y = vp->y;
800 if (vp->z < mn->z) mn->z = vp->z;
802 if (vp->x+ofs->x > big_mx->x) big_mx->x = vp->x+ofs->x;
803 if (vp->y+ofs->y > big_mx->y) big_mx->y = vp->y+ofs->y;
804 if (vp->z+ofs->z > big_mx->z) big_mx->z = vp->z+ofs->z;
806 if (vp->x+ofs->x < big_mn->x) big_mn->x = vp->x+ofs->x;
807 if (vp->y+ofs->y < big_mn->y) big_mn->y = vp->y+ofs->y;
808 if (vp->z+ofs->z < big_mn->z) big_mn->z = vp->z+ofs->z;
813 // printf("Submodel %d: (%8x,%8x) (%8x,%8x) (%8x,%8x)\n",m,mn->x,mx->x,mn->y,mx->y,mn->z,mx->z);
816 // printf("Whole model: (%8x,%8x) (%8x,%8x) (%8x,%8x)\n",big_mn->x,big_mx->x,big_mn->y,big_mx->y,big_mn->z,big_mx->z);
820 extern short highest_texture_num; //from the 3d
822 char Pof_names[MAX_POLYGON_MODELS][FILENAME_LEN];
824 //returns the number of this model
826 int load_polygon_model(char *filename,int n_textures,int first_texture,robot_info *r)
828 int load_polygon_model(char *filename,int n_textures,grs_bitmap ***textures)
835 Assert(N_polygon_models < MAX_POLYGON_MODELS);
836 Assert(n_textures < MAX_POLYOBJ_TEXTURES);
838 // MK was real tired of those useless, slow mprintfs...
839 if (N_polygon_models > MAX_POLYGON_MODELS - 10)
840 mprintf(( 0, "Used %d/%d polygon model slots\n", N_polygon_models+1, MAX_POLYGON_MODELS ));
842 Assert(strlen(filename) <= 12);
843 strcpy(Pof_names[N_polygon_models],filename);
845 read_model_file(&Polygon_models[N_polygon_models],filename,r);
847 polyobj_find_min_max(&Polygon_models[N_polygon_models]);
849 g3_init_polygon_model(Polygon_models[N_polygon_models].model_data);
851 if (highest_texture_num+1 != n_textures)
852 Error("Model <%s> references %d textures but specifies %d.",filename,highest_texture_num+1,n_textures);
854 Polygon_models[N_polygon_models].n_textures = n_textures;
855 Polygon_models[N_polygon_models].first_texture = first_texture;
856 Polygon_models[N_polygon_models].simpler_model = 0;
858 // Assert(polygon_models[N_polygon_models]!=NULL);
862 return N_polygon_models-1;
867 void init_polygon_models()
869 N_polygon_models = 0;
871 atexit((void (*)())free_polygon_models);
875 //compare against this size when figuring how far to place eye for picture
876 #define BASE_MODEL_SIZE 0x28000
878 #define DEFAULT_VIEW_DIST 0x60000
880 //draws the given model in the current canvas. The distance is set to
881 //more-or-less fill the canvas. Note that this routine actually renders
882 //into an off-screen canvas that it creates, then copies to the current
884 void draw_model_picture(int mn,vms_angvec *orient_angles)
886 vms_vector temp_pos=ZERO_VECTOR;
887 vms_matrix temp_orient = IDENTITY_MATRIX;
889 grs_canvas *save_canv = grd_curcanv,*temp_canv;
892 Assert(mn>=0 && mn<N_polygon_models);
895 ogl_start_offscreen_render(0, 0, grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h);
897 temp_canv = gr_create_canvas(save_canv->cv_bitmap.bm_w,save_canv->cv_bitmap.bm_h);
898 gr_set_current_canvas(temp_canv);
900 gr_clear_canvas( BM_XRGB(0,0,0) );
903 g3_set_view_matrix(&temp_pos,&temp_orient,0x9000);
905 if (Polygon_models[mn].rad != 0)
906 temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST,Polygon_models[mn].rad,BASE_MODEL_SIZE);
908 temp_pos.z = DEFAULT_VIEW_DIST;
910 vm_angles_2_matrix(&temp_orient, orient_angles);
912 draw_polygon_model(&temp_pos,&temp_orient,NULL,mn,0,f1_0,NULL,NULL);
917 ogl_end_offscreen_render();
919 gr_set_current_canvas(save_canv);
921 gr_bitmap(0,0,&temp_canv->cv_bitmap);
923 gr_free_canvas(temp_canv);
929 * reads a polymodel structure from a CFILE
931 extern void polymodel_read(polymodel *pm, CFILE *fp)
935 pm->n_models = cfile_read_int(fp);
936 pm->model_data_size = cfile_read_int(fp);
937 pm->model_data = (ubyte *)cfile_read_int(fp); // garbage, read it anyway just for consistency
938 for (i = 0; i < MAX_SUBMODELS; i++)
939 pm->submodel_ptrs[i] = cfile_read_int(fp);
940 for (i = 0; i < MAX_SUBMODELS; i++)
941 cfile_read_vector(&(pm->submodel_offsets[i]), fp);
942 for (i = 0; i < MAX_SUBMODELS; i++)
943 cfile_read_vector(&(pm->submodel_norms[i]), fp);
944 for (i = 0; i < MAX_SUBMODELS; i++)
945 cfile_read_vector(&(pm->submodel_pnts[i]), fp);
946 for (i = 0; i < MAX_SUBMODELS; i++)
947 pm->submodel_rads[i] = cfile_read_fix(fp);
948 cfread(pm->submodel_parents, MAX_SUBMODELS, 1, fp);
949 for (i = 0; i < MAX_SUBMODELS; i++)
950 cfile_read_vector(&(pm->submodel_mins[i]), fp);
951 for (i = 0; i < MAX_SUBMODELS; i++)
952 cfile_read_vector(&(pm->submodel_maxs[i]), fp);
953 cfile_read_vector(&(pm->mins), fp);
954 cfile_read_vector(&(pm->maxs), fp);
955 pm->rad = cfile_read_fix(fp);
956 pm->n_textures = cfile_read_byte(fp);
957 pm->first_texture = cfile_read_short(fp);
958 pm->simpler_model = cfile_read_byte(fp);
962 * reads n polymodel structs from a CFILE
964 extern int polymodel_read_n(polymodel *pm, int n, CFILE *fp)
968 for (i = 0; i < n; i++) {
969 pm[i].n_models = cfile_read_int(fp);
970 pm[i].model_data_size = cfile_read_int(fp);
971 pm->model_data = (ubyte *)cfile_read_int(fp); // garbage, read it anyway just for consistency
972 for (j = 0; j < MAX_SUBMODELS; j++)
973 pm[i].submodel_ptrs[j] = cfile_read_int(fp);
974 for (j = 0; j < MAX_SUBMODELS; j++)
975 cfile_read_vector(&(pm[i].submodel_offsets[j]), fp);
976 for (j = 0; j < MAX_SUBMODELS; j++)
977 cfile_read_vector(&(pm[i].submodel_norms[j]), fp);
978 for (j = 0; j < MAX_SUBMODELS; j++)
979 cfile_read_vector(&(pm[i].submodel_pnts[j]), fp);
980 for (j = 0; j < MAX_SUBMODELS; j++)
981 pm[i].submodel_rads[j] = cfile_read_fix(fp);
982 cfread(pm[i].submodel_parents, MAX_SUBMODELS, 1, fp);
983 for (j = 0; j < MAX_SUBMODELS; j++)
984 cfile_read_vector(&(pm[i].submodel_mins[j]), fp);
985 for (j = 0; j < MAX_SUBMODELS; j++)
986 cfile_read_vector(&(pm[i].submodel_maxs[j]), fp);
987 cfile_read_vector(&(pm[i].mins), fp);
988 cfile_read_vector(&(pm[i].maxs), fp);
989 pm[i].rad = cfile_read_fix(fp);
990 pm[i].n_textures = cfile_read_byte(fp);
991 pm[i].first_texture = cfile_read_short(fp);
992 pm[i].simpler_model = cfile_read_byte(fp);
1000 * routine which allocates, reads, and inits a polymodel's model_data
1002 void polygon_model_data_read(polymodel *pm, CFILE *fp)
1004 pm->model_data = d_malloc(pm->model_data_size);
1005 Assert(pm->model_data != NULL);
1006 cfread(pm->model_data, sizeof(ubyte), pm->model_data_size, fp );
1007 #ifdef WORDS_NEED_ALIGNMENT
1008 align_polygon_model_data(pm);
1010 #ifdef WORDS_BIGENDIAN
1011 swap_polygon_model_data(pm->model_data);
1013 //verify(pm->model_data);
1014 g3_init_polygon_model(pm->model_data);