home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / p.c < prev    next >
Text File  |  1998-06-08  |  20KB  |  784 lines

  1. /*
  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-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/main/rcs/polyobj.c $
  15.  * $Revision: 2.0 $
  16.  * $Author: john $
  17.  * $Date: 1995/02/27 11:32:44 $
  18.  * 
  19.  * Hacked-in polygon objects
  20.  * 
  21.  * $Log: polyobj.c $
  22.  * Revision 2.0  1995/02/27  11:32:44  john
  23.  * New version 2.0, which has no anonymous unions, builds with
  24.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  25.  * 
  26.  * Revision 1.64  1995/01/14  19:16:43  john
  27.  * First version of new bitmap paging code.
  28.  * 
  29.  * Revision 1.63  1994/12/14  18:06:54  matt
  30.  * Removed compile warnings
  31.  * 
  32.  * Revision 1.62  1994/12/09  17:54:31  john
  33.  * Made the CFILE's close right after reading in data.
  34.  * 
  35.  * Revision 1.61  1994/12/09  16:13:28  mike
  36.  * speedup pof file reading, but still horribly slow using hog file...problem somewhere else.
  37.  * 
  38.  * Revision 1.60  1994/12/08  17:41:20  yuan
  39.  * Cfiling stuff.
  40.  * 
  41.  * Revision 1.59  1994/11/21  11:02:19  matt
  42.  * Added error checking
  43.  * 
  44.  * Revision 1.58  1994/11/14  11:32:49  matt
  45.  * Allow switching to simpler models even when alt_textures specified
  46.  * 
  47.  * Revision 1.57  1994/11/13  21:15:24  matt
  48.  * Added basic support for more than one level of detail simplification
  49.  * 
  50.  * Revision 1.56  1994/11/11  19:29:25  matt
  51.  * Added code to show low detail polygon models
  52.  * 
  53.  * Revision 1.55  1994/11/10  14:02:57  matt
  54.  * Hacked in support for player ships with different textures
  55.  * 
  56.  * Revision 1.54  1994/11/03  11:01:59  matt
  57.  * Made robot pics lighted
  58.  * 
  59.  * Revision 1.53  1994/11/02  16:18:34  matt
  60.  * Moved draw_model_picture() out of editor
  61.  * 
  62.  * Revision 1.52  1994/10/18  14:38:11  matt
  63.  * Restored assert now that bug is fixed
  64.  * 
  65.  * Revision 1.51  1994/10/17  21:35:03  matt
  66.  * Added support for new Control Center/Main Reactor
  67.  * 
  68.  * Revision 1.50  1994/10/14  17:46:23  yuan
  69.  * Made the soft Int3 only work in net mode.
  70.  * 
  71.  * Revision 1.49  1994/10/14  17:43:47  yuan
  72.  * Added soft int3's instead of Asserts  for some common network bugs.
  73.  * 
  74.  * Revision 1.48  1994/10/14  17:09:04  yuan
  75.  * Made Assert on line 610 be if in an attempt
  76.  * to bypass.
  77.  * 
  78.  * Revision 1.47  1994/09/09  14:23:42  matt
  79.  * Added glow code to polygon models for engine glow
  80.  * 
  81.  * Revision 1.46  1994/08/26  18:03:30  matt
  82.  * Added code to remap polygon model numbers by matching filenames
  83.  * 
  84.  * Revision 1.45  1994/08/26  15:35:58  matt
  85.  * Made eclips usable on more than one object at a time
  86.  * 
  87.  * Revision 1.44  1994/08/25  18:11:58  matt
  88.  * Made player's weapons and flares fire from the positions on the 3d model.
  89.  * Also added support for quad lasers.
  90.  * 
  91.  * Revision 1.43  1994/07/25  00:14:18  matt
  92.  * Made a couple of minor changes for the drivethrough
  93.  * 
  94.  * Revision 1.42  1994/07/25  00:02:41  matt
  95.  * Various changes to accomodate new 3d, which no longer takes point numbers
  96.  * as parms, and now only takes pointers to points.
  97.  * 
  98.  */
  99.  
  100.  
  101. #pragma off (unreferenced)
  102. static char rcsid[] = "$Id: polyobj.c 2.0 1995/02/27 11:32:44 john Exp $";
  103. #pragma on (unreferenced)
  104.  
  105. #include <stdio.h>
  106. #include <stdlib.h>
  107. #include <string.h>
  108. #include <io.h>
  109.  
  110. #ifdef DRIVE
  111. #include "drive.h"
  112. #else
  113. #include "inferno.h"
  114. #endif
  115.  
  116. #include "polyobj.h"
  117.  
  118. #include "vecmat.h"
  119. #include "3d.h"
  120. #include "error.h"
  121. #include "mono.h"
  122. #include "mem.h"
  123. #include "args.h"
  124.  
  125. #ifndef DRIVE
  126. #include "texmap.h"
  127. #include "bm.h"
  128. #include "textures.h"
  129. #include "object.h"
  130. #include "lighting.h"
  131. #include "cfile.h"
  132. #include "piggy.h"
  133. #endif
  134.  
  135. polymodel Polygon_models[MAX_POLYGON_MODELS];    // = {&bot11,&bot17,&robot_s2,&robot_b2,&bot11,&bot17,&robot_s2,&robot_b2};
  136.  
  137. int N_polygon_models = 0;
  138.  
  139. #define MAX_POLYGON_VECS 1000
  140. g3s_point robot_points[MAX_POLYGON_VECS];
  141.  
  142. #define PM_COMPATIBLE_VERSION 6
  143. #define PM_OBJFILE_VERSION 7
  144.  
  145. int    Pof_file_end;
  146. int    Pof_addr;
  147.  
  148. #define    MODEL_BUF_SIZE    32768
  149.  
  150. void _pof_cfseek(int len,int type)
  151. {
  152.     switch (type) {
  153.         case SEEK_SET:    Pof_addr = len;    break;
  154.         case SEEK_CUR:    Pof_addr += len;    break;
  155.         case SEEK_END:
  156.             Assert(len <= 0);    //    seeking from end, better be moving back.
  157.             Pof_addr = Pof_file_end + len;
  158.             break;
  159.     }
  160.  
  161.     if (Pof_addr > MODEL_BUF_SIZE)
  162.         Int3();
  163. }
  164.  
  165. #define pof_cfseek(_buf,_len,_type) _pof_cfseek((_len),(_type))
  166.  
  167. int pof_read_int(ubyte *bufp)
  168. {
  169.     int i;
  170.  
  171.     i = *((int *) &bufp[Pof_addr]);
  172.     Pof_addr += 4;
  173.     return i;
  174.  
  175. //    if (cfread(&i,sizeof(i),1,f) != 1)
  176. //        Error("Unexpected end-of-file while reading object");
  177. //
  178. //    return i;
  179. }
  180.  
  181. size_t pof_cfread(void *dst, size_t elsize, size_t nelem, ubyte *bufp)
  182. {
  183.     if (Pof_addr + nelem*elsize > Pof_file_end)
  184.         return 0;
  185.  
  186.     memcpy(dst, &bufp[Pof_addr], elsize*nelem);
  187.  
  188.     Pof_addr += elsize*nelem;
  189.  
  190.     if (Pof_addr > MODEL_BUF_SIZE)
  191.         Int3();
  192.  
  193.     return nelem;
  194. }
  195.  
  196. // #define new_read_int(i,f) cfread(&(i),sizeof(i),1,(f))
  197. #define new_pof_read_int(i,f) pof_cfread(&(i),sizeof(i),1,(f))
  198.  
  199. short pof_read_short(ubyte *bufp)
  200. {
  201.     short s;
  202.  
  203.     s = *((short *) &bufp[Pof_addr]);
  204.     Pof_addr += 2;
  205.     return s;
  206. //    if (cfread(&s,sizeof(s),1,f) != 1)
  207. //        Error("Unexpected end-of-file while reading object");
  208. //
  209. //    return s;
  210. }
  211.  
  212. pof_read_string(char *buf,int max, ubyte *bufp)
  213. {
  214.     int    i;
  215.  
  216.     for (i=0; i<max; i++) {
  217.         if ((*buf++ = bufp[Pof_addr++]) == 0)
  218.             break;
  219.     }
  220.  
  221. //    while (max-- && (*buf=cfgetc(f)) != 0) buf++;
  222.  
  223. }
  224.  
  225. pof_read_vecs(vms_vector *vecs,int n,ubyte *bufp)
  226. {
  227. //    cfread(vecs,sizeof(vms_vector),n,f);
  228.  
  229.     memcpy(vecs, &bufp[Pof_addr], n*sizeof(*vecs));
  230.     Pof_addr += n*sizeof(*vecs);
  231.     
  232.     if (Pof_addr > MODEL_BUF_SIZE)
  233.         Int3();
  234. }
  235.  
  236. #define ID_OHDR 'RDHO'    //Object header
  237. #define ID_SOBJ 'JBOS'    //Subobject header
  238. #define ID_GUNS 'SNUG'    //List of guns on this object
  239. #define ID_ANIM 'MINA'    //Animation data
  240. #define ID_IDTA 'ATDI'    //Interpreter data
  241. #define ID_TXTR 'RTXT'    //Texture filename list
  242.  
  243. #ifdef DRIVE
  244. #define robot_info void
  245. #else
  246. vms_angvec anim_angs[N_ANIM_STATES][MAX_SUBMODELS];
  247.  
  248. //set the animation angles for this robot.  Gun fields of robot info must
  249. //be filled in.
  250. robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS]);
  251. #endif
  252.  
  253. //reads a binary file containing a 3d model
  254. polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r)
  255. {
  256.     CFILE *ifile;
  257.     short version;
  258.     int id,len, next_chunk;
  259.     ubyte    model_buf[MODEL_BUF_SIZE];
  260.  
  261.     if ((ifile=cfopen(filename,"rb"))==NULL) 
  262.         Error("Can't open file <%s>",filename);
  263.  
  264.     Assert(ifile->size <= MODEL_BUF_SIZE);
  265.  
  266.     Pof_addr = 0;
  267.     Pof_file_end = cfread(model_buf, 1, cfilelength(ifile), ifile);
  268.     cfclose(ifile);
  269.  
  270.     id = pof_read_int(model_buf);
  271.  
  272.     if (id!='OPSP')
  273.         Error("Bad ID in model file <%s>",filename);
  274.  
  275.     version = pof_read_short(model_buf);
  276.     
  277.     if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
  278.         Error("Bad version (%d) in model file <%s>",version,filename);
  279.  
  280.     if ( FindArg( "-bspgen" )) 
  281.         fprintf( stderr, "bspgen -c1" );
  282.  
  283.     while (new_pof_read_int(id,model_buf) == 1) {
  284.  
  285.         //id  = pof_read_int(model_buf);
  286.         len = pof_read_int(model_buf);
  287.         next_chunk = Pof_addr + len;
  288.                         
  289.         switch (id) {
  290.  
  291.             case ID_OHDR: {        //Object header
  292.                 vms_vector pmmin,pmmax;
  293.  
  294.                 //mprintf(0,"Got chunk OHDR, len=%d\n",len);
  295.  
  296.                 pm->n_models = pof_read_int(model_buf);
  297.                 pm->rad = pof_read_int(model_buf);
  298.  
  299.                 Assert(pm->n_models <= MAX_SUBMODELS);
  300.  
  301.                 pof_read_vecs(&pmmin,1,model_buf);
  302.                 pof_read_vecs(&pmmax,1,model_buf);
  303.  
  304.                 if ( FindArg( "-bspgen" ))    {
  305.                     vms_vector v;
  306.                     fix l;
  307.                 
  308.                     vm_vec_sub(&v, &pmmax, &pmmin );
  309.                     l = v.x;
  310.                     if ( v.y > l ) l = v.y;                    
  311.                     if ( v.z > l ) l = v.z;                    
  312.                                                     
  313.                     fprintf( stderr, " -l%.3f", f2fl(l) );
  314.                 }
  315.  
  316.                 break;
  317.             }
  318.             
  319.             case ID_SOBJ: {        //Subobject header
  320.                 int n;
  321.  
  322.                 //mprintf(0,"Got chunk SOBJ, len=%d\n",len);
  323.  
  324.                 n = pof_read_short(model_buf);
  325.  
  326.                 Assert(n < MAX_SUBMODELS);
  327.  
  328.                 pm->submodel_parents[n] = pof_read_short(model_buf);
  329.  
  330.                 pof_read_vecs(&pm->submodel_norms[n],1,model_buf);
  331.                 pof_read_vecs(&pm->submodel_pnts[n],1,model_buf);
  332.                 pof_read_vecs(&pm->submodel_offsets[n],1,model_buf);
  333.  
  334.                 pm->submodel_rads[n] = pof_read_int(model_buf);        //radius
  335.  
  336.                 pm->submodel_ptrs[n] = pof_read_int(model_buf);    //offset
  337.  
  338.                 break;
  339.  
  340.             }
  341.             
  342.             #ifndef DRIVE
  343.             case ID_GUNS: {        //List of guns on this object
  344.  
  345.                 //mprintf(0,"Got chunk GUNS, len=%d\n",len);
  346.  
  347.                 if (r) {
  348.                     int i;
  349.                     vms_vector gun_dir;
  350.  
  351.                     r->n_guns = pof_read_int(model_buf);
  352.  
  353.                     Assert(r->n_guns <= MAX_GUNS);
  354.  
  355.                     for (i=0;i<r->n_guns;i++) {
  356.                         int id;
  357.  
  358.                         id = pof_read_short(model_buf);
  359.                         r->gun_submodels[id] = pof_read_short(model_buf);
  360.                         Assert(r->gun_submodels[id] != 0xff);
  361.                         pof_read_vecs(&r->gun_points[id],1,model_buf);
  362.  
  363.                         if (version >= 7)
  364.                             pof_read_vecs(&gun_dir,1,model_buf);
  365.                     }
  366.                 }
  367.                 else
  368.                     pof_cfseek(model_buf,len,SEEK_CUR);
  369.  
  370.                 break;
  371.             }
  372.             
  373.             case ID_ANIM:        //Animation data
  374.                 //mprintf(0,"Got chunk ANIM, len=%d\n",len);
  375.  
  376.                 if ( FindArg( "-bspgen" ))
  377.                     fprintf( stderr, " -a" );
  378.                 
  379.                 if (r) {
  380.                     int n_frames,f,m;
  381.  
  382.                     n_frames = pof_read_short(model_buf);
  383.  
  384.                     Assert(n_frames == N_ANIM_STATES);
  385.  
  386.                     for (m=0;m<pm->n_models;m++)
  387.                         for (f=0;f<n_frames;f++)
  388.                             pof_cfread(&anim_angs[f][m],1,sizeof(vms_angvec),model_buf);
  389.  
  390.                     robot_set_angles(r,pm,anim_angs);
  391.                 
  392.                 }
  393.                 else
  394.                     pof_cfseek(model_buf,len,SEEK_CUR);
  395.  
  396.                 break;
  397.             #endif
  398.             
  399.             case ID_TXTR: {        //Texture filename list
  400.                 int n;
  401.                 char name_buf[128];
  402.  
  403.                 //mprintf(0,"Got chunk TXTR, len=%d\n",len);
  404.  
  405.                 n = pof_read_short(model_buf);
  406.                 //mprintf(0,"  num textures = %d\n",n);
  407.                 while (n--) {
  408.                     pof_read_string(name_buf,128,model_buf);
  409.                     //mprintf(0,"<%s>\n",name_buf);
  410.                 }
  411.  
  412.                 break;
  413.             }
  414.             
  415.             case ID_IDTA:        //Interpreter data
  416.                 //mprintf(0,"Got chunk IDTA, len=%d\n",len);
  417.  
  418.                 pm->model_data = malloc(len);
  419.                 pm->model_data_size = len;
  420.             
  421.                 pof_cfread(pm->model_data,1,len,model_buf);
  422.             
  423.                 break;
  424.  
  425.             default:
  426.                 //mprintf(0,"Unknown chunk <%c%c%c%c>, len = %d\n",id,id>>8,id>>16,id>>24,len);
  427.                 pof_cfseek(model_buf,len,SEEK_CUR);
  428.                 break;
  429.  
  430.         }
  431.         pof_cfseek(model_buf,next_chunk,SEEK_SET);
  432.     }
  433.  
  434. //    for (i=0;i<pm->n_models;i++)
  435. //        pm->submodel_ptrs[i] += (int) pm->model_data;
  436.  
  437.     if ( FindArg( "-bspgen" )) {
  438.         char *p = strchr( filename, '.' );
  439.         *p = 0;
  440.         fprintf( stderr, " %s.3ds\n", filename );
  441.         *p = '.';
  442.     }
  443.  
  444.     return pm;
  445. }
  446.  
  447. //reads the gun information for a model
  448. //fills in arrays gun_points & gun_dirs, returns the number of guns read
  449. int read_model_guns(char *filename,vms_vector *gun_points, vms_vector *gun_dirs, int *gun_submodels)
  450. {
  451.     CFILE *ifile;
  452.     short version;
  453.     int id,len;
  454.     int n_guns=0;
  455.     ubyte    model_buf[MODEL_BUF_SIZE];
  456.  
  457.     if ((ifile=cfopen(filename,"rb"))==NULL) 
  458.         Error("Can't open file <%s>",filename);
  459.  
  460.     Assert(ifile->size <= MODEL_BUF_SIZE);
  461.  
  462.     Pof_addr = 0;
  463.     Pof_file_end = cfread(model_buf, 1, ifile->size, ifile);
  464.     cfclose(ifile);
  465.  
  466.     id = pof_read_int(model_buf);
  467.  
  468.     if (id!='OPSP')
  469.         Error("Bad ID in model file <%s>",filename);
  470.  
  471.     version = pof_read_short(model_buf);
  472.     
  473.     Assert(version >= 7);        //must be 7 or higher for this data
  474.  
  475.     if (version < PM_COMPATIBLE_VERSION || version > PM_OBJFILE_VERSION)
  476.         Error("Bad version (%d) in model file <%s>",version,filename);
  477.  
  478.     while (new_pof_read_int(id,model_buf) == 1) {
  479.  
  480.         //id  = pof_read_int(model_buf);
  481.         len = pof_read_int(model_buf);
  482.  
  483.         if (id == ID_GUNS) {        //List of guns on this object
  484.  
  485.             //mprintf(0,"Got chunk GUNS, len=%d\n",len);
  486.  
  487.             int i;
  488.  
  489.             n_guns = pof_read_int(model_buf);
  490.  
  491.             for (i=0;i<n_guns;i++) {
  492.                 int id,sm;
  493.  
  494.                 id = pof_read_short(model_buf);
  495.                 sm = pof_read_short(model_buf);
  496.                 if (gun_submodels)
  497.                     gun_submodels[id] = sm;
  498.                 else if (sm!=0)
  499.                     Error("Invalid gun submodel in file <%s>",filename);
  500.                 pof_read_vecs(&gun_points[id],1,model_buf);
  501.  
  502.                 pof_read_vecs(&gun_dirs[id],1,model_buf);
  503.             }
  504.  
  505.         }
  506.         else
  507.             pof_cfseek(model_buf,len,SEEK_CUR);
  508.  
  509.     }
  510.  
  511.     return n_guns;
  512. }
  513.  
  514. //free up a model, getting rid of all its memory
  515. free_model(polymodel *po)
  516. {
  517.     free(po->model_data);
  518. }
  519.  
  520. grs_bitmap *texture_list[MAX_POLYOBJ_TEXTURES];
  521. bitmap_index texture_list_index[MAX_POLYOBJ_TEXTURES];
  522.  
  523. int Simple_model_threshhold_scale=5;        //switch when this times radius far away
  524.  
  525.  
  526. //draw a polygon model
  527.  
  528. 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[])
  529. {
  530.     polymodel *po;
  531.     int i;
  532.  
  533.     Assert(model_num < N_polygon_models);
  534.  
  535.     po=&Polygon_models[model_num];
  536.  
  537.     //check if should use simple model
  538.     if (po->simpler_model )                    //must have a simpler model
  539.         if (flags==0)                            //can't switch if this is debris
  540.             //!!if (!alt_textures) {                //alternate textures might not match
  541.             //alt textures might not match, but in the one case we're using this
  542.             //for on 11/14/94, they do match.  So we leave it in.
  543.             {
  544.                 int cnt=1;
  545.                 fix depth;
  546.     
  547.                 depth = g3_calc_point_depth(pos);        //gets 3d depth
  548.  
  549.                 while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad)
  550.                     po = &Polygon_models[po->simpler_model-1];
  551.             }
  552.  
  553.     if (alt_textures)
  554.         for (i=0;i<po->n_textures;i++)    {
  555.             texture_list_index[i] = alt_textures[i];
  556.             texture_list[i] = &GameBitmaps[alt_textures[i].index];
  557.         }
  558.     else
  559.         for (i=0;i<po->n_textures;i++)    {
  560.             texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
  561.             texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index];
  562.         }
  563.  
  564. #ifdef PIGGY_USE_PAGING
  565.     // Make sure the textures for this object are paged in...
  566.     piggy_page_flushed = 0;
  567.     for (i=0;i<po->n_textures;i++)    
  568.         PIGGY_PAGE_IN( texture_list_index[i] );
  569.     // Hmmm... cache got flushed in the middle of paging all these in,
  570.     // so we need to reread them all in.
  571.     if (piggy_page_flushed)    {
  572.         piggy_page_flushed = 0;
  573.         for (i=0;i<po->n_textures;i++)    
  574.             PIGGY_PAGE_IN( texture_list_index[i] );
  575.     }
  576.     // Make sure that they can all fit in memory.
  577.     Assert( piggy_page_flushed == 0 );
  578. #endif
  579.  
  580.     g3_start_instance_matrix(pos,orient);
  581.  
  582.     g3_set_interp_points(robot_points);
  583.  
  584.     if (flags == 0)        //draw entire object
  585.  
  586.         g3_draw_polygon_model(po->model_data,texture_list,anim_angles,light,glow_values);
  587.  
  588.     else {
  589.         int i;
  590.     
  591.         for (i=0;flags;flags>>=1,i++)
  592.             if (flags & 1) {
  593.                 vms_vector ofs;
  594.  
  595.                 Assert(i < po->n_models);
  596.  
  597.                 //if submodel, rotate around its center point, not pivot point
  598.     
  599.                 vm_vec_avg(&ofs,&po->submodel_mins[i],&po->submodel_maxs[i]);
  600.                 vm_vec_negate(&ofs);
  601.                 g3_start_instance_matrix(&ofs,NULL);
  602.     
  603.                 g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]],texture_list,anim_angles,light,glow_values);
  604.     
  605.                 g3_done_instance();
  606.             }    
  607.     }
  608.  
  609.     g3_done_instance();
  610.  
  611. }
  612.  
  613. free_polygon_models()
  614. {
  615.     int i;
  616.  
  617.     for (i=0;i<N_polygon_models;i++) {
  618.         free_model(&Polygon_models[i]);
  619.     }
  620.  
  621. }
  622.  
  623. polyobj_find_min_max(polymodel *pm)
  624. {
  625.     ushort nverts;
  626.     vms_vector *vp;
  627.     ushort *data,type;
  628.     int m;
  629.     vms_vector *big_mn,*big_mx;
  630.     
  631.     big_mn = &pm->mins;
  632.     big_mx = &pm->maxs;
  633.  
  634.     for (m=0;m<pm->n_models;m++) {
  635.         vms_vector *mn,*mx,*ofs;
  636.  
  637.         mn = &pm->submodel_mins[m];
  638.         mx = &pm->submodel_maxs[m];
  639.         ofs= &pm->submodel_offsets[m];
  640.  
  641.         data = (ushort *)&pm->model_data[pm->submodel_ptrs[m]];
  642.     
  643.         type = *data++;
  644.     
  645.         Assert(type == 7 || type == 1);
  646.     
  647.         nverts = *data++;
  648.     
  649.         if (type==7)
  650.             data+=2;        //skip start & pad
  651.     
  652.         vp = (vms_vector *) data;
  653.     
  654.         *mn = *mx = *vp++; nverts--;
  655.  
  656.         if (m==0)
  657.             *big_mn = *big_mx = *mn;
  658.     
  659.         while (nverts--) {
  660.             if (vp->x > mx->x) mx->x = vp->x;
  661.             if (vp->y > mx->y) mx->y = vp->y;
  662.             if (vp->z > mx->z) mx->z = vp->z;
  663.     
  664.             if (vp->x < mn->x) mn->x = vp->x;
  665.             if (vp->y < mn->y) mn->y = vp->y;
  666.             if (vp->z < mn->z) mn->z = vp->z;
  667.     
  668.             if (vp->x+ofs->x > big_mx->x) big_mx->x = vp->x+ofs->x;
  669.             if (vp->y+ofs->y > big_mx->y) big_mx->y = vp->y+ofs->y;
  670.             if (vp->z+ofs->z > big_mx->z) big_mx->z = vp->z+ofs->z;
  671.     
  672.             if (vp->x+ofs->x < big_mn->x) big_mn->x = vp->x+ofs->x;
  673.             if (vp->y+ofs->y < big_mn->y) big_mn->y = vp->y+ofs->y;
  674.             if (vp->z+ofs->z < big_mn->z) big_mn->z = vp->z+ofs->z;
  675.     
  676.             vp++;
  677.         }
  678.  
  679. //        printf("Submodel %d:  (%8x,%8x) (%8x,%8x) (%8x,%8x)\n",m,mn->x,mx->x,mn->y,mx->y,mn->z,mx->z);
  680.     }
  681.  
  682. //    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);
  683.  
  684. }
  685.  
  686. extern short highest_texture_num;    //from the 3d
  687.  
  688. char Pof_names[MAX_POLYGON_MODELS][13];
  689.  
  690. //returns the number of this model
  691. #ifndef DRIVE
  692. int load_polygon_model(char *filename,int n_textures,int first_texture,robot_info *r)
  693. #else
  694. int load_polygon_model(char *filename,int n_textures,grs_bitmap ***textures)
  695. #endif
  696. {
  697.     #ifdef DRIVE
  698.     #define r NULL
  699.     #endif
  700.  
  701.     Assert(N_polygon_models < MAX_POLYGON_MODELS);
  702.     Assert(n_textures < MAX_POLYOBJ_TEXTURES);
  703.  
  704.     mprintf(( 0, "Used %d/%d polygon model slots\n", N_polygon_models+1, MAX_POLYGON_MODELS ));
  705.  
  706.     Assert(strlen(filename) <= 12);
  707.     strcpy(Pof_names[N_polygon_models],filename);
  708.  
  709.     read_model_file(&Polygon_models[N_polygon_models],filename,r);
  710.  
  711.     polyobj_find_min_max(&Polygon_models[N_polygon_models]);
  712.  
  713.     g3_init_polygon_model(Polygon_models[N_polygon_models].model_data);
  714.  
  715.     if (highest_texture_num+1 != n_textures)
  716.         Error("Model <%s> references %d textures but specifies %d.",filename,highest_texture_num+1,n_textures);
  717.  
  718.     Polygon_models[N_polygon_models].n_textures = n_textures;
  719.     Polygon_models[N_polygon_models].first_texture = first_texture;
  720.     Polygon_models[N_polygon_models].simpler_model = 0;
  721.  
  722. //    Assert(polygon_models[N_polygon_models]!=NULL);
  723.  
  724.     N_polygon_models++;
  725.  
  726.     return N_polygon_models-1;
  727.  
  728. }
  729.  
  730.  
  731. init_polygon_models()
  732. {
  733.     N_polygon_models = 0;
  734.  
  735.     atexit(free_polygon_models);
  736.  
  737. }
  738.  
  739. //compare against this size when figuring how far to place eye for picture
  740. #define BASE_MODEL_SIZE 0x28000
  741.  
  742. #define DEFAULT_VIEW_DIST 0x60000
  743.  
  744. //draws the given model in the current canvas.  The distance is set to
  745. //more-or-less fill the canvas.  Note that this routine actually renders
  746. //into an off-screen canvas that it creates, then copies to the current
  747. //canvas.
  748. draw_model_picture(int mn,vms_angvec *orient_angles)
  749. {
  750.     vms_vector    temp_pos=ZERO_VECTOR;
  751.     vms_matrix    temp_orient = IDENTITY_MATRIX;
  752.     grs_canvas    *save_canv = grd_curcanv,*temp_canv;
  753.     //int            save_light;
  754.  
  755.     Assert(mn>=0 && mn<N_polygon_models);
  756.  
  757.     temp_canv = gr_create_canvas(save_canv->cv_bitmap.bm_w,save_canv->cv_bitmap.bm_h);
  758.     gr_set_current_canvas(temp_canv);
  759.     gr_clear_canvas( BM_XRGB(0,0,0) );
  760.  
  761.     g3_start_frame();
  762.     g3_set_view_matrix(&temp_pos,&temp_orient,0x9000);
  763.  
  764.     if (Polygon_models[mn].rad != 0)
  765.         temp_pos.z = fixmuldiv(DEFAULT_VIEW_DIST,Polygon_models[mn].rad,BASE_MODEL_SIZE);
  766.     else
  767.         temp_pos.z = DEFAULT_VIEW_DIST;
  768.  
  769.     vm_angles_2_matrix(&temp_orient, orient_angles);
  770.  
  771.     //save_light = Lighting_on;
  772.     //Lighting_on = 0;
  773.     draw_polygon_model(&temp_pos,&temp_orient,NULL,mn,0,f1_0,NULL,NULL);
  774.     //Lighting_on = save_light;
  775.  
  776.     gr_set_current_canvas(save_canv);
  777.  
  778.     gr_bitmap(0,0,&temp_canv->cv_bitmap);
  779.  
  780.     gr_free_canvas(temp_canv);
  781. }
  782.  
  783. 
  784.