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