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
42 polymodel Polygon_models[MAX_POLYGON_MODELS]; // = {&bot11,&bot17,&robot_s2,&robot_b2,&bot11,&bot17,&robot_s2,&robot_b2};
44 int D1Share_Polymodel_map[] = {
50 108, 109, 110, 111, 112,
51 113, 114, 115, 116, 117,
52 118, 119, 120, 121, 122,
53 123, 124, 125, 126, 127,
54 128, 129, 130, 133, 134,
55 136, 137, 138, 139, 140,
64 int D1_Polymodel_map[] = {
74 110, 111, 112, 113, 114,
75 115, 116, 117, 118, 119,
76 120, 121, 122, 123, 124,
77 125, 126, 127, 128, 129,
78 130, 131, 132, 133, 134,
79 135, 136, 137, 138, 139,
80 140, 141, 142, -1, -1,
84 int D2Demo_Polymodel_map[] = {
89 97, 98, 107, 108, 109,
90 110, -1, -1, 111, 112,
91 113, 114, 115, 116, 117,
92 118, 119, 120, 121, 122,
93 123, 124, 125, 126, 127,
94 128, 129, 130, 133, 134,
95 136, 137, 138, 139, 140,
96 141, 143, 144, 145, 146,
97 147, 148, 149, 150, 151,
98 152, 155, 156, 157, 158,
104 int N_polygon_models = 0;
106 #define MAX_POLYGON_VECS 1000
107 g3s_point robot_points[MAX_POLYGON_VECS];
109 #define PM_COMPATIBLE_VERSION 6
110 #define PM_OBJFILE_VERSION 8
115 #define MODEL_BUF_SIZE 32768
117 void _pof_cfseek(int len,int type)
120 case SEEK_SET: Pof_addr = len; break;
121 case SEEK_CUR: Pof_addr += len; break;
123 Assert(len <= 0); // seeking from end, better be moving back.
124 Pof_addr = Pof_file_end + len;
128 if (Pof_addr > MODEL_BUF_SIZE)
132 #define pof_cfseek(_buf,_len,_type) _pof_cfseek((_len),(_type))
134 int pof_read_int(ubyte *bufp)
138 i = *((int *) &bufp[Pof_addr]);
142 // if (cfread(&i,sizeof(i),1,f) != 1)
143 // Error("Unexpected end-of-file while reading object");
148 size_t pof_cfread(void *dst, size_t elsize, size_t nelem, ubyte *bufp)
150 if (Pof_addr + nelem*elsize > Pof_file_end)
153 memcpy(dst, &bufp[Pof_addr], elsize*nelem);
155 Pof_addr += elsize*nelem;
157 if (Pof_addr > MODEL_BUF_SIZE)
163 // #define new_read_int(i,f) cfread(&(i),sizeof(i),1,(f))
164 #define new_pof_read_int(i,f) pof_cfread(&(i),sizeof(i),1,(f))
166 short pof_read_short(ubyte *bufp)
170 s = *((short *) &bufp[Pof_addr]);
172 return INTEL_SHORT(s);
173 // if (cfread(&s,sizeof(s),1,f) != 1)
174 // Error("Unexpected end-of-file while reading object");
179 void pof_read_string(char *buf,int max_char, ubyte *bufp)
183 for (i=0; i<max_char; i++) {
184 if ((*buf++ = bufp[Pof_addr++]) == 0)
188 // while (max_char-- && (*buf=cfgetc(f)) != 0) buf++;
192 void pof_read_vecs(vms_vector *vecs,int n,ubyte *bufp)
194 // cfread(vecs,sizeof(vms_vector),n,f);
196 memcpy(vecs, &bufp[Pof_addr], n*sizeof(*vecs));
197 Pof_addr += n*sizeof(*vecs);
199 #ifdef WORDS_BIGENDIAN
201 vms_vector_swap(&vecs[--n]);
204 if (Pof_addr > MODEL_BUF_SIZE)
208 void pof_read_angs(vms_angvec *angs,int n,ubyte *bufp)
210 memcpy(angs, &bufp[Pof_addr], n*sizeof(*angs));
211 Pof_addr += n*sizeof(*angs);
213 #ifdef WORDS_BIGENDIAN
215 vms_angvec_swap(&angs[--n]);
218 if (Pof_addr > MODEL_BUF_SIZE)
222 #define ID_OHDR 0x5244484f // 'RDHO' //Object header
223 #define ID_SOBJ 0x4a424f53 // 'JBOS' //Subobject header
224 #define ID_GUNS 0x534e5547 // 'SNUG' //List of guns on this object
225 #define ID_ANIM 0x4d494e41 // 'MINA' //Animation data
226 #define ID_IDTA 0x41544449 // 'ATDI' //Interpreter data
227 #define ID_TXTR 0x52545854 // 'RTXT' //Texture filename list
230 #define robot_info void
232 vms_angvec anim_angs[N_ANIM_STATES][MAX_SUBMODELS];
234 //set the animation angles for this robot. Gun fields of robot info must
236 void robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS]);
239 #define DEBUG_LEVEL CON_NORMAL
241 #ifdef WORDS_NEED_ALIGNMENT
242 ubyte * old_dest(chunk o) // return where chunk is (in unaligned struct)
244 return o.old_base + INTEL_SHORT(*((short *)(o.old_base + o.offset)));
246 ubyte * new_dest(chunk o) // return where chunk is (in aligned struct)
248 return o.new_base + INTEL_SHORT(*((short *)(o.old_base + o.offset))) + o.correction;
251 * find chunk with smallest address
253 int get_first_chunks_index(chunk *chunk_list, int no_chunks)
255 int i, first_index = 0;
256 Assert(no_chunks >= 1);
257 for (i = 1; i < no_chunks; i++)
258 if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index]))
262 #define SHIFT_SPACE 500 // increase if insufficent
264 void align_polygon_model_data(polymodel *pm)
267 int total_correction = 0;
268 ubyte *cur_old, *cur_new;
270 chunk ch_list[MAX_CHUNKS];
272 int tmp_size = pm->model_data_size + SHIFT_SPACE;
273 ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data
276 //start with first chunk (is always aligned!)
277 cur_old = pm->model_data;
279 chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
280 memcpy(cur_new, cur_old, chunk_len);
281 while (no_chunks > 0) {
282 int first_index = get_first_chunks_index(ch_list, no_chunks);
283 cur_ch = ch_list[first_index];
284 // remove first chunk from array:
286 for (i = first_index; i < no_chunks; i++)
287 ch_list[i] = ch_list[i + 1];
288 // if (new) address unaligned:
289 if ((uint32_t)new_dest(cur_ch) % 4L != 0) {
290 // calculate how much to move to be aligned
291 short to_shift = 4 - (uint32_t)new_dest(cur_ch) % 4L;
292 // correct chunks' addresses
293 cur_ch.correction += to_shift;
294 for (i = 0; i < no_chunks; i++)
295 ch_list[i].correction += to_shift;
296 total_correction += to_shift;
297 Assert((uint32_t)new_dest(cur_ch) % 4L == 0);
298 Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE
300 //write (corrected) chunk for current chunk:
301 *((short *)(cur_ch.new_base + cur_ch.offset))
302 = INTEL_SHORT(cur_ch.correction
303 + INTEL_SHORT(*((short *)(cur_ch.old_base + cur_ch.offset))));
304 //write (correctly aligned) chunk:
305 cur_old = old_dest(cur_ch);
306 cur_new = new_dest(cur_ch);
307 chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
308 memcpy(cur_new, cur_old, chunk_len);
309 //correct submodel_ptr's for pm, too
310 for (i = 0; i < MAX_SUBMODELS; i++)
311 if (pm->model_data + pm->submodel_ptrs[i] >= cur_old
312 && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len)
313 pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data);
315 d_free(pm->model_data);
316 pm->model_data_size += total_correction;
317 pm->model_data = d_malloc(pm->model_data_size);
318 Assert(pm->model_data != NULL);
319 memcpy(pm->model_data, tmp, pm->model_data_size);
322 #endif //def WORDS_NEED_ALIGNMENT
324 //reads a binary file containing a 3d model
325 polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r)
329 int id,len, next_chunk;
333 model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) );
335 Error("Can't allocate space to read model %s\n", filename);
337 if ((ifile=cfopen(filename,"rb"))==NULL)
338 Error("Can't open file <%s>",filename);
340 Assert(cfilelength(ifile) <= MODEL_BUF_SIZE);
343 Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
346 id = pof_read_int(model_buf);
348 if (id!=0x4f505350) /* 'OPSP' */
349 Error("Bad ID in model file <%s>",filename);
351 version = pof_read_short(model_buf);
353 if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
354 Error("Bad version (%d) in model file <%s>",version,filename);
356 if ( FindArg( "-bspgen" ))
357 printf( "bspgen -c1" );
359 while (new_pof_read_int(id,model_buf) == 1) {
361 //id = pof_read_int(model_buf);
362 len = pof_read_int(model_buf);
363 next_chunk = Pof_addr + len;
367 case ID_OHDR: { //Object header
368 vms_vector pmmin,pmmax;
370 //con_printf(DEBUG_LEVEL, "Got chunk OHDR, len=%d\n",len);
372 pm->n_models = pof_read_int(model_buf);
373 pm->rad = pof_read_int(model_buf);
375 Assert(pm->n_models <= MAX_SUBMODELS);
377 pof_read_vecs(&pmmin,1,model_buf);
378 pof_read_vecs(&pmmax,1,model_buf);
380 if ( FindArg( "-bspgen" )) {
384 vm_vec_sub(&v, &pmmax, &pmmin );
386 if ( v.y > l ) l = v.y;
387 if ( v.z > l ) l = v.z;
389 printf( " -l%.3f", f2fl(l) );
395 case ID_SOBJ: { //Subobject header
400 //con_printf(DEBUG_LEVEL, "Got chunk SOBJ, len=%d\n",len);
402 n = pof_read_short(model_buf);
404 Assert(n < MAX_SUBMODELS);
406 pm->submodel_parents[n] = pof_read_short(model_buf);
408 pof_read_vecs(&pm->submodel_norms[n],1,model_buf);
409 pof_read_vecs(&pm->submodel_pnts[n],1,model_buf);
410 pof_read_vecs(&pm->submodel_offsets[n],1,model_buf);
412 pm->submodel_rads[n] = pof_read_int(model_buf); //radius
414 pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset
421 case ID_GUNS: { //List of guns on this object
423 //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len);
428 ubyte gun_used[MAX_GUNS];
430 r->n_guns = pof_read_int(model_buf);
435 Assert(r->n_guns <= MAX_GUNS);
437 for (i=0;i<r->n_guns;i++)
440 for (i=0;i<r->n_guns;i++) {
443 id = pof_read_short(model_buf);
444 Assert(id < r->n_guns);
445 Assert(gun_used[id] == 0);
447 r->gun_submodels[id] = pof_read_short(model_buf);
448 Assert(r->gun_submodels[id] != 0xff);
449 pof_read_vecs(&r->gun_points[id],1,model_buf);
452 pof_read_vecs(&gun_dir,1,model_buf);
456 pof_cfseek(model_buf,len,SEEK_CUR);
461 case ID_ANIM: //Animation data
462 //con_printf(DEBUG_LEVEL, "Got chunk ANIM, len=%d\n",len);
469 n_frames = pof_read_short(model_buf);
471 Assert(n_frames == N_ANIM_STATES);
473 for (m=0;m<pm->n_models;m++)
474 for (f=0;f<n_frames;f++)
475 pof_read_angs(&anim_angs[f][m], 1, model_buf);
478 robot_set_angles(r,pm,anim_angs);
482 pof_cfseek(model_buf,len,SEEK_CUR);
487 case ID_TXTR: { //Texture filename list
491 //con_printf(DEBUG_LEVEL, "Got chunk TXTR, len=%d\n",len);
493 n = pof_read_short(model_buf);
494 //con_printf(DEBUG_LEVEL, " num textures = %d\n",n);
496 pof_read_string(name_buf,128,model_buf);
497 //con_printf(DEBUG_LEVEL, "<%s>\n",name_buf);
503 case ID_IDTA: //Interpreter data
504 //con_printf(DEBUG_LEVEL, "Got chunk IDTA, len=%d\n",len);
506 pm->model_data = d_malloc(len);
507 pm->model_data_size = len;
509 pof_cfread(pm->model_data,1,len,model_buf);
514 //con_printf(DEBUG_LEVEL, "Unknown chunk <%c%c%c%c>, len = %d\n",id,id>>8,id>>16,id>>24,len);
515 pof_cfseek(model_buf,len,SEEK_CUR);
519 if ( version >= 8 ) // Version 8 needs 4-byte alignment!!!
520 pof_cfseek(model_buf,next_chunk,SEEK_SET);
523 // for (i=0;i<pm->n_models;i++)
524 // pm->submodel_ptrs[i] += (int) pm->model_data;
526 if ( FindArg( "-bspgen" )) {
527 char *p = strchr( filename, '.' );
533 printf( " %s.3ds\n", filename );
539 #ifdef WORDS_NEED_ALIGNMENT
540 align_polygon_model_data(pm);
542 #ifdef WORDS_BIGENDIAN
543 swap_polygon_model_data(pm->model_data);
545 //verify(pm->model_data);
550 //reads the gun information for a model
551 //fills in arrays gun_points & gun_dirs, returns the number of guns read
552 int read_model_guns(char *filename,vms_vector *gun_points, vms_vector *gun_dirs, int *gun_submodels)
560 model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) );
562 Error("Can't allocate space to read model %s\n", filename);
564 if ((ifile=cfopen(filename,"rb"))==NULL)
565 Error("Can't open file <%s>",filename);
567 Assert(cfilelength(ifile) <= MODEL_BUF_SIZE);
570 Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
573 id = pof_read_int(model_buf);
575 if (id!=0x4f505350) /* 'OPSP' */
576 Error("Bad ID in model file <%s>",filename);
578 version = pof_read_short(model_buf);
580 Assert(version >= 7); //must be 7 or higher for this data
582 if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
583 Error("Bad version (%d) in model file <%s>",version,filename);
585 while (new_pof_read_int(id,model_buf) == 1) {
587 //id = pof_read_int(model_buf);
588 len = pof_read_int(model_buf);
590 if (id == ID_GUNS) { //List of guns on this object
592 //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len);
596 n_guns = pof_read_int(model_buf);
598 for (i=0;i<n_guns;i++) {
601 id = pof_read_short(model_buf);
602 sm = pof_read_short(model_buf);
604 gun_submodels[id] = sm;
606 Error("Invalid gun submodel in file <%s>",filename);
607 pof_read_vecs(&gun_points[id],1,model_buf);
609 pof_read_vecs(&gun_dirs[id],1,model_buf);
614 pof_cfseek(model_buf,len,SEEK_CUR);
623 //free up a model, getting rid of all its memory
624 void free_model(polymodel *po)
626 d_free(po->model_data);
629 grs_bitmap *texture_list[MAX_POLYOBJ_TEXTURES];
630 bitmap_index texture_list_index[MAX_POLYOBJ_TEXTURES];
632 int Simple_model_threshhold_scale=5; //switch when this times radius far away
635 //draw a polygon model
637 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[])
642 Assert(model_num < N_polygon_models);
644 po=&Polygon_models[model_num];
646 //check if should use simple model
647 if (po->simpler_model ) //must have a simpler model
648 if (flags==0) //can't switch if this is debris
649 //!!if (!alt_textures) { //alternate textures might not match
650 //alt textures might not match, but in the one case we're using this
651 //for on 11/14/94, they do match. So we leave it in.
656 depth = g3_calc_point_depth(pos); //gets 3d depth
658 while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad)
659 po = &Polygon_models[po->simpler_model-1];
664 for (i=0;i<po->n_textures;i++) {
665 texture_list_index[i] = alt_textures[i];
666 texture_list[i] = &GameBitmaps[alt_textures[i].index];
671 for (i=0;i<po->n_textures;i++) {
672 texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
673 texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index];
677 #ifdef PIGGY_USE_PAGING
678 // Make sure the textures for this object are paged in...
679 piggy_page_flushed = 0;
680 for (i=0;i<po->n_textures;i++)
681 PIGGY_PAGE_IN( texture_list_index[i] );
682 // Hmmm... cache got flushed in the middle of paging all these in,
683 // so we need to reread them all in.
684 if (piggy_page_flushed) {
685 piggy_page_flushed = 0;
686 for (i=0;i<po->n_textures;i++)
687 PIGGY_PAGE_IN( texture_list_index[i] );
689 // Make sure that they can all fit in memory.
690 Assert( piggy_page_flushed == 0 );
693 g3_start_instance_matrix(pos,orient);
695 g3_set_interp_points(robot_points);
697 if (flags == 0) //draw entire object
699 g3_draw_polygon_model(po->model_data,texture_list,anim_angles,light,glow_values);
704 for (i=0;flags;flags>>=1,i++)
708 Assert(i < po->n_models);
710 //if submodel, rotate around its center point, not pivot point
712 vm_vec_avg(&ofs,&po->submodel_mins[i],&po->submodel_maxs[i]);
714 g3_start_instance_matrix(&ofs,NULL);
716 g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]],texture_list,anim_angles,light,glow_values);
725 void free_polygon_models()
729 for (i=0;i<N_polygon_models;i++) {
730 free_model(&Polygon_models[i]);
735 void polyobj_find_min_max(polymodel *pm)
741 vms_vector *big_mn,*big_mx;
746 for (m=0;m<pm->n_models;m++) {
747 vms_vector *mn,*mx,*ofs;
749 mn = &pm->submodel_mins[m];
750 mx = &pm->submodel_maxs[m];
751 ofs= &pm->submodel_offsets[m];
753 data = (ushort *)&pm->model_data[pm->submodel_ptrs[m]];
757 Assert(type == 7 || type == 1);
762 data+=2; //skip start & pad
764 vp = (vms_vector *) data;
766 *mn = *mx = *vp++; nverts--;
769 *big_mn = *big_mx = *mn;
772 if (vp->x > mx->x) mx->x = vp->x;
773 if (vp->y > mx->y) mx->y = vp->y;
774 if (vp->z > mx->z) mx->z = vp->z;
776 if (vp->x < mn->x) mn->x = vp->x;
777 if (vp->y < mn->y) mn->y = vp->y;
778 if (vp->z < mn->z) mn->z = vp->z;
780 if (vp->x+ofs->x > big_mx->x) big_mx->x = vp->x+ofs->x;
781 if (vp->y+ofs->y > big_mx->y) big_mx->y = vp->y+ofs->y;
782 if (vp->z+ofs->z > big_mx->z) big_mx->z = vp->z+ofs->z;
784 if (vp->x+ofs->x < big_mn->x) big_mn->x = vp->x+ofs->x;
785 if (vp->y+ofs->y < big_mn->y) big_mn->y = vp->y+ofs->y;
786 if (vp->z+ofs->z < big_mn->z) big_mn->z = vp->z+ofs->z;
791 // printf("Submodel %d: (%8x,%8x) (%8x,%8x) (%8x,%8x)\n",m,mn->x,mx->x,mn->y,mx->y,mn->z,mx->z);
794 // 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);
798 extern short highest_texture_num; //from the 3d
800 char Pof_names[MAX_POLYGON_MODELS][FILENAME_LEN];
802 //returns the number of this model
804 int load_polygon_model(char *filename,int n_textures,int first_texture,robot_info *r)
806 int load_polygon_model(char *filename,int n_textures,grs_bitmap ***textures)
813 Assert(N_polygon_models < MAX_POLYGON_MODELS);
814 Assert(n_textures < MAX_POLYOBJ_TEXTURES);
816 // MK was real tired of those useless, slow mprintfs...
817 if (N_polygon_models > MAX_POLYGON_MODELS - 10)
818 mprintf(( 0, "Used %d/%d polygon model slots\n", N_polygon_models+1, MAX_POLYGON_MODELS ));
820 Assert(strlen(filename) <= 12);
821 strcpy(Pof_names[N_polygon_models],filename);
823 read_model_file(&Polygon_models[N_polygon_models],filename,r);
825 polyobj_find_min_max(&Polygon_models[N_polygon_models]);
827 g3_init_polygon_model(Polygon_models[N_polygon_models].model_data);
829 if (highest_texture_num+1 != n_textures)
830 Error("Model <%s> references %d textures but specifies %d.",filename,highest_texture_num+1,n_textures);
832 Polygon_models[N_polygon_models].n_textures = n_textures;
833 Polygon_models[N_polygon_models].first_texture = first_texture;
834 Polygon_models[N_polygon_models].simpler_model = 0;
836 // Assert(polygon_models[N_polygon_models]!=NULL);
840 return N_polygon_models-1;
845 void init_polygon_models()
847 N_polygon_models = 0;
849 atexit(free_polygon_models);
853 //compare against this size when figuring how far to place eye for picture
854 #define BASE_MODEL_SIZE 0x28000
856 #define DEFAULT_VIEW_DIST 0x60000
858 //draws the given model in the current canvas. The distance is set to
859 //more-or-less fill the canvas. Note that this routine actually renders
860 //into an off-screen canvas that it creates, then copies to the current
862 void draw_model_picture(int mn,vms_angvec *orient_angles)
864 vms_vector temp_pos=ZERO_VECTOR;
865 vms_matrix temp_orient = IDENTITY_MATRIX;
867 grs_canvas *save_canv = grd_curcanv,*temp_canv;
870 Assert(mn>=0 && mn<N_polygon_models);
873 ogl_start_offscreen_render(0, 0, grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h);
875 temp_canv = gr_create_canvas(save_canv->cv_bitmap.bm_w,save_canv->cv_bitmap.bm_h);
876 gr_set_current_canvas(temp_canv);
878 gr_clear_canvas( BM_XRGB(0,0,0) );
881 g3_set_view_matrix(&temp_pos,&temp_orient,0x9000);
883 if (Polygon_models[mn].rad != 0)
884 temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST,Polygon_models[mn].rad,BASE_MODEL_SIZE);
886 temp_pos.z = DEFAULT_VIEW_DIST;
888 vm_angles_2_matrix(&temp_orient, orient_angles);
890 draw_polygon_model(&temp_pos,&temp_orient,NULL,mn,0,f1_0,NULL,NULL);
895 ogl_end_offscreen_render();
897 gr_set_current_canvas(save_canv);
899 gr_bitmap(0,0,&temp_canv->cv_bitmap);
901 gr_free_canvas(temp_canv);
907 * reads a polymodel structure from a CFILE
909 extern void polymodel_read(polymodel *pm, CFILE *fp)
913 pm->n_models = cfile_read_int(fp);
914 pm->model_data_size = cfile_read_int(fp);
915 pm->model_data = (ubyte *)(size_t)cfile_read_int(fp); // garbage, read it anyway just for consistency
916 for (i = 0; i < MAX_SUBMODELS; i++)
917 pm->submodel_ptrs[i] = cfile_read_int(fp);
918 for (i = 0; i < MAX_SUBMODELS; i++)
919 cfile_read_vector(&(pm->submodel_offsets[i]), fp);
920 for (i = 0; i < MAX_SUBMODELS; i++)
921 cfile_read_vector(&(pm->submodel_norms[i]), fp);
922 for (i = 0; i < MAX_SUBMODELS; i++)
923 cfile_read_vector(&(pm->submodel_pnts[i]), fp);
924 for (i = 0; i < MAX_SUBMODELS; i++)
925 pm->submodel_rads[i] = cfile_read_fix(fp);
926 cfread(pm->submodel_parents, MAX_SUBMODELS, 1, fp);
927 for (i = 0; i < MAX_SUBMODELS; i++)
928 cfile_read_vector(&(pm->submodel_mins[i]), fp);
929 for (i = 0; i < MAX_SUBMODELS; i++)
930 cfile_read_vector(&(pm->submodel_maxs[i]), fp);
931 cfile_read_vector(&(pm->mins), fp);
932 cfile_read_vector(&(pm->maxs), fp);
933 pm->rad = cfile_read_fix(fp);
934 pm->n_textures = cfile_read_byte(fp);
935 pm->first_texture = cfile_read_short(fp);
936 pm->simpler_model = cfile_read_byte(fp);
940 * reads n polymodel structs from a CFILE
942 extern int polymodel_read_n(polymodel *pm, int n, CFILE *fp)
946 for (i = 0; i < n; i++) {
947 pm[i].n_models = cfile_read_int(fp);
948 pm[i].model_data_size = cfile_read_int(fp);
949 pm->model_data = (ubyte *)(size_t)cfile_read_int(fp); // garbage, read it anyway just for consistency
950 for (j = 0; j < MAX_SUBMODELS; j++)
951 pm[i].submodel_ptrs[j] = cfile_read_int(fp);
952 for (j = 0; j < MAX_SUBMODELS; j++)
953 cfile_read_vector(&(pm[i].submodel_offsets[j]), fp);
954 for (j = 0; j < MAX_SUBMODELS; j++)
955 cfile_read_vector(&(pm[i].submodel_norms[j]), fp);
956 for (j = 0; j < MAX_SUBMODELS; j++)
957 cfile_read_vector(&(pm[i].submodel_pnts[j]), fp);
958 for (j = 0; j < MAX_SUBMODELS; j++)
959 pm[i].submodel_rads[j] = cfile_read_fix(fp);
960 cfread(pm[i].submodel_parents, MAX_SUBMODELS, 1, fp);
961 for (j = 0; j < MAX_SUBMODELS; j++)
962 cfile_read_vector(&(pm[i].submodel_mins[j]), fp);
963 for (j = 0; j < MAX_SUBMODELS; j++)
964 cfile_read_vector(&(pm[i].submodel_maxs[j]), fp);
965 cfile_read_vector(&(pm[i].mins), fp);
966 cfile_read_vector(&(pm[i].maxs), fp);
967 pm[i].rad = cfile_read_fix(fp);
968 pm[i].n_textures = cfile_read_byte(fp);
969 pm[i].first_texture = cfile_read_short(fp);
970 pm[i].simpler_model = cfile_read_byte(fp);
978 * routine which allocates, reads, and inits a polymodel's model_data
980 void polygon_model_data_read(polymodel *pm, CFILE *fp)
982 pm->model_data = d_malloc(pm->model_data_size);
983 Assert(pm->model_data != NULL);
984 cfread(pm->model_data, sizeof(ubyte), pm->model_data_size, fp );
985 #ifdef WORDS_NEED_ALIGNMENT
986 align_polygon_model_data(pm);
988 #ifdef WORDS_BIGENDIAN
989 swap_polygon_model_data(pm->model_data);
991 //verify(pm->model_data);
992 g3_init_polygon_model(pm->model_data);