home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 543a.lha / Nebula / source.LZH / source / 3drout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-10  |  14.9 KB  |  768 lines

  1. /*
  2. ------------------------------------------------------------------
  3.  
  4. Black Nebula
  5.  
  6. File :                3drout.c
  7. Programmer:        Colin Adams
  8. Date:                4/3/91
  9. Last Modified :    10/6/91
  10.  
  11. ------------------------------------------------------------------
  12.  
  13. */
  14.  
  15. #define D3ROUT
  16. #define AMIGA_INCLUDES
  17.  
  18. #include "3d.h"
  19.  
  20. extern object myship;
  21. extern short swapflag, U_rot;
  22. extern short num_active[];
  23.  
  24. extern struct BitMap my_bit_map;
  25. extern struct BitMap back_bit_map;
  26.  
  27. short store1 = 0, store2 = 0;
  28.  
  29. /*    ------------------------------------------------------------------
  30.         Fast Sin/Cos Routines
  31.         ------------------------------------------------------------------
  32. */
  33.  
  34. double deg(int degrees)
  35. /* converts degrees to radians */
  36. {
  37.     double test = degrees;
  38.     double one8 = 180;
  39.     
  40.     return 3.141592654/(one8/test);
  41. }
  42.  
  43. void TrigSetUp(void)
  44. {
  45.     register int i;
  46.     FILE *fp;
  47.     
  48.     if(!(fp=fopen("trig.pre","r")))
  49.     {
  50.         printf("Creating trig tables...\n");
  51.     
  52.         for(i=0; i<=90; i++)
  53.         {
  54.             sintable[i] = ((double) sin(deg(i)) * 65536);
  55.             costable[i] = ((double) cos(deg(i)) * 65536);
  56.         }
  57.     
  58.         /* precalculate sin/cos for all quadrants */
  59.         
  60.         for(i=91; i<=360; i++)
  61.         {
  62.             short six = 0, cix = 0, rot = i;
  63.         
  64.             if(rot>=271)
  65.             {
  66.                 rot = 360 - rot;
  67.                 six = 1;
  68.             }
  69.             else if(rot>=181)
  70.             {
  71.                 rot -= 180;
  72.                 six = cix = 1;
  73.             }
  74.             else if(rot>=91)
  75.             {
  76.                 rot = 180 - rot;
  77.                 cix = 1;
  78.             }
  79.         
  80.             cix = cix ? -1 : 1;
  81.             six = six ? -1 : 1;
  82.         
  83.             sintable[i] = ((double) sin(deg(rot)) * 65536)*six;
  84.             costable[i] = ((double) cos(deg(rot)) * 65536)*cix;
  85.         }
  86.     
  87.         printf("Saving...\n");
  88.     
  89.         if(!(fp = fopen("trig.pre","w")))
  90.         {
  91.             printf("Failed to save trig data!!!\n");
  92.             return;
  93.         }
  94.     
  95.         fwrite((void *) &sintable[0], sizeof(int), 361, fp);
  96.         fwrite((void *) &costable[0], sizeof(int), 361, fp);
  97.         fclose(fp);
  98.     }
  99.     else
  100.     {
  101.         fread((void *) &sintable[0], sizeof(int), 361, fp);
  102.         fread((void *) &costable[0], sizeof(int), 361, fp);
  103.         fclose(fp);
  104.     }
  105. }
  106.  
  107. /*    ------------------------------------------------------------------
  108.         Random Number Functions
  109.         ------------------------------------------------------------------
  110. */
  111.  
  112. void SetRandom(void)
  113. {
  114.     long t;
  115.     time(&t);
  116.     srand((int) t);
  117. }
  118.  
  119. int getrandom(int a, int b)
  120. {
  121.     return (rand() % (1+b-a)) + a;
  122. }
  123.     
  124. /*    ------------------------------------------------------------------
  125.         Routines for Object Manipulation
  126.         ------------------------------------------------------------------
  127. */
  128.  
  129.  
  130. void Rotate_Obj_Abs(object *obj, short x, short y, short z)
  131. {
  132.     obj->rot_x = x;
  133.     obj->rot_y = y;
  134.     obj->rot_z = z;
  135. }
  136.  
  137. void Rotate_Obj_Rel(object *obj, short x, short y, short z)
  138. {
  139.     if((obj->rot_x += x)>=360)
  140.         obj->rot_x -= 360;
  141.     else if(obj->rot_x<0)
  142.         obj->rot_x += 360;
  143.         
  144.     if((obj->rot_y += y)>=360)
  145.         obj->rot_y -= 360;
  146.     else if(obj->rot_y<0)
  147.         obj->rot_y += 360;
  148.     
  149.     if((obj->rot_z += z)>=360)
  150.         obj->rot_z -= 360;
  151.     else if(obj->rot_z<0)
  152.         obj->rot_z += 360;
  153. }
  154.  
  155. void Translate_Obj_Abs(object *obj, short x, short y, short z)
  156. {
  157.     obj->trans_x = x;
  158.     obj->trans_y = y;
  159.     obj->trans_z = z;
  160. }    
  161.  
  162. void Translate_Obj_Rel(object *obj, short x, short y, short z)
  163. {
  164.     obj->trans_x += x;
  165.     obj->trans_y += y;
  166.     obj->trans_z += z;
  167. }
  168.  
  169. void Destroy_Object(object *obj)
  170. /* pretty obvious what this does */
  171. {
  172.     polygon *p, *nextp;
  173.     
  174.     p = obj->poly;
  175.     while(p)
  176.     {
  177.         nextp = (polygon *) p->next;
  178.         free(p);
  179.         p = nextp;
  180.     }
  181.     
  182.     free(obj);
  183. }
  184.  
  185. void Save_Object(object *obj, char *filename)
  186. {
  187.     FILE *fp;
  188.     polygon *p;
  189.     int zero = 0, one = 1;
  190.     
  191.     if(!(fp=fopen(filename,"w")))
  192.     {
  193.             printf("Disk Error : Couldn't open the file for output!\n");
  194.             return;
  195.     }
  196.  
  197.     fwrite((void *) &(obj->type), sizeof(char), 1, fp);
  198.     fwrite((void *) &(obj->start_x), sizeof(short), 1, fp);
  199.     fwrite((void *) &(obj->start_y), sizeof(short), 1, fp);
  200.     fwrite((void *) &(obj->start_z), sizeof(short), 1, fp);
  201.     fwrite((void *) &(obj->numpoints), sizeof(short), 1, fp);
  202.     fwrite((void *) &(obj->radius), sizeof(short), 1, fp);
  203.     fwrite((void *) &(obj->objpoints[0]), sizeof(point), MAX_OBJ_POINTS, fp);
  204.  
  205.     p = obj->poly;
  206.     
  207.     while(p)
  208.     {
  209.         fwrite((void *) &one, sizeof(int), 1, fp);
  210.         
  211.         fwrite((void *) &(p->numpoints), sizeof(char), 1, fp);
  212.         fwrite((void *) &(p->colour), sizeof(short), 1, fp);
  213.         fwrite((void *) &(p->centre), sizeof(point), 1, fp);        
  214.         fwrite((void *) &(p->p[0]), sizeof(short), MAX_POINTS, fp);
  215.  
  216.         p = (polygon *) p->next;
  217.     }
  218.     
  219.     fwrite((void *) &zero, sizeof(int), 1, fp);
  220.     fclose(fp);
  221.     printf("Object saved to file.\n");
  222. }
  223.  
  224. int Load_Object(object *obj, char *filename)
  225. {
  226.     FILE *fp;
  227.     polygon *p;
  228.     int i;
  229.     
  230.     if(!(fp=fopen(filename,"r")))
  231.     {
  232.         printf("Disk Error : Couldn't open the file for input!\n");
  233.         return 0;
  234.     }
  235.  
  236.     fread((void *) &(obj->type), sizeof(char), 1, fp);
  237.     fread((void *) &(obj->start_x), sizeof(short), 1, fp);
  238.     fread((void *) &(obj->start_y), sizeof(short), 1, fp);
  239.     fread((void *) &(obj->start_z), sizeof(short), 1, fp);
  240.     fread((void *) &(obj->numpoints), sizeof(short), 1, fp);
  241.     fread((void *) &(obj->radius), sizeof(short), 1, fp);
  242.     
  243.     fread((void *) &(obj->objpoints[0]), sizeof(point), MAX_OBJ_POINTS, fp);
  244.     
  245.     fread((void *) &i, sizeof(int), 1, fp);
  246.     
  247.     if(i)
  248.     {
  249.         obj->poly = (polygon *) malloc(sizeof(polygon));
  250.         p = obj->poly;
  251.         
  252.         fread((void *) &(p->numpoints), sizeof(char), 1, fp);
  253.         fread((void *) &(p->colour), sizeof(short), 1, fp);
  254.         fread((void *) &(p->centre), sizeof(point), 1, fp);        
  255.         fread((void *) &(p->p[0]), sizeof(short), MAX_POINTS, fp);
  256.  
  257.         fread((void *) &i, sizeof(int), 1, fp);
  258.         while(i)
  259.         {
  260.             p->last_num = p->clip_num = p->last_num2 = 0;
  261.             p->next = (polygon *) malloc(sizeof(polygon));
  262.             p = (polygon *) p->next;
  263.             
  264.             fread((void *) &(p->numpoints), sizeof(char), 1, fp);
  265.             fread((void *) &(p->colour), sizeof(short), 1, fp);
  266.             fread((void *) &(p->centre), sizeof(point), 1, fp);        
  267.             fread((void *) &(p->p[0]), sizeof(short), MAX_POINTS, fp);
  268.  
  269.             fread((void *) &i, sizeof(int), 1, fp);
  270.         }
  271.         p->next = NULL;
  272.     }
  273.         
  274.     fclose(fp);
  275.     return 1;
  276. }
  277.  
  278. object *CreateObject(void)
  279. {
  280.     object *obj;
  281.     
  282.     if(!(obj = (object *) malloc(sizeof(object))))
  283.     {
  284.         printf("Fatal Error : Not enough memory!\n");
  285.         CleanUpandExit();
  286.     }
  287.     
  288.     obj->poly = NULL;
  289.     obj->start_x = obj->start_y = obj->start_z = 0;
  290.     obj->type = obj->centre_x = obj->centre_y = obj->centre_z = 0;
  291.     obj->trans_x = obj->trans_y = obj->trans_z = 500;
  292.     obj->rot_x = obj->rot_y = obj->rot_z = 0;
  293.     obj->velocity = 5;
  294.     obj->heading = 0;
  295.     return obj;
  296. }    
  297.  
  298. void AddPoly(object *obj, polygon *p)
  299. {
  300.     polygon *point = obj->poly;
  301.     if(point)
  302.     {
  303.         while(point->next)
  304.             point = (polygon *) point->next;
  305.         
  306.         point->next = p;
  307.         p->next = NULL;
  308.     }
  309.     else
  310.     {
  311.         obj->poly = p;
  312.         p->next = NULL;
  313.     }
  314. }
  315.  
  316. void SpinThatObject(object *obj)
  317. /*
  318. Spins an object around the axies.  Seems to be a bottleneck, so will
  319. have to be converted to 68k.  Anyone with a faster algorithm please tell
  320. me, as this is the fastest one I know.
  321. */
  322. {
  323.     register short i;
  324.     register short xrot = obj->rot_x;
  325.     register short yrot = obj->rot_y;
  326.     register short zrot = obj->rot_z;
  327.     
  328.     for(i=1; i<=obj->numpoints; i++)
  329.     {
  330.         register int x,y,z;
  331.         
  332.         x = obj->objpoints[i].x;
  333.         y = obj->objpoints[i].y;
  334.         z = obj->objpoints[i].z;
  335.  
  336.         /* rotate a point around the z axis */
  337.         
  338.         if(zrot)
  339.         {
  340.             register int temp, temp2, temp3;
  341.             temp = x;
  342.             temp2 = costable[zrot];
  343.             temp3 = sintable[zrot];
  344.             
  345.             x = ((temp2*temp)>>16) - ((temp3*y)>>16);
  346.             y = ((temp3*temp)>>16) + ((temp2*y)>>16);
  347.         }
  348.             
  349.         /* rotate a point around the x axis */
  350.             
  351.         if(xrot)
  352.         {
  353.             register int temp, temp2, temp3;
  354.             temp = y;
  355.             temp2 = costable[xrot];
  356.             temp3 = sintable[xrot];
  357.             
  358.             y = ((temp2*temp)>>16) - ((temp3*z)>>16);
  359.             z = ((temp3*temp)>>16) + ((temp2*z)>>16);
  360.         }
  361.             
  362.         /* rotate a point around the y axis */
  363.             
  364.         if(yrot)
  365.         {
  366.             register int temp, temp2, temp3;
  367.             temp = z;
  368.             temp2 = costable[yrot];
  369.             temp3 = sintable[yrot];
  370.             
  371.             z = ((temp2*temp)>>16) - ((temp3*x)>>16);
  372.             x = ((temp3*temp)>>16) + ((temp2*x)>>16);
  373.         }
  374.             
  375.         /* move back to points */
  376.         
  377.         manipulate_x[i] = x;
  378.         manipulate_y[i] = y;
  379.         manipulate_z[i] = z;
  380.     }    
  381. }
  382.  
  383. void SpinObjCentres(void)
  384. /* another use of my rotate code */
  385. {
  386.     register short i;
  387.     
  388.     for(i=0; i<no_objects; i++)
  389.     {
  390.         register object *obj = active_list[i];
  391.         register int x,y,z;
  392.     
  393.         register short xrot = obj->rot_x;
  394.         register short yrot = obj->rot_y;
  395.         register short zrot = obj->rot_z;
  396.  
  397.         x = obj->start_x;
  398.         y = obj->start_y;
  399.         z = obj->start_z;
  400.  
  401.         /* rotate a point around the z axis */
  402.         
  403.         if(zrot)
  404.         {
  405.             register int temp, temp2, temp3;
  406.             temp = x;
  407.             temp2 = costable[zrot];
  408.             temp3 = sintable[zrot];
  409.             
  410.             x = ((temp2*temp)>>16) - ((temp3*y)>>16);
  411.             y = ((temp3*temp)>>16) + ((temp2*y)>>16);
  412.         }
  413.             
  414.         /* rotate a point around the x axis */
  415.             
  416.         if(xrot)
  417.         {
  418.             register int temp, temp2, temp3;
  419.             temp = y;
  420.             temp2 = costable[xrot];
  421.             temp3 = sintable[xrot];
  422.             
  423.             y = ((temp2*temp)>>16) - ((temp3*z)>>16);
  424.             z = ((temp3*temp)>>16) + ((temp2*z)>>16);
  425.         }
  426.             
  427.         /* rotate a point around the y axis */
  428.             
  429.         if(yrot)
  430.         {
  431.             register int temp, temp2, temp3;
  432.             temp = z;
  433.             temp2 = costable[yrot];
  434.             temp3 = sintable[yrot];
  435.             
  436.             z = ((temp2*temp)>>16) - ((temp3*x)>>16);
  437.             x = ((temp3*temp)>>16) + ((temp2*x)>>16);
  438.         }
  439.             
  440.         /* move back to points */
  441.         
  442.         obj->centre_x = x;
  443.         obj->centre_y = y;
  444.         obj->centre_z = z;
  445.     }    
  446. }
  447.  
  448. void PrepareObject(object *obj)
  449. {
  450.     polygon *pg = obj->poly;
  451.     register short i;
  452.  
  453.     if(!(obj->drawme))
  454.         return;
  455.  
  456.     SpinThatObject(obj);
  457.  
  458.     for(i=1; i<=obj->numpoints; i++) /* do translation */
  459.     {
  460.         manipulate_x[i] += obj->trans_x;
  461.         manipulate_y[i] += obj->trans_y;
  462.         manipulate_z[i] += obj->trans_z;
  463.     }
  464.     
  465.     DepthSort(obj); /* sort polygons by depth from eye */
  466.     
  467.     /* convert all points in object to 2d */
  468.     
  469.     for(i=1; i<=obj->numpoints; i++)
  470.     {
  471.         get2d(manipulate_x[i], manipulate_y[i], manipulate_z[i]);
  472.         obj->pointx[i] = x;
  473.         obj->pointy[i] = y;
  474.     }
  475.  
  476.     /* work out what points are in each polygon, then clip them */
  477.     
  478.     while(pg)
  479.     {
  480.         for(i=0; i<pg->numpoints; i++)
  481.         {
  482.             pg->x[i] = obj->pointx[pg->p[i]];
  483.             pg->y[i] = obj->pointy[pg->p[i]];
  484.         }
  485.         if(!pg->back_face)
  486.              polygon_clip(pg); /* creates a new polygon clipped */
  487.         pg = (polygon *) pg->next;
  488.     }
  489. }
  490.  
  491. void DrawObject(object *obj)
  492. /* can only be used on an object that has already been clipped and
  493. arranged in drawing order */
  494. {
  495.     register int j = 0;
  496.     register polygon *pg;
  497.  
  498.     pg = obj->draworder[j];
  499.  
  500.     obj->lastdraw2 = obj->lastdrawme;
  501.     obj->lastdrawme = obj->drawme;
  502.  
  503.     if(!(obj->drawme))
  504.         return;
  505.         
  506.     while(pg) /* list is only terminated with a NULL */
  507.     {
  508.         register int i;
  509.         
  510.         if(!pg->back_face)
  511.         {
  512.             SetAPen(rastport, pg->colour);
  513.             
  514.             MoveTo(pg->clip_x[0], pg->clip_y[0]);
  515.     
  516.             for(i=1; i<pg->clip_num; i++)
  517.                 DrawTo(pg->clip_x[i], pg->clip_y[i]);
  518.                 
  519.             FillArea();
  520.         }
  521.  
  522.         if(swapflag)
  523.         {
  524.             store1 = 1;
  525.             
  526.             pg->last_num = pg->clip_num;
  527.         
  528.             for(i=0; i<pg->clip_num; i++)
  529.             {
  530.                 pg->last_x[i] = pg->clip_x[i];
  531.                 pg->last_y[i] = pg->clip_y[i];
  532.             }
  533.         }
  534.         else
  535.         {
  536.             store2 = 1;
  537.             
  538.             pg->last_num2 = pg->clip_num;
  539.         
  540.             for(i=0; i<pg->clip_num; i++)
  541.             {
  542.                 pg->last_x2[i] = pg->clip_x[i];
  543.                 pg->last_y2[i] = pg->clip_y[i];
  544.             }
  545.         }
  546.         
  547.         j++;
  548.         pg = obj->draworder[j];
  549.     }
  550. }
  551.  
  552. void EraseObject(object *obj)
  553. /* can only be used on an object that has already been drawn */
  554. {
  555.     polygon *pg;
  556.  
  557.     if(!(obj->lastdraw2))
  558.         return;
  559.  
  560.     pg = obj->poly;
  561.     SetAPen(rastport, 0);
  562.     
  563.     if(swapflag)
  564.     {
  565.         if(store1)
  566.         {
  567.             while(pg)
  568.             {
  569.                 register int i;
  570.  
  571.                 if(pg->last_num)
  572.                 {
  573.                     MoveTo(pg->last_x[0], pg->last_y[0]);
  574.                 
  575.                     for(i=1; i<pg->last_num; i++)
  576.                         DrawTo(pg->last_x[i], pg->last_y[i]);
  577.                     
  578.                     FillArea();
  579.                 }
  580.                 pg = (polygon *) pg->next;
  581.             }
  582.         }
  583.     }
  584.     else
  585.     {
  586.         if(store2)
  587.         {
  588.             while(pg)
  589.             {
  590.                 register int i;
  591.                 
  592.                 if(pg->last_num2)
  593.                 {
  594.                     MoveTo(pg->last_x2[0], pg->last_y2[0]);
  595.  
  596.                     for(i=1; i<pg->last_num2; i++)
  597.                         DrawTo(pg->last_x2[i], pg->last_y2[i]);
  598.                 
  599.                     FillArea();
  600.  
  601.                 }
  602.                 pg = (polygon *) pg->next;
  603.             }
  604.         }
  605.     }
  606. }
  607.  
  608. void AddObject(char *filename, short type)
  609. {
  610.     object *obj;
  611.     int i;
  612.     
  613.     for(i=0; i<MAX_OBJECTS; i++)
  614.     {    
  615.         obj = CreateObject();
  616.         if(!(Load_Object(obj, filename)))
  617.         {
  618.             printf("Failed to load %s\n",filename);
  619.             free(obj);
  620.             return;
  621.         }
  622.         memcpy(&obj_types[type][i], obj, sizeof(object));    
  623.         free(obj);
  624.     }
  625. }
  626.  
  627. void SetUpExplosions(void)
  628. {
  629.     int i;
  630.     
  631.     for(i=0; i<MAX_EXPLOSIONS; i++)
  632.     {
  633.         explosions[i].type = EXPLOSION;
  634.         explosions[i].radius = 2500;
  635.  
  636.         if(!(explosions[i].poly = malloc(sizeof(polygon))))
  637.         {
  638.             printf("Error creating explosions!\n");
  639.             CleanUpandExit();
  640.         }
  641.         explosions[i].poly->next = NULL;
  642.         explosions[i].poly->last_num = explosions[i].poly->last_num2 = 0;
  643.     }
  644. }
  645.  
  646. void AddNewObject(short type, short x, short y, short z)
  647. {
  648.     register int i;
  649.     register object *obj;
  650.         
  651.     for(i=0; i<MAX_OBJECTS; i++)
  652.     {
  653.         if(!obj_free[type][i])
  654.         {
  655.             obj = &obj_types[type][i];
  656.             
  657.             Translate_Obj_Abs(obj, x, y, z);
  658.             
  659.             obj->i_am_dying = obj->lastdrawme = obj->lastdraw2 = 0;
  660.             obj->timeinflight = 0;
  661.             
  662.             if(type==MYMISSILE || type==GUIDEDMISSILE)
  663.             {
  664.                 
  665.                 obj->velocity = 30;
  666.                 obj->heading = View_Angle;
  667.                 obj->target = NULL;
  668.                 if(type==MYMISSILE)
  669.                     Rotate_Obj_Abs(obj, 0, View_Angle, 180);
  670.                 else
  671.                     Rotate_Obj_Abs(obj, 0, View_Angle, 0);
  672.             }
  673.             
  674.             if(type==PLAYER || type==MAMBA)
  675.                 Rotate_Obj_Abs(obj, 90, 0, 0);
  676.             
  677.             obj->explode = 0;
  678.             obj_free[type][i] = 1;
  679.             active_list[no_objects] = obj;
  680.             no_objects++;
  681.             num_active[type]++;
  682.             return;
  683.         }
  684.     }
  685. }
  686.  
  687. void KillAllObjects(void)
  688. {
  689.     unsigned char i, j;
  690.     
  691.     for(j=0; j<NO_OBJ_TYPES; j++)
  692.     {
  693.         for(i=0; i<MAX_OBJECTS; i++)
  694.             obj_free[j][i] = 0;
  695.         
  696.         num_active[j] = 0;
  697.     }
  698.     
  699.     for(i=0; i<MAX_EXPLOSIONS; i++)
  700.         exp_free[i] = 0;
  701.         
  702.     no_objects = 0;
  703.     am_i_dead = 0;
  704. }
  705.  
  706. void CreateExplosion(object *obj)
  707. /*
  708. Cool routine to blow an object into it's polygons.  Takes a while though,
  709. so I'll have to fix it up a bit.  Looks damn nice though...
  710. */
  711. {
  712.     register int i, j = 0;
  713.     register polygon *pg = obj->poly;
  714.     
  715.     while(pg)
  716.     {
  717.         for(i=j; i<MAX_EXPLOSIONS; i++)
  718.         {
  719.             if(!exp_free[i]) /* is free ! */
  720.             {
  721.                 register int n;
  722.                 
  723.                 explosions[i].lastdrawme = explosions[i].lastdraw2 = 0;
  724.                 explosions[i].drawme = 1;
  725.                 explosions[i].explode = 0;
  726.                 explosions[i].i_am_dying = 0;
  727.                 explosions[i].type = EXPLOSION;
  728.                 explosions[i].centre_x = pg->centre.x;
  729.                 explosions[i].centre_y = pg->centre.y;
  730.                 explosions[i].centre_z = pg->centre.z;
  731.                 explosions[i].timeinflight = getrandom(5,25); /* time will last */
  732.                 
  733.                 explosions[i].poly->numpoints = explosions[i].numpoints =
  734.                     pg->numpoints;
  735.                 
  736.                 explosions[i].poly->colour = pg->colour;
  737.                 explosions[i].poly->centre = pg->centre;
  738.                 
  739.                 for(n=0; n<pg->numpoints; n++)
  740.                     explosions[i].poly->p[n] = n + 1;
  741.                     
  742.                 for(n=1; n<=pg->numpoints; n++)
  743.                     explosions[i].objpoints[n] = obj->objpoints[pg->p[n-1]];
  744.                 
  745.                 Translate_Obj_Abs(&explosions[i], obj->trans_x,
  746.                     obj->trans_y, obj->trans_z);
  747.                     
  748.                 Rotate_Obj_Abs(&explosions[i], obj->rot_x,
  749.                     obj->rot_y, obj->rot_z);
  750.                 
  751.                 explosions[i].velocity = getrandom(0,10);
  752.                 explosions[i].heading = getrandom(0,360);
  753.                 explosions[i].up_or_down = getrandom(0,2);
  754.                 
  755.                 exp_free[i] = 1; /* not free */
  756.                 active_list[no_objects] = &explosions[i];
  757.                 no_objects++;
  758.                 break;    
  759.             }
  760.         }
  761.         j = i;    /* by doing this, I can search in order n instead of n^2 */
  762.         pg = (polygon *) pg->next;
  763.     }
  764.     StartSound(1);
  765. }
  766.                     
  767. /* end of module */
  768.