1 /* $Id: polyobj.c,v 1.17 2004-05-19 03:29:04 btb 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
20 * Revision 1.3 1995/10/25 14:07:07 allender
21 * removed load_poly_model function
23 * Revision 1.2 1995/09/14 14:10:20 allender
24 * two funtions should be void
26 * Revision 1.1 1995/05/16 15:30:08 allender
29 * Revision 2.1 1995/05/26 16:10:37 john
30 * Support for new 4-byte align v8 pof files.
32 * Revision 2.0 1995/02/27 11:32:44 john
33 * New version 2.0, which has no anonymous unions, builds with
34 * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
36 * Revision 1.64 1995/01/14 19:16:43 john
37 * First version of new bitmap paging code.
39 * Revision 1.63 1994/12/14 18:06:54 matt
40 * Removed compile warnings
42 * Revision 1.62 1994/12/09 17:54:31 john
43 * Made the CFILE's close right after reading in data.
45 * Revision 1.61 1994/12/09 16:13:28 mike
46 * speedup pof file reading, but still horribly slow using hog file...problem somewhere else.
48 * Revision 1.60 1994/12/08 17:41:20 yuan
51 * Revision 1.59 1994/11/21 11:02:19 matt
52 * Added error checking
54 * Revision 1.58 1994/11/14 11:32:49 matt
55 * Allow switching to simpler models even when alt_textures specified
57 * Revision 1.57 1994/11/13 21:15:24 matt
58 * Added basic support for more than one level of detail simplification
60 * Revision 1.56 1994/11/11 19:29:25 matt
61 * Added code to show low detail polygon models
63 * Revision 1.55 1994/11/10 14:02:57 matt
64 * Hacked in support for player ships with different textures
66 * Revision 1.54 1994/11/03 11:01:59 matt
67 * Made robot pics lighted
69 * Revision 1.53 1994/11/02 16:18:34 matt
70 * Moved draw_model_picture() out of editor
72 * Revision 1.52 1994/10/18 14:38:11 matt
73 * Restored assert now that bug is fixed
75 * Revision 1.51 1994/10/17 21:35:03 matt
76 * Added support for new Control Center/Main Reactor
78 * Revision 1.50 1994/10/14 17:46:23 yuan
79 * Made the soft Int3 only work in net mode.
81 * Revision 1.49 1994/10/14 17:43:47 yuan
82 * Added soft int3's instead of Asserts for some common network bugs.
84 * Revision 1.48 1994/10/14 17:09:04 yuan
85 * Made Assert on line 610 be if in an attempt
88 * Revision 1.47 1994/09/09 14:23:42 matt
89 * Added glow code to polygon models for engine glow
91 * Revision 1.46 1994/08/26 18:03:30 matt
92 * Added code to remap polygon model numbers by matching filenames
94 * Revision 1.45 1994/08/26 15:35:58 matt
95 * Made eclips usable on more than one object at a time
97 * Revision 1.44 1994/08/25 18:11:58 matt
98 * Made player's weapons and flares fire from the positions on the 3d model.
99 * Also added support for quad lasers.
101 * Revision 1.43 1994/07/25 00:14:18 matt
102 * Made a couple of minor changes for the drivethrough
104 * Revision 1.42 1994/07/25 00:02:41 matt
105 * Various changes to accomodate new 3d, which no longer takes point numbers
106 * as parms, and now only takes pointers to points.
116 static char rcsid[] = "$Id: polyobj.c,v 1.17 2004-05-19 03:29:04 btb Exp $";
123 // -- I hate this warning in make depend! -- #ifdef DRIVE
124 // -- I hate this warning in make depend! -- #include "drive.h"
125 // -- I hate this warning in make depend! -- #else
127 // -- I hate this warning in make depend! -- #endif
137 #include "byteswap.h"
142 #include "textures.h"
144 #include "lighting.h"
149 #include "pa_enabl.h"
152 #include "3dfx_des.h"
156 #include "ogl_init.h"
159 polymodel Polygon_models[MAX_POLYGON_MODELS]; // = {&bot11,&bot17,&robot_s2,&robot_b2,&bot11,&bot17,&robot_s2,&robot_b2};
161 int N_polygon_models = 0;
163 #define MAX_POLYGON_VECS 1000
164 g3s_point robot_points[MAX_POLYGON_VECS];
166 #define PM_COMPATIBLE_VERSION 6
167 #define PM_OBJFILE_VERSION 8
172 #define MODEL_BUF_SIZE 32768
174 void _pof_cfseek(int len,int type)
177 case SEEK_SET: Pof_addr = len; break;
178 case SEEK_CUR: Pof_addr += len; break;
180 Assert(len <= 0); // seeking from end, better be moving back.
181 Pof_addr = Pof_file_end + len;
185 if (Pof_addr > MODEL_BUF_SIZE)
189 #define pof_cfseek(_buf,_len,_type) _pof_cfseek((_len),(_type))
191 int pof_read_int(ubyte *bufp)
195 i = *((int *) &bufp[Pof_addr]);
199 // if (cfread(&i,sizeof(i),1,f) != 1)
200 // Error("Unexpected end-of-file while reading object");
205 size_t pof_cfread(void *dst, size_t elsize, size_t nelem, ubyte *bufp)
207 if (Pof_addr + nelem*elsize > Pof_file_end)
210 memcpy(dst, &bufp[Pof_addr], elsize*nelem);
212 Pof_addr += elsize*nelem;
214 if (Pof_addr > MODEL_BUF_SIZE)
220 // #define new_read_int(i,f) cfread(&(i),sizeof(i),1,(f))
221 #define new_pof_read_int(i,f) pof_cfread(&(i),sizeof(i),1,(f))
223 short pof_read_short(ubyte *bufp)
227 s = *((short *) &bufp[Pof_addr]);
229 return INTEL_SHORT(s);
230 // if (cfread(&s,sizeof(s),1,f) != 1)
231 // Error("Unexpected end-of-file while reading object");
236 void pof_read_string(char *buf,int max_char, ubyte *bufp)
240 for (i=0; i<max_char; i++) {
241 if ((*buf++ = bufp[Pof_addr++]) == 0)
245 // while (max_char-- && (*buf=cfgetc(f)) != 0) buf++;
249 void pof_read_vecs(vms_vector *vecs,int n,ubyte *bufp)
251 // cfread(vecs,sizeof(vms_vector),n,f);
253 memcpy(vecs, &bufp[Pof_addr], n*sizeof(*vecs));
254 Pof_addr += n*sizeof(*vecs);
256 #ifdef WORDS_BIGENDIAN
258 vms_vector_swap(&vecs[--n]);
261 if (Pof_addr > MODEL_BUF_SIZE)
265 void pof_read_angs(vms_angvec *angs,int n,ubyte *bufp)
267 memcpy(angs, &bufp[Pof_addr], n*sizeof(*angs));
268 Pof_addr += n*sizeof(*angs);
270 #ifdef WORDS_BIGENDIAN
272 vms_angvec_swap(&angs[--n]);
275 if (Pof_addr > MODEL_BUF_SIZE)
279 #define ID_OHDR 0x5244484f // 'RDHO' //Object header
280 #define ID_SOBJ 0x4a424f53 // 'JBOS' //Subobject header
281 #define ID_GUNS 0x534e5547 // 'SNUG' //List of guns on this object
282 #define ID_ANIM 0x4d494e41 // 'MINA' //Animation data
283 #define ID_IDTA 0x41544449 // 'ATDI' //Interpreter data
284 #define ID_TXTR 0x52545854 // 'RTXT' //Texture filename list
287 #define robot_info void
289 vms_angvec anim_angs[N_ANIM_STATES][MAX_SUBMODELS];
291 //set the animation angles for this robot. Gun fields of robot info must
293 void robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS]);
296 #define DEBUG_LEVEL CON_NORMAL
298 #ifdef WORDS_NEED_ALIGNMENT
299 ubyte * old_dest(chunk o) // return where chunk is (in unaligned struct)
301 return o.old_base + INTEL_SHORT(*((short *)(o.old_base + o.offset)));
303 ubyte * new_dest(chunk o) // return where chunk is (in aligned struct)
305 return o.new_base + INTEL_SHORT(*((short *)(o.old_base + o.offset))) + o.correction;
308 * find chunk with smallest address
310 int get_first_chunks_index(chunk *chunk_list, int no_chunks)
312 int i, first_index = 0;
313 Assert(no_chunks >= 1);
314 for (i = 1; i < no_chunks; i++)
315 if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index]))
319 #define SHIFT_SPACE 500 // increase if insufficent
321 void align_polygon_model_data(polymodel *pm)
324 int total_correction = 0;
325 ubyte *cur_old, *cur_new;
327 chunk ch_list[MAX_CHUNKS];
329 int tmp_size = pm->model_data_size + SHIFT_SPACE;
330 ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data
333 //start with first chunk (is always aligned!)
334 cur_old = pm->model_data;
336 chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
337 memcpy(cur_new, cur_old, chunk_len);
338 while (no_chunks > 0) {
339 int first_index = get_first_chunks_index(ch_list, no_chunks);
340 cur_ch = ch_list[first_index];
341 // remove first chunk from array:
343 for (i = first_index; i < no_chunks; i++)
344 ch_list[i] = ch_list[i + 1];
345 // if (new) address unaligned:
346 if ((u_int32_t)new_dest(cur_ch) % 4L != 0) {
347 // calculate how much to move to be aligned
348 short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L;
349 // correct chunks' addresses
350 cur_ch.correction += to_shift;
351 for (i = 0; i < no_chunks; i++)
352 ch_list[i].correction += to_shift;
353 total_correction += to_shift;
354 Assert((u_int32_t)new_dest(cur_ch) % 4L == 0);
355 Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE
357 //write (corrected) chunk for current chunk:
358 *((short *)(cur_ch.new_base + cur_ch.offset))
359 = INTEL_SHORT(cur_ch.correction
360 + INTEL_SHORT(*((short *)(cur_ch.old_base + cur_ch.offset))));
361 //write (correctly aligned) chunk:
362 cur_old = old_dest(cur_ch);
363 cur_new = new_dest(cur_ch);
364 chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
365 memcpy(cur_new, cur_old, chunk_len);
366 //correct submodel_ptr's for pm, too
367 for (i = 0; i < MAX_SUBMODELS; i++)
368 if (pm->model_data + pm->submodel_ptrs[i] >= cur_old
369 && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len)
370 pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data);
372 d_free(pm->model_data);
373 pm->model_data_size += total_correction;
374 pm->model_data = d_malloc(pm->model_data_size);
375 Assert(pm->model_data != NULL);
376 memcpy(pm->model_data, tmp, pm->model_data_size);
379 #endif //def WORDS_NEED_ALIGNMENT
381 //reads a binary file containing a 3d model
382 polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r)
386 int id,len, next_chunk;
390 model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) );
392 Error("Can't allocate space to read model %s\n", filename);
394 if ((ifile=cfopen(filename,"rb"))==NULL)
395 Error("Can't open file <%s>",filename);
397 Assert(cfilelength(ifile) <= MODEL_BUF_SIZE);
400 Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
403 id = pof_read_int(model_buf);
405 if (id!=0x4f505350) /* 'OPSP' */
406 Error("Bad ID in model file <%s>",filename);
408 version = pof_read_short(model_buf);
410 if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
411 Error("Bad version (%d) in model file <%s>",version,filename);
413 if ( FindArg( "-bspgen" ))
414 printf( "bspgen -c1" );
416 while (new_pof_read_int(id,model_buf) == 1) {
418 //id = pof_read_int(model_buf);
419 len = pof_read_int(model_buf);
420 next_chunk = Pof_addr + len;
424 case ID_OHDR: { //Object header
425 vms_vector pmmin,pmmax;
427 //con_printf(DEBUG_LEVEL, "Got chunk OHDR, len=%d\n",len);
429 pm->n_models = pof_read_int(model_buf);
430 pm->rad = pof_read_int(model_buf);
432 Assert(pm->n_models <= MAX_SUBMODELS);
434 pof_read_vecs(&pmmin,1,model_buf);
435 pof_read_vecs(&pmmax,1,model_buf);
437 if ( FindArg( "-bspgen" )) {
441 vm_vec_sub(&v, &pmmax, &pmmin );
443 if ( v.y > l ) l = v.y;
444 if ( v.z > l ) l = v.z;
446 printf( " -l%.3f", f2fl(l) );
452 case ID_SOBJ: { //Subobject header
457 //con_printf(DEBUG_LEVEL, "Got chunk SOBJ, len=%d\n",len);
459 n = pof_read_short(model_buf);
461 Assert(n < MAX_SUBMODELS);
463 pm->submodel_parents[n] = pof_read_short(model_buf);
465 pof_read_vecs(&pm->submodel_norms[n],1,model_buf);
466 pof_read_vecs(&pm->submodel_pnts[n],1,model_buf);
467 pof_read_vecs(&pm->submodel_offsets[n],1,model_buf);
469 pm->submodel_rads[n] = pof_read_int(model_buf); //radius
471 pm->submodel_ptrs[n] = pof_read_int(model_buf); //offset
478 case ID_GUNS: { //List of guns on this object
480 //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len);
485 ubyte gun_used[MAX_GUNS];
487 r->n_guns = pof_read_int(model_buf);
492 Assert(r->n_guns <= MAX_GUNS);
494 for (i=0;i<r->n_guns;i++)
497 for (i=0;i<r->n_guns;i++) {
500 id = pof_read_short(model_buf);
501 Assert(id < r->n_guns);
502 Assert(gun_used[id] == 0);
504 r->gun_submodels[id] = pof_read_short(model_buf);
505 Assert(r->gun_submodels[id] != 0xff);
506 pof_read_vecs(&r->gun_points[id],1,model_buf);
509 pof_read_vecs(&gun_dir,1,model_buf);
513 pof_cfseek(model_buf,len,SEEK_CUR);
518 case ID_ANIM: //Animation data
519 //con_printf(DEBUG_LEVEL, "Got chunk ANIM, len=%d\n",len);
526 n_frames = pof_read_short(model_buf);
528 Assert(n_frames == N_ANIM_STATES);
530 for (m=0;m<pm->n_models;m++)
531 for (f=0;f<n_frames;f++)
532 pof_read_angs(&anim_angs[f][m], 1, model_buf);
535 robot_set_angles(r,pm,anim_angs);
539 pof_cfseek(model_buf,len,SEEK_CUR);
544 case ID_TXTR: { //Texture filename list
548 //con_printf(DEBUG_LEVEL, "Got chunk TXTR, len=%d\n",len);
550 n = pof_read_short(model_buf);
551 //con_printf(DEBUG_LEVEL, " num textures = %d\n",n);
553 pof_read_string(name_buf,128,model_buf);
554 //con_printf(DEBUG_LEVEL, "<%s>\n",name_buf);
560 case ID_IDTA: //Interpreter data
561 //con_printf(DEBUG_LEVEL, "Got chunk IDTA, len=%d\n",len);
563 pm->model_data = d_malloc(len);
564 pm->model_data_size = len;
566 pof_cfread(pm->model_data,1,len,model_buf);
571 //con_printf(DEBUG_LEVEL, "Unknown chunk <%c%c%c%c>, len = %d\n",id,id>>8,id>>16,id>>24,len);
572 pof_cfseek(model_buf,len,SEEK_CUR);
576 if ( version >= 8 ) // Version 8 needs 4-byte alignment!!!
577 pof_cfseek(model_buf,next_chunk,SEEK_SET);
580 // for (i=0;i<pm->n_models;i++)
581 // pm->submodel_ptrs[i] += (int) pm->model_data;
583 if ( FindArg( "-bspgen" )) {
584 char *p = strchr( filename, '.' );
590 printf( " %s.3ds\n", filename );
596 #ifdef WORDS_NEED_ALIGNMENT
597 align_polygon_model_data(pm);
599 #ifdef WORDS_BIGENDIAN
600 swap_polygon_model_data(pm->model_data);
602 //verify(pm->model_data);
607 //reads the gun information for a model
608 //fills in arrays gun_points & gun_dirs, returns the number of guns read
609 int read_model_guns(char *filename,vms_vector *gun_points, vms_vector *gun_dirs, int *gun_submodels)
617 model_buf = (ubyte *)d_malloc( MODEL_BUF_SIZE * sizeof(ubyte) );
619 Error("Can't allocate space to read model %s\n", filename);
621 if ((ifile=cfopen(filename,"rb"))==NULL)
622 Error("Can't open file <%s>",filename);
624 Assert(cfilelength(ifile) <= MODEL_BUF_SIZE);
627 Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
630 id = pof_read_int(model_buf);
632 if (id!=0x4f505350) /* 'OPSP' */
633 Error("Bad ID in model file <%s>",filename);
635 version = pof_read_short(model_buf);
637 Assert(version >= 7); //must be 7 or higher for this data
639 if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
640 Error("Bad version (%d) in model file <%s>",version,filename);
642 while (new_pof_read_int(id,model_buf) == 1) {
644 //id = pof_read_int(model_buf);
645 len = pof_read_int(model_buf);
647 if (id == ID_GUNS) { //List of guns on this object
649 //con_printf(DEBUG_LEVEL, "Got chunk GUNS, len=%d\n",len);
653 n_guns = pof_read_int(model_buf);
655 for (i=0;i<n_guns;i++) {
658 id = pof_read_short(model_buf);
659 sm = pof_read_short(model_buf);
661 gun_submodels[id] = sm;
663 Error("Invalid gun submodel in file <%s>",filename);
664 pof_read_vecs(&gun_points[id],1,model_buf);
666 pof_read_vecs(&gun_dirs[id],1,model_buf);
671 pof_cfseek(model_buf,len,SEEK_CUR);
680 //free up a model, getting rid of all its memory
681 void free_model(polymodel *po)
683 d_free(po->model_data);
686 grs_bitmap *texture_list[MAX_POLYOBJ_TEXTURES];
687 bitmap_index texture_list_index[MAX_POLYOBJ_TEXTURES];
689 int Simple_model_threshhold_scale=5; //switch when this times radius far away
692 //draw a polygon model
694 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[])
698 PA_DFX (int save_light);
700 Assert(model_num < N_polygon_models);
702 po=&Polygon_models[model_num];
704 //check if should use simple model
705 if (po->simpler_model ) //must have a simpler model
706 if (flags==0) //can't switch if this is debris
707 //!!if (!alt_textures) { //alternate textures might not match
708 //alt textures might not match, but in the one case we're using this
709 //for on 11/14/94, they do match. So we leave it in.
714 depth = g3_calc_point_depth(pos); //gets 3d depth
716 while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad)
717 po = &Polygon_models[po->simpler_model-1];
722 for (i=0;i<po->n_textures;i++) {
723 texture_list_index[i] = alt_textures[i];
724 texture_list[i] = &GameBitmaps[alt_textures[i].index];
727 texture_list[i]->bm_handle = texture_list_index[i].index;
733 for (i=0;i<po->n_textures;i++) {
734 texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
735 texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index];
738 texture_list[i]->bm_handle = texture_list_index[i].index;
743 #ifdef PIGGY_USE_PAGING
744 // Make sure the textures for this object are paged in...
745 piggy_page_flushed = 0;
746 for (i=0;i<po->n_textures;i++)
747 PIGGY_PAGE_IN( texture_list_index[i] );
748 // Hmmm... cache got flushed in the middle of paging all these in,
749 // so we need to reread them all in.
750 if (piggy_page_flushed) {
751 piggy_page_flushed = 0;
752 for (i=0;i<po->n_textures;i++)
753 PIGGY_PAGE_IN( texture_list_index[i] );
755 // Make sure that they can all fit in memory.
756 Assert( piggy_page_flushed == 0 );
759 g3_start_instance_matrix(pos,orient);
761 g3_set_interp_points(robot_points);
764 _3dfx_rendering_poly_obj = 1;
766 PA_DFX(save_light = Lighting_on);
767 PA_DFX(Lighting_on = 0);
769 if (flags == 0) //draw entire object
771 g3_draw_polygon_model(po->model_data,texture_list,anim_angles,light,glow_values);
776 for (i=0;flags;flags>>=1,i++)
780 Assert(i < po->n_models);
782 //if submodel, rotate around its center point, not pivot point
784 vm_vec_avg(&ofs,&po->submodel_mins[i],&po->submodel_maxs[i]);
786 g3_start_instance_matrix(&ofs,NULL);
788 g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]],texture_list,anim_angles,light,glow_values);
797 _3dfx_rendering_poly_obj = 0;
800 PA_DFX (Lighting_on = save_light);
805 void free_polygon_models()
809 for (i=0;i<N_polygon_models;i++) {
810 free_model(&Polygon_models[i]);
815 void polyobj_find_min_max(polymodel *pm)
821 vms_vector *big_mn,*big_mx;
826 for (m=0;m<pm->n_models;m++) {
827 vms_vector *mn,*mx,*ofs;
829 mn = &pm->submodel_mins[m];
830 mx = &pm->submodel_maxs[m];
831 ofs= &pm->submodel_offsets[m];
833 data = (ushort *)&pm->model_data[pm->submodel_ptrs[m]];
837 Assert(type == 7 || type == 1);
842 data+=2; //skip start & pad
844 vp = (vms_vector *) data;
846 *mn = *mx = *vp++; nverts--;
849 *big_mn = *big_mx = *mn;
852 if (vp->x > mx->x) mx->x = vp->x;
853 if (vp->y > mx->y) mx->y = vp->y;
854 if (vp->z > mx->z) mx->z = vp->z;
856 if (vp->x < mn->x) mn->x = vp->x;
857 if (vp->y < mn->y) mn->y = vp->y;
858 if (vp->z < mn->z) mn->z = vp->z;
860 if (vp->x+ofs->x > big_mx->x) big_mx->x = vp->x+ofs->x;
861 if (vp->y+ofs->y > big_mx->y) big_mx->y = vp->y+ofs->y;
862 if (vp->z+ofs->z > big_mx->z) big_mx->z = vp->z+ofs->z;
864 if (vp->x+ofs->x < big_mn->x) big_mn->x = vp->x+ofs->x;
865 if (vp->y+ofs->y < big_mn->y) big_mn->y = vp->y+ofs->y;
866 if (vp->z+ofs->z < big_mn->z) big_mn->z = vp->z+ofs->z;
871 // printf("Submodel %d: (%8x,%8x) (%8x,%8x) (%8x,%8x)\n",m,mn->x,mx->x,mn->y,mx->y,mn->z,mx->z);
874 // 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);
878 extern short highest_texture_num; //from the 3d
880 char Pof_names[MAX_POLYGON_MODELS][FILENAME_LEN];
882 //returns the number of this model
884 int load_polygon_model(char *filename,int n_textures,int first_texture,robot_info *r)
886 int load_polygon_model(char *filename,int n_textures,grs_bitmap ***textures)
893 Assert(N_polygon_models < MAX_POLYGON_MODELS);
894 Assert(n_textures < MAX_POLYOBJ_TEXTURES);
896 // MK was real tired of those useless, slow mprintfs...
897 if (N_polygon_models > MAX_POLYGON_MODELS - 10)
898 mprintf(( 0, "Used %d/%d polygon model slots\n", N_polygon_models+1, MAX_POLYGON_MODELS ));
900 Assert(strlen(filename) <= 12);
901 strcpy(Pof_names[N_polygon_models],filename);
903 read_model_file(&Polygon_models[N_polygon_models],filename,r);
905 polyobj_find_min_max(&Polygon_models[N_polygon_models]);
907 g3_init_polygon_model(Polygon_models[N_polygon_models].model_data);
909 if (highest_texture_num+1 != n_textures)
910 Error("Model <%s> references %d textures but specifies %d.",filename,highest_texture_num+1,n_textures);
912 Polygon_models[N_polygon_models].n_textures = n_textures;
913 Polygon_models[N_polygon_models].first_texture = first_texture;
914 Polygon_models[N_polygon_models].simpler_model = 0;
916 // Assert(polygon_models[N_polygon_models]!=NULL);
920 return N_polygon_models-1;
925 void init_polygon_models()
927 N_polygon_models = 0;
929 atexit((void (*)())free_polygon_models);
933 //compare against this size when figuring how far to place eye for picture
934 #define BASE_MODEL_SIZE 0x28000
936 #define DEFAULT_VIEW_DIST 0x60000
938 //draws the given model in the current canvas. The distance is set to
939 //more-or-less fill the canvas. Note that this routine actually renders
940 //into an off-screen canvas that it creates, then copies to the current
942 void draw_model_picture(int mn,vms_angvec *orient_angles)
944 vms_vector temp_pos=ZERO_VECTOR;
945 vms_matrix temp_orient = IDENTITY_MATRIX;
947 grs_canvas *save_canv = grd_curcanv,*temp_canv;
950 Assert(mn>=0 && mn<N_polygon_models);
953 ogl_start_offscreen_render(0, 0, grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h);
955 temp_canv = gr_create_canvas(save_canv->cv_bitmap.bm_w,save_canv->cv_bitmap.bm_h);
956 gr_set_current_canvas(temp_canv);
958 gr_clear_canvas( BM_XRGB(0,0,0) );
961 g3_set_view_matrix(&temp_pos,&temp_orient,0x9000);
963 if (Polygon_models[mn].rad != 0)
964 temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST,Polygon_models[mn].rad,BASE_MODEL_SIZE);
966 temp_pos.z = DEFAULT_VIEW_DIST;
968 vm_angles_2_matrix(&temp_orient, orient_angles);
970 PA_DFX(save_light = Lighting_on);
971 PA_DFX(Lighting_on = 0);
972 draw_polygon_model(&temp_pos,&temp_orient,NULL,mn,0,f1_0,NULL,NULL);
973 PA_DFX (Lighting_on = save_light);
978 ogl_end_offscreen_render();
980 gr_set_current_canvas(save_canv);
982 gr_bitmap(0,0,&temp_canv->cv_bitmap);
984 gr_free_canvas(temp_canv);
990 * reads a polymodel structure from a CFILE
992 extern void polymodel_read(polymodel *pm, CFILE *fp)
996 pm->n_models = cfile_read_int(fp);
997 pm->model_data_size = cfile_read_int(fp);
998 pm->model_data = (ubyte *) cfile_read_int(fp);
999 for (i = 0; i < MAX_SUBMODELS; i++)
1000 pm->submodel_ptrs[i] = cfile_read_int(fp);
1001 for (i = 0; i < MAX_SUBMODELS; i++)
1002 cfile_read_vector(&(pm->submodel_offsets[i]), fp);
1003 for (i = 0; i < MAX_SUBMODELS; i++)
1004 cfile_read_vector(&(pm->submodel_norms[i]), fp);
1005 for (i = 0; i < MAX_SUBMODELS; i++)
1006 cfile_read_vector(&(pm->submodel_pnts[i]), fp);
1007 for (i = 0; i < MAX_SUBMODELS; i++)
1008 pm->submodel_rads[i] = cfile_read_fix(fp);
1009 cfread(pm->submodel_parents, MAX_SUBMODELS, 1, fp);
1010 for (i = 0; i < MAX_SUBMODELS; i++)
1011 cfile_read_vector(&(pm->submodel_mins[i]), fp);
1012 for (i = 0; i < MAX_SUBMODELS; i++)
1013 cfile_read_vector(&(pm->submodel_maxs[i]), fp);
1014 cfile_read_vector(&(pm->mins), fp);
1015 cfile_read_vector(&(pm->maxs), fp);
1016 pm->rad = cfile_read_fix(fp);
1017 pm->n_textures = cfile_read_byte(fp);
1018 pm->first_texture = cfile_read_short(fp);
1019 pm->simpler_model = cfile_read_byte(fp);
1023 * reads n polymodel structs from a CFILE
1025 extern int polymodel_read_n(polymodel *pm, int n, CFILE *fp)
1029 for (i = 0; i < n; i++) {
1030 pm[i].n_models = cfile_read_int(fp);
1031 pm[i].model_data_size = cfile_read_int(fp);
1032 pm[i].model_data = (ubyte *) cfile_read_int(fp);
1033 for (j = 0; j < MAX_SUBMODELS; j++)
1034 pm[i].submodel_ptrs[j] = cfile_read_int(fp);
1035 for (j = 0; j < MAX_SUBMODELS; j++)
1036 cfile_read_vector(&(pm[i].submodel_offsets[j]), fp);
1037 for (j = 0; j < MAX_SUBMODELS; j++)
1038 cfile_read_vector(&(pm[i].submodel_norms[j]), fp);
1039 for (j = 0; j < MAX_SUBMODELS; j++)
1040 cfile_read_vector(&(pm[i].submodel_pnts[j]), fp);
1041 for (j = 0; j < MAX_SUBMODELS; j++)
1042 pm[i].submodel_rads[j] = cfile_read_fix(fp);
1043 cfread(pm[i].submodel_parents, MAX_SUBMODELS, 1, fp);
1044 for (j = 0; j < MAX_SUBMODELS; j++)
1045 cfile_read_vector(&(pm[i].submodel_mins[j]), fp);
1046 for (j = 0; j < MAX_SUBMODELS; j++)
1047 cfile_read_vector(&(pm[i].submodel_maxs[j]), fp);
1048 cfile_read_vector(&(pm[i].mins), fp);
1049 cfile_read_vector(&(pm[i].maxs), fp);
1050 pm[i].rad = cfile_read_fix(fp);
1051 pm[i].n_textures = cfile_read_byte(fp);
1052 pm[i].first_texture = cfile_read_short(fp);
1053 pm[i].simpler_model = cfile_read_byte(fp);
1061 * routine which allocates, reads, and inits a polymodel's model_data
1063 void polygon_model_data_read(polymodel *pm, CFILE *fp)
1065 pm->model_data = d_malloc(pm->model_data_size);
1066 Assert(pm->model_data != NULL);
1067 cfread(pm->model_data, sizeof(ubyte), pm->model_data_size, fp );
1068 #ifdef WORDS_NEED_ALIGNMENT
1069 align_polygon_model_data(pm);
1071 #ifdef WORDS_BIGENDIAN
1072 swap_polygon_model_data(pm->model_data);
1074 //verify(pm->model_data);
1075 g3_init_polygon_model(pm->model_data);