2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
16 * Hacked-in polygon objects
29 // -- I hate this warning in make depend! -- #ifdef DRIVE
30 // -- I hate this warning in make depend! -- #include "drive.h"
31 // -- I hate this warning in make depend! -- #else
33 // -- I hate this warning in make depend! -- #endif
59 polymodel Polygon_models[MAX_POLYGON_MODELS]; // = {&bot11,&bot17,&robot_s2,&robot_b2,&bot11,&bot17,&robot_s2,&robot_b2};
61 int D1Share_Polymodel_map[] = {
67 108, 109, 110, 111, 112,
68 113, 114, 115, 116, 117,
69 118, 119, 120, 121, 122,
70 123, 124, 125, 126, 127,
71 128, 129, 130, 133, 134,
72 136, 137, 138, 139, 140,
81 int D1_Polymodel_map[] = {
91 110, 111, 112, 113, 114,
92 115, 116, 117, 118, 119,
93 120, 121, 122, 123, 124,
94 125, 126, 127, 128, 129,
95 130, 131, 132, 133, 134,
96 135, 136, 137, 138, 139,
97 140, 141, 142, -1, -1,
101 int D2Demo_Polymodel_map[] = {
106 97, 98, 107, 108, 109,
107 110, -1, -1, 111, 112,
108 113, 114, 115, 116, 117,
109 118, 119, 120, 121, 122,
110 123, 124, 125, 126, 127,
111 128, 129, 130, 133, 134,
112 136, 137, 138, 139, 140,
113 141, 143, 144, 145, 146,
114 147, 148, 149, 150, 151,
115 152, 155, 156, 157, 158,
121 int N_polygon_models = 0;
123 #define MAX_POLYGON_VECS 1000
124 g3s_point robot_points[MAX_POLYGON_VECS];
126 #define PM_COMPATIBLE_VERSION 6
127 #define PM_OBJFILE_VERSION 8
132 #define MODEL_BUF_SIZE 32768
134 void _pof_cfseek(int len,int type)
137 case SEEK_SET: Pof_addr = len; break;
138 case SEEK_CUR: Pof_addr += len; break;
140 Assert(len <= 0); // seeking from end, better be moving back.
141 Pof_addr = Pof_file_end + len;
145 if (Pof_addr > MODEL_BUF_SIZE)
149 #define pof_cfseek(_buf,_len,_type) _pof_cfseek((_len),(_type))
151 int pof_read_int(ubyte *bufp)
155 i = *((int *) &bufp[Pof_addr]);
159 // if (cfread(&i,sizeof(i),1,f) != 1)
160 // Error("Unexpected end-of-file while reading object");
165 size_t pof_cfread(void *dst, size_t elsize, size_t nelem, ubyte *bufp)
167 if (Pof_addr + nelem*elsize > Pof_file_end)
170 memcpy(dst, &bufp[Pof_addr], elsize*nelem);
172 Pof_addr += elsize*nelem;
174 if (Pof_addr > MODEL_BUF_SIZE)
180 // #define new_read_int(i,f) cfread(&(i),sizeof(i),1,(f))
181 #define new_pof_read_int(i,f) pof_cfread(&(i),sizeof(i),1,(f))
183 short pof_read_short(ubyte *bufp)
187 s = *((short *) &bufp[Pof_addr]);
189 return INTEL_SHORT(s);
190 // if (cfread(&s,sizeof(s),1,f) != 1)
191 // Error("Unexpected end-of-file while reading object");
196 void pof_read_string(char *buf,int max_char, ubyte *bufp)
200 for (i=0; i<max_char; i++) {
201 if ((*buf++ = bufp[Pof_addr++]) == 0)
205 // while (max_char-- && (*buf=cfgetc(f)) != 0) buf++;
209 void pof_read_vecs(vms_vector *vecs,int n,ubyte *bufp)
211 // cfread(vecs,sizeof(vms_vector),n,f);
213 memcpy(vecs, &bufp[Pof_addr], n*sizeof(*vecs));
214 Pof_addr += n*sizeof(*vecs);
216 #ifdef WORDS_BIGENDIAN
218 vms_vector_swap(&vecs[--n]);
221 if (Pof_addr > MODEL_BUF_SIZE)
225 void pof_read_angs(vms_angvec *angs,int n,ubyte *bufp)
227 memcpy(angs, &bufp[Pof_addr], n*sizeof(*angs));
228 Pof_addr += n*sizeof(*angs);
230 #ifdef WORDS_BIGENDIAN
232 vms_angvec_swap(&angs[--n]);
235 if (Pof_addr > MODEL_BUF_SIZE)
239 #define ID_OHDR 0x5244484f // 'RDHO' //Object header
240 #define ID_SOBJ 0x4a424f53 // 'JBOS' //Subobject header
241 #define ID_GUNS 0x534e5547 // 'SNUG' //List of guns on this object
242 #define ID_ANIM 0x4d494e41 // 'MINA' //Animation data
243 #define ID_IDTA 0x41544449 // 'ATDI' //Interpreter data
244 #define ID_TXTR 0x52545854 // 'RTXT' //Texture filename list
247 #define robot_info void
249 vms_angvec anim_angs[N_ANIM_STATES][MAX_SUBMODELS];
251 //set the animation angles for this robot. Gun fields of robot info must
253 void robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS]);
256 #define DEBUG_LEVEL CON_NORMAL
258 #ifdef WORDS_NEED_ALIGNMENT
259 ubyte * old_dest(chunk o) // return where chunk is (in unaligned struct)
261 return o.old_base + INTEL_SHORT(*((short *)(o.old_base + o.offset)));
263 ubyte * new_dest(chunk o) // return where chunk is (in aligned struct)
265 return o.new_base + INTEL_SHORT(*((short *)(o.old_base + o.offset))) + o.correction;
268 * find chunk with smallest address
270 int get_first_chunks_index(chunk *chunk_list, int no_chunks)
272 int i, first_index = 0;
273 Assert(no_chunks >= 1);
274 for (i = 1; i < no_chunks; i++)
275 if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index]))
279 #define SHIFT_SPACE 500 // increase if insufficent
281 void align_polygon_model_data(polymodel *pm)
284 int total_correction = 0;
285 ubyte *cur_old, *cur_new;
287 chunk ch_list[MAX_CHUNKS];
289 int tmp_size = pm->model_data_size + SHIFT_SPACE;
290 ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data
293 //start with first chunk (is always aligned!)
294 cur_old = pm->model_data;
296 chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
297 memcpy(cur_new, cur_old, chunk_len);
298 while (no_chunks > 0) {
299 int first_index = get_first_chunks_index(ch_list, no_chunks);
300 cur_ch = ch_list[first_index];
301 // remove first chunk from array:
303 for (i = first_index; i < no_chunks; i++)
304 ch_list[i] = ch_list[i + 1];
305 // if (new) address unaligned:
306 if ((uint32_t)new_dest(cur_ch) % 4L != 0) {
307 // calculate how much to move to be aligned
308 short to_shift = 4 - (uint32_t)new_dest(cur_ch) % 4L;
309 // correct chunks' addresses
310 cur_ch.correction += to_shift;
311 for (i = 0; i < no_chunks; i++)
312 ch_list[i].correction += to_shift;
313 total_correction += to_shift;
314 Assert((uint32_t)new_dest(cur_ch) % 4L == 0);
315 Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE
317 //write (corrected) chunk for current chunk:
318 *((short *)(cur_ch.new_base + cur_ch.offset))
319 = INTEL_SHORT(cur_ch.correction
320 + INTEL_SHORT(*((short *)(cur_ch.old_base + cur_ch.offset))));
321 //write (correctly aligned) chunk:
322 cur_old = old_dest(cur_ch);
323 cur_new = new_dest(cur_ch);
324 chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
325 memcpy(cur_new, cur_old, chunk_len);
326 //correct submodel_ptr's for pm, too
327 for (i = 0; i < MAX_SUBMODELS; i++)
328 if (pm->model_data + pm->submodel_ptrs[i] >= cur_old
329 && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len)
330 pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data);
332 d_free(pm->model_data);
333 pm->model_data_size += total_correction;
334 pm->model_data = d_malloc(pm->model_data_size);
335 Assert(pm->model_data != NULL);
336 memcpy(pm->model_data, tmp, pm->model_data_size);
339 #endif //def WORDS_NEED_ALIGNMENT
341 //reads a binary file containing a 3d model
342 polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r)
346 int id,len, next_chunk;
350 model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) );
352 Error("Can't allocate space to read model %s\n", filename);
354 if ((ifile=cfopen(filename,"rb"))==NULL)
355 Error("Can't open file <%s>",filename);
357 Assert(cfilelength(ifile) <= MODEL_BUF_SIZE);
360 Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
363 id = pof_read_int(model_buf);
365 if (id!=0x4f505350) /* 'OPSP' */
366 Error("Bad ID in model file <%s>",filename);
368 version = pof_read_short(model_buf);
370 if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
371 Error("Bad version (%d) in model file <%s>",version,filename);
373 if ( FindArg( "-bspgen" ))
374 printf( "bspgen -c1" );
376 while (new_pof_read_int(id,model_buf) == 1) {
378 //id = pof_read_int(model_buf);
379 len = pof_read_int(model_buf);
380 next_chunk = Pof_addr + len;
384 case ID_OHDR: { //Object header
385 vms_vector pmmin,pmmax;
387 //con_printf(DEBUG_LEVEL, "Got chunk OHDR, len=%d\n",len);
389 pm->n_models = pof_read_int(model_buf);
390 pm->rad = pof_read_int(model_buf);
392 Assert(pm->n_models <= MAX_SUBMODELS);
394 pof_read_vecs(&pmmin,1,model_buf);
395 pof_read_vecs(&pmmax,1,model_buf);
397 if ( FindArg( "-bspgen" )) {
401 vm_vec_sub(&v, &pmmax, &pmmin );
403 if ( v.y > l ) l = v.y;
404 if ( v.z > l ) l = v.z;
406 printf( " -l%.3f", f2fl(l) );
412 case ID_SOBJ: { //Subobject header
417 //con_printf(DEBUG_LEVEL, "Got chunk SOBJ, len=%d\n",len);
419 n = pof_read_short(model_buf);
421 Assert(n < MAX_SUBMODELS);
423 pm->submodel_parents[n] = pof_read_short(model_buf);
425 pof_read_vecs(&pm->submodel_norms[n],1,model_buf);
426 pof_read_vecs(&pm->submodel_pnts[n],1,model_buf);
427 pof_read_vecs(&pm->submodel_offsets[n],1,model_buf);
429 pm->submodel_rads[n] = pof_read_int(model_buf); //radius
431 pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset
438 case ID_GUNS: { //List of guns on this object
440 //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len);
445 ubyte gun_used[MAX_GUNS];
447 r->n_guns = pof_read_int(model_buf);
452 Assert(r->n_guns <= MAX_GUNS);
454 for (i=0;i<r->n_guns;i++)
457 for (i=0;i<r->n_guns;i++) {
460 id = pof_read_short(model_buf);
461 Assert(id < r->n_guns);
462 Assert(gun_used[id] == 0);
464 r->gun_submodels[id] = pof_read_short(model_buf);
465 Assert(r->gun_submodels[id] != 0xff);
466 pof_read_vecs(&r->gun_points[id],1,model_buf);
469 pof_read_vecs(&gun_dir,1,model_buf);
473 pof_cfseek(model_buf,len,SEEK_CUR);
478 case ID_ANIM: //Animation data
479 //con_printf(DEBUG_LEVEL, "Got chunk ANIM, len=%d\n",len);
486 n_frames = pof_read_short(model_buf);
488 Assert(n_frames == N_ANIM_STATES);
490 for (m=0;m<pm->n_models;m++)
491 for (f=0;f<n_frames;f++)
492 pof_read_angs(&anim_angs[f][m], 1, model_buf);
495 robot_set_angles(r,pm,anim_angs);
499 pof_cfseek(model_buf,len,SEEK_CUR);
504 case ID_TXTR: { //Texture filename list
508 //con_printf(DEBUG_LEVEL, "Got chunk TXTR, len=%d\n",len);
510 n = pof_read_short(model_buf);
511 //con_printf(DEBUG_LEVEL, " num textures = %d\n",n);
513 pof_read_string(name_buf,128,model_buf);
514 //con_printf(DEBUG_LEVEL, "<%s>\n",name_buf);
520 case ID_IDTA: //Interpreter data
521 //con_printf(DEBUG_LEVEL, "Got chunk IDTA, len=%d\n",len);
523 pm->model_data = d_malloc(len);
524 pm->model_data_size = len;
526 pof_cfread(pm->model_data,1,len,model_buf);
531 //con_printf(DEBUG_LEVEL, "Unknown chunk <%c%c%c%c>, len = %d\n",id,id>>8,id>>16,id>>24,len);
532 pof_cfseek(model_buf,len,SEEK_CUR);
536 if ( version >= 8 ) // Version 8 needs 4-byte alignment!!!
537 pof_cfseek(model_buf,next_chunk,SEEK_SET);
540 // for (i=0;i<pm->n_models;i++)
541 // pm->submodel_ptrs[i] += (int) pm->model_data;
543 if ( FindArg( "-bspgen" )) {
544 char *p = strchr( filename, '.' );
550 printf( " %s.3ds\n", filename );
556 #ifdef WORDS_NEED_ALIGNMENT
557 align_polygon_model_data(pm);
559 #ifdef WORDS_BIGENDIAN
560 swap_polygon_model_data(pm->model_data);
562 //verify(pm->model_data);
567 //reads the gun information for a model
568 //fills in arrays gun_points & gun_dirs, returns the number of guns read
569 int read_model_guns(char *filename,vms_vector *gun_points, vms_vector *gun_dirs, int *gun_submodels)
577 model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) );
579 Error("Can't allocate space to read model %s\n", filename);
581 if ((ifile=cfopen(filename,"rb"))==NULL)
582 Error("Can't open file <%s>",filename);
584 Assert(cfilelength(ifile) <= MODEL_BUF_SIZE);
587 Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
590 id = pof_read_int(model_buf);
592 if (id!=0x4f505350) /* 'OPSP' */
593 Error("Bad ID in model file <%s>",filename);
595 version = pof_read_short(model_buf);
597 Assert(version >= 7); //must be 7 or higher for this data
599 if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
600 Error("Bad version (%d) in model file <%s>",version,filename);
602 while (new_pof_read_int(id,model_buf) == 1) {
604 //id = pof_read_int(model_buf);
605 len = pof_read_int(model_buf);
607 if (id == ID_GUNS) { //List of guns on this object
609 //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len);
613 n_guns = pof_read_int(model_buf);
615 for (i=0;i<n_guns;i++) {
618 id = pof_read_short(model_buf);
619 sm = pof_read_short(model_buf);
621 gun_submodels[id] = sm;
623 Error("Invalid gun submodel in file <%s>",filename);
624 pof_read_vecs(&gun_points[id],1,model_buf);
626 pof_read_vecs(&gun_dirs[id],1,model_buf);
631 pof_cfseek(model_buf,len,SEEK_CUR);
640 //free up a model, getting rid of all its memory
641 void free_model(polymodel *po)
643 d_free(po->model_data);
646 grs_bitmap *texture_list[MAX_POLYOBJ_TEXTURES];
647 bitmap_index texture_list_index[MAX_POLYOBJ_TEXTURES];
649 int Simple_model_threshhold_scale=5; //switch when this times radius far away
652 //draw a polygon model
654 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[])
659 Assert(model_num < N_polygon_models);
661 po=&Polygon_models[model_num];
663 //check if should use simple model
664 if (po->simpler_model ) //must have a simpler model
665 if (flags==0) //can't switch if this is debris
666 //!!if (!alt_textures) { //alternate textures might not match
667 //alt textures might not match, but in the one case we're using this
668 //for on 11/14/94, they do match. So we leave it in.
673 depth = g3_calc_point_depth(pos); //gets 3d depth
675 while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad)
676 po = &Polygon_models[po->simpler_model-1];
681 for (i=0;i<po->n_textures;i++) {
682 texture_list_index[i] = alt_textures[i];
683 texture_list[i] = &GameBitmaps[alt_textures[i].index];
688 for (i=0;i<po->n_textures;i++) {
689 texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
690 texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index];
694 #ifdef PIGGY_USE_PAGING
695 // Make sure the textures for this object are paged in...
696 piggy_page_flushed = 0;
697 for (i=0;i<po->n_textures;i++)
698 PIGGY_PAGE_IN( texture_list_index[i] );
699 // Hmmm... cache got flushed in the middle of paging all these in,
700 // so we need to reread them all in.
701 if (piggy_page_flushed) {
702 piggy_page_flushed = 0;
703 for (i=0;i<po->n_textures;i++)
704 PIGGY_PAGE_IN( texture_list_index[i] );
706 // Make sure that they can all fit in memory.
707 Assert( piggy_page_flushed == 0 );
710 g3_start_instance_matrix(pos,orient);
712 g3_set_interp_points(robot_points);
714 if (flags == 0) //draw entire object
716 g3_draw_polygon_model(po->model_data,texture_list,anim_angles,light,glow_values);
721 for (i=0;flags;flags>>=1,i++)
725 Assert(i < po->n_models);
727 //if submodel, rotate around its center point, not pivot point
729 vm_vec_avg(&ofs,&po->submodel_mins[i],&po->submodel_maxs[i]);
731 g3_start_instance_matrix(&ofs,NULL);
733 g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]],texture_list,anim_angles,light,glow_values);
742 void free_polygon_models()
746 for (i=0;i<N_polygon_models;i++) {
747 free_model(&Polygon_models[i]);
752 void polyobj_find_min_max(polymodel *pm)
758 vms_vector *big_mn,*big_mx;
763 for (m=0;m<pm->n_models;m++) {
764 vms_vector *mn,*mx,*ofs;
766 mn = &pm->submodel_mins[m];
767 mx = &pm->submodel_maxs[m];
768 ofs= &pm->submodel_offsets[m];
770 data = (ushort *)&pm->model_data[pm->submodel_ptrs[m]];
774 Assert(type == 7 || type == 1);
779 data+=2; //skip start & pad
781 vp = (vms_vector *) data;
783 *mn = *mx = *vp++; nverts--;
786 *big_mn = *big_mx = *mn;
789 if (vp->x > mx->x) mx->x = vp->x;
790 if (vp->y > mx->y) mx->y = vp->y;
791 if (vp->z > mx->z) mx->z = vp->z;
793 if (vp->x < mn->x) mn->x = vp->x;
794 if (vp->y < mn->y) mn->y = vp->y;
795 if (vp->z < mn->z) mn->z = vp->z;
797 if (vp->x+ofs->x > big_mx->x) big_mx->x = vp->x+ofs->x;
798 if (vp->y+ofs->y > big_mx->y) big_mx->y = vp->y+ofs->y;
799 if (vp->z+ofs->z > big_mx->z) big_mx->z = vp->z+ofs->z;
801 if (vp->x+ofs->x < big_mn->x) big_mn->x = vp->x+ofs->x;
802 if (vp->y+ofs->y < big_mn->y) big_mn->y = vp->y+ofs->y;
803 if (vp->z+ofs->z < big_mn->z) big_mn->z = vp->z+ofs->z;
808 // printf("Submodel %d: (%8x,%8x) (%8x,%8x) (%8x,%8x)\n",m,mn->x,mx->x,mn->y,mx->y,mn->z,mx->z);
811 // 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);
815 extern short highest_texture_num; //from the 3d
817 char Pof_names[MAX_POLYGON_MODELS][FILENAME_LEN];
819 //returns the number of this model
821 int load_polygon_model(char *filename,int n_textures,int first_texture,robot_info *r)
823 int load_polygon_model(char *filename,int n_textures,grs_bitmap ***textures)
830 Assert(N_polygon_models < MAX_POLYGON_MODELS);
831 Assert(n_textures < MAX_POLYOBJ_TEXTURES);
833 // MK was real tired of those useless, slow mprintfs...
834 if (N_polygon_models > MAX_POLYGON_MODELS - 10)
835 mprintf(( 0, "Used %d/%d polygon model slots\n", N_polygon_models+1, MAX_POLYGON_MODELS ));
837 Assert(strlen(filename) <= 12);
838 strcpy(Pof_names[N_polygon_models],filename);
840 read_model_file(&Polygon_models[N_polygon_models],filename,r);
842 polyobj_find_min_max(&Polygon_models[N_polygon_models]);
844 g3_init_polygon_model(Polygon_models[N_polygon_models].model_data);
846 if (highest_texture_num+1 != n_textures)
847 Error("Model <%s> references %d textures but specifies %d.",filename,highest_texture_num+1,n_textures);
849 Polygon_models[N_polygon_models].n_textures = n_textures;
850 Polygon_models[N_polygon_models].first_texture = first_texture;
851 Polygon_models[N_polygon_models].simpler_model = 0;
853 // Assert(polygon_models[N_polygon_models]!=NULL);
857 return N_polygon_models-1;
862 void init_polygon_models()
864 N_polygon_models = 0;
866 atexit((void (*)())free_polygon_models);
870 //compare against this size when figuring how far to place eye for picture
871 #define BASE_MODEL_SIZE 0x28000
873 #define DEFAULT_VIEW_DIST 0x60000
875 //draws the given model in the current canvas. The distance is set to
876 //more-or-less fill the canvas. Note that this routine actually renders
877 //into an off-screen canvas that it creates, then copies to the current
879 void draw_model_picture(int mn,vms_angvec *orient_angles)
881 vms_vector temp_pos=ZERO_VECTOR;
882 vms_matrix temp_orient = IDENTITY_MATRIX;
884 grs_canvas *save_canv = grd_curcanv,*temp_canv;
887 Assert(mn>=0 && mn<N_polygon_models);
890 ogl_start_offscreen_render(0, 0, grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h);
892 temp_canv = gr_create_canvas(save_canv->cv_bitmap.bm_w,save_canv->cv_bitmap.bm_h);
893 gr_set_current_canvas(temp_canv);
895 gr_clear_canvas( BM_XRGB(0,0,0) );
898 g3_set_view_matrix(&temp_pos,&temp_orient,0x9000);
900 if (Polygon_models[mn].rad != 0)
901 temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST,Polygon_models[mn].rad,BASE_MODEL_SIZE);
903 temp_pos.z = DEFAULT_VIEW_DIST;
905 vm_angles_2_matrix(&temp_orient, orient_angles);
907 draw_polygon_model(&temp_pos,&temp_orient,NULL,mn,0,f1_0,NULL,NULL);
912 ogl_end_offscreen_render();
914 gr_set_current_canvas(save_canv);
916 gr_bitmap(0,0,&temp_canv->cv_bitmap);
918 gr_free_canvas(temp_canv);
924 * reads a polymodel structure from a CFILE
926 extern void polymodel_read(polymodel *pm, CFILE *fp)
930 pm->n_models = cfile_read_int(fp);
931 pm->model_data_size = cfile_read_int(fp);
932 pm->model_data = (ubyte *)cfile_read_int(fp); // garbage, read it anyway just for consistency
933 for (i = 0; i < MAX_SUBMODELS; i++)
934 pm->submodel_ptrs[i] = cfile_read_int(fp);
935 for (i = 0; i < MAX_SUBMODELS; i++)
936 cfile_read_vector(&(pm->submodel_offsets[i]), fp);
937 for (i = 0; i < MAX_SUBMODELS; i++)
938 cfile_read_vector(&(pm->submodel_norms[i]), fp);
939 for (i = 0; i < MAX_SUBMODELS; i++)
940 cfile_read_vector(&(pm->submodel_pnts[i]), fp);
941 for (i = 0; i < MAX_SUBMODELS; i++)
942 pm->submodel_rads[i] = cfile_read_fix(fp);
943 cfread(pm->submodel_parents, MAX_SUBMODELS, 1, fp);
944 for (i = 0; i < MAX_SUBMODELS; i++)
945 cfile_read_vector(&(pm->submodel_mins[i]), fp);
946 for (i = 0; i < MAX_SUBMODELS; i++)
947 cfile_read_vector(&(pm->submodel_maxs[i]), fp);
948 cfile_read_vector(&(pm->mins), fp);
949 cfile_read_vector(&(pm->maxs), fp);
950 pm->rad = cfile_read_fix(fp);
951 pm->n_textures = cfile_read_byte(fp);
952 pm->first_texture = cfile_read_short(fp);
953 pm->simpler_model = cfile_read_byte(fp);
957 * reads n polymodel structs from a CFILE
959 extern int polymodel_read_n(polymodel *pm, int n, CFILE *fp)
963 for (i = 0; i < n; i++) {
964 pm[i].n_models = cfile_read_int(fp);
965 pm[i].model_data_size = cfile_read_int(fp);
966 pm->model_data = (ubyte *)cfile_read_int(fp); // garbage, read it anyway just for consistency
967 for (j = 0; j < MAX_SUBMODELS; j++)
968 pm[i].submodel_ptrs[j] = cfile_read_int(fp);
969 for (j = 0; j < MAX_SUBMODELS; j++)
970 cfile_read_vector(&(pm[i].submodel_offsets[j]), fp);
971 for (j = 0; j < MAX_SUBMODELS; j++)
972 cfile_read_vector(&(pm[i].submodel_norms[j]), fp);
973 for (j = 0; j < MAX_SUBMODELS; j++)
974 cfile_read_vector(&(pm[i].submodel_pnts[j]), fp);
975 for (j = 0; j < MAX_SUBMODELS; j++)
976 pm[i].submodel_rads[j] = cfile_read_fix(fp);
977 cfread(pm[i].submodel_parents, MAX_SUBMODELS, 1, fp);
978 for (j = 0; j < MAX_SUBMODELS; j++)
979 cfile_read_vector(&(pm[i].submodel_mins[j]), fp);
980 for (j = 0; j < MAX_SUBMODELS; j++)
981 cfile_read_vector(&(pm[i].submodel_maxs[j]), fp);
982 cfile_read_vector(&(pm[i].mins), fp);
983 cfile_read_vector(&(pm[i].maxs), fp);
984 pm[i].rad = cfile_read_fix(fp);
985 pm[i].n_textures = cfile_read_byte(fp);
986 pm[i].first_texture = cfile_read_short(fp);
987 pm[i].simpler_model = cfile_read_byte(fp);
995 * routine which allocates, reads, and inits a polymodel's model_data
997 void polygon_model_data_read(polymodel *pm, CFILE *fp)
999 pm->model_data = d_malloc(pm->model_data_size);
1000 Assert(pm->model_data != NULL);
1001 cfread(pm->model_data, sizeof(ubyte), pm->model_data_size, fp );
1002 #ifdef WORDS_NEED_ALIGNMENT
1003 align_polygon_model_data(pm);
1005 #ifdef WORDS_BIGENDIAN
1006 swap_polygon_model_data(pm->model_data);
1008 //verify(pm->model_data);
1009 g3_init_polygon_model(pm->model_data);