home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwdos / object.c < prev    next >
C/C++ Source or Header  |  1995-02-15  |  29KB  |  952 lines

  1. /**********************************************************************
  2.  *
  3.  * File :     object.c
  4.  *
  5.  * Abstract : Generic object handler. This module handles the depth
  6.  *            sorting and general control flow for the objects in
  7.  *            the street.
  8.  *
  9.  **********************************************************************
  10.  *
  11.  * This file is a product of Criterion Software Ltd.
  12.  *
  13.  * This file is provided as is with no warranties of any kind and is
  14.  * provided without any obligation on Criterion Software Ltd. or
  15.  * Canon Inc. to assist in its use or modification.
  16.  *
  17.  * Criterion Software Ltd. will not, under any
  18.  * circumstances, be liable for any lost revenue or other damages arising
  19.  * from the use of this file.
  20.  *
  21.  * Copyright (c) 1995 Criterion Software Ltd.
  22.  * All Rights Reserved.
  23.  *
  24.  * RenderWare is a trademark of Canon Inc.
  25.  *
  26.  ************************************************************************/
  27.  
  28. /*--- Include files ---*/
  29.  
  30. #include "global.h"     /* Application general includes */
  31.  
  32. /*--- Structure Definitions ---*/
  33.  
  34. /* All Objects: A single global variable of this type is declared and used
  35.  *  to hold the data for all of the objects currently defined
  36.  */
  37.  
  38. typedef struct
  39. {
  40.     Object **oppObjects;
  41.     int nEndObject;
  42.     int nAmoObjects;
  43.     RwV3d vDeletePos;
  44.     int nFirst;             /* 0-2 : 0 x 1 y 2 z */
  45.     int nSecond;
  46.     int nThird;
  47.     int (*fpCompare)(const void *,const void *);
  48. } AllObjects;
  49.  
  50. AllObjects aoGAll;
  51.  
  52. /*--- Macor and Magic Number definitions */
  53.  
  54. #define MAX_NUM     20   /* The maximum depth for an object in cyberstreet
  55.                             any objects that are further away from the camera
  56.                             than this will automatically be deleted */
  57.  
  58.  
  59. /* Patch for floating point */
  60.  
  61. #ifdef RWFLOAT
  62. #define RETURNINT(A) ((int)((A)*65536.0))
  63. #else
  64. #define RETURNINT(A) (A)
  65. #endif
  66.  
  67. #define INITIAL_OBJECTS  20  /* Initial number of objects */
  68. #define OBJ_INCREASE 5       /* Allocate space for this many objects
  69.                                 at a time */
  70.  
  71. /************************************************************************
  72.  *
  73.  *      Function:       DefaultRender()
  74.  *
  75.  *      Description:    The default object render function. This function
  76.  *                      will be used to render all objects that don't
  77.  *                      explicitly define their own render function
  78.  *
  79.  *      Parameters:     opObj - the object to render
  80.  *
  81.  *      Return Value:   None
  82.  *
  83.  ************************************************************************/
  84. static void DefaultRender(Object *opObj)
  85. {
  86.     if (opObj->cpClump)
  87.     {
  88.         /* The default render action is just to translate the clump to
  89.            its final position and render it */
  90.  
  91.         RwTranslateMatrix(RwScratchMatrix(),
  92.                           opObj->vPos.x,
  93.                           opObj->vPos.y,
  94.                           opObj->vPos.z, rwREPLACE);
  95.  
  96.         RwTransformClump(opObj->cpClump, RwScratchMatrix(), rwREPLACE);
  97.         RwRenderClump(opObj->cpClump);
  98.     }
  99. }
  100.  
  101. /************************************************************************
  102.  *
  103.  *      Function:       DefaultUpdate()
  104.  *
  105.  *      Description:    The default object update function. This function
  106.  *                      will be used to update all objects that don't
  107.  *                      explicitly define their own update function
  108.  *
  109.  *      Parameters:     opObj - the object to update
  110.  *
  111.  *      Return Value:   None
  112.  *
  113.  ************************************************************************/
  114. static void
  115. DefaultUpdate(Object *opObj)
  116. {
  117.   /* Don't do anything for the default object */
  118.   opObj = opObj;
  119. }
  120.  
  121. /************************************************************************
  122.  *
  123.  *      Function:       DefaultDestroy()
  124.  *
  125.  *      Description:    The default object destroy function. This function
  126.  *                      will be used to destroy all objects that don't
  127.  *                      explicitly define their own destroy function
  128.  *
  129.  *      Parameters:     opObj - the object to destroy
  130.  *
  131.  *      Return Value:   None
  132.  *
  133.  ************************************************************************/
  134. static void
  135. DefaultDestroy(Object *opObj)
  136. {
  137.     /* Destroy the RenderWare clump */
  138.     RwDestroyClump(opObj->cpClump);
  139.  
  140.     /* free up the object data */
  141.     free(opObj);
  142. }
  143.  
  144. /************************************************************************
  145.  * Object Depth Sorting:
  146.  * We make the following assumptions about the objects in the cyberstreet scene.
  147.  * 1. If 2 objects occupy the same space then they will be drawn in an
  148.  *    arbitrary order. We don't want to Z buffer them.
  149.  * 2. The objects are small and self contained, therefore a simple depth sort
  150.  *    using the objects origins is sufficient.
  151.  * For these reasons we choose to implement our own scene sorting which because
  152.  * of its specific nature will be quicker than the more general RenderWare
  153.  * scene sorting which will always try to render an accurate result.
  154.  *
  155.  * The algorithm that is used is a simple depth sort, where objects are sorted
  156.  * such that those furthest from the camera are drawn first. We use the standard
  157.  * C library function 'qsort' to perform the sorting.
  158.  *
  159.  * There are 2 mechanisms that are used to determine how best to sort the scene.
  160.  * the implementation of these mechanism varies with camera position.
  161.  * 1. We sort the scene by the most significant axis first down to least
  162.  *    least significant. ie if the camera is looking along the X axis, then
  163.  *    the x component of an objects position is more important than the y
  164.  *    component in determining correct ordering. The order of sorting is
  165.  *    assigned as first, second, third
  166.  *
  167.  * 2. Depending on the direction of the camera's at vector, the comparison
  168.  *    mechanism varies. ie A camera looking along the positive X axis would
  169.  *    sort from maximum X (furthest) to minimum Z (nearest). If the camera
  170.  *    was looking along the negative X axis then the sort order would be from
  171.  *    minimum X (furthest) to maximum X (nearest). Given this, we need 8
  172.  *    comparison functions for qsort which implement all combinations of
  173.  *    camera orientation in the 3 axis X, Y, and Z
  174.  *
  175.  *************************************************************************/
  176.  
  177. /************************************************************************
  178.  *
  179.  *      Function:       FMaxSMaxTMax()
  180.  *
  181.  *      Description:    qsort comparison function.
  182.  *
  183.  *      Parameters:     oppF - first object
  184.  *                      oppS - second object
  185.  *
  186.  *      Return Value:   -ve if 2nd object is further away than the first
  187.  *                      0 if they occupy the same location
  188.  *                      +ve if the 2nd object is nearer that the first
  189.  *
  190.  ************************************************************************/
  191. static int
  192. FMaxSMaxTMax(const Object **oppF, const Object **oppS)
  193. {
  194.     RwReal nVal;
  195.  
  196.     /* Compare the position of the 2 objects in the Most Significant Axis */
  197.  
  198.     if (nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nFirst] +
  199.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nFirst] )
  200.     {
  201.         return RETURNINT(nVal);
  202.     }
  203.  
  204.     /* Most significant Axis comarison was zero so try the next one */
  205.     if (nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nSecond] +
  206.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nSecond] )
  207.     {
  208.         return RETURNINT(nVal);
  209.     }
  210.  
  211.     /* Try the least significant axis */
  212.  
  213.     nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nThird] +
  214.             ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nThird];
  215.  
  216.     return RETURNINT(nVal);
  217. }
  218.  
  219. /************************************************************************
  220.  *
  221.  *      Function:       FMinSMaxTMax()
  222.  *                      
  223.  *      Description:    qsort comparison function. 
  224.  *
  225.  *      Parameters:     oppF - first object
  226.  *                      oppS - second object
  227.  *
  228.  *      Return Value:   -ve if 2nd object is further away than the first
  229.  *                      0 if they occupy the same location
  230.  *                      +ve if the 2nd object is nearer that the first
  231.  *
  232.  ************************************************************************/
  233. static int 
  234. FMinSMaxTMax(const Object **oppF, const Object **oppS)
  235. {
  236.     RwReal nVal;
  237.  
  238.     /* Compare the position of the 2 objects in the Most Significant Axis */
  239.  
  240.     if (nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nFirst] -
  241.                ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nFirst] )
  242.     {
  243.         return RETURNINT(nVal);
  244.     }
  245.  
  246.     /* Most significant Axis comarison was zero so try the next one */
  247.  
  248.     if (nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nSecond] +
  249.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nSecond] )
  250.     {
  251.         return RETURNINT(nVal);
  252.     }
  253.  
  254.     /* Try the least significant axis */
  255.  
  256.     nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nThird] +
  257.             ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nThird];
  258.     
  259.     return RETURNINT(nVal);
  260. }
  261.  
  262. /************************************************************************
  263.  *
  264.  *      Function:       FMinSMinTMax()
  265.  *                      
  266.  *      Description:    qsort comparison function. 
  267.  *
  268.  *      Parameters:     oppF - first object
  269.  *                      oppS - second object
  270.  *
  271.  *      Return Value:   -ve if 2nd object is further away than the first
  272.  *                      0 if they occupy the same location
  273.  *                      +ve if the 2nd object is nearer that the first
  274.  *
  275.  ************************************************************************/
  276. static int FMinSMinTMax(const Object **oppF,const Object **oppS)
  277. {
  278.     RwReal nVal;
  279.  
  280.     /* Compare the position of the 2 objects in the Most Significant Axis */
  281.  
  282.     if (nVal =  ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nFirst] -
  283.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nFirst] )
  284.     {
  285.         return RETURNINT(nVal);
  286.     }
  287.  
  288.     /* Most significant Axis comarison was zero so try the next one */
  289.  
  290.     if (nVal =  ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nSecond] -
  291.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nSecond] ) 
  292.     {
  293.         return RETURNINT(nVal);
  294.     }
  295.  
  296.     /* Try the least significant axis */
  297.  
  298.      nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nThird] +
  299.              ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nThird];
  300.     
  301.     return RETURNINT(nVal);
  302. }
  303.  
  304. /************************************************************************
  305.  *
  306.  *      Function:       FMaxSMinTMax()
  307.  *                      
  308.  *      Description:    qsort comparison function. 
  309.  *
  310.  *      Parameters:     oppF - first object
  311.  *                      oppS - second object
  312.  *
  313.  *      Return Value:   -ve if 2nd object is further away than the first
  314.  *                      0 if they occupy the same location
  315.  *                      +ve if the 2nd object is nearer that the first
  316.  *
  317.  ************************************************************************/
  318. static int 
  319. FMaxSMinTMax(const Object **oppF, const Object **oppS)
  320. {
  321.     RwReal nVal;
  322.  
  323.     /* Compare the position of the 2 objects in the Most Significant Axis */
  324.  
  325.     if (nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nFirst] +
  326.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nFirst] )
  327.     {
  328.         return RETURNINT(nVal);
  329.     }
  330.  
  331.     /* Most significant Axis comarison was zero so try the next one */
  332.  
  333.     if (nVal =  ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nSecond] -
  334.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nSecond] )
  335.     {
  336.         return RETURNINT(nVal);
  337.     }
  338.  
  339.     /* Try the least significant axis */
  340.  
  341.     nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nThird] +
  342.             ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nThird];
  343.   
  344.     return RETURNINT(nVal);
  345. }
  346.  
  347. /************************************************************************
  348.  *
  349.  *      Function:       FMaxSMinTMin()
  350.  *                      
  351.  *      Description:    qsort comparison function. 
  352.  *
  353.  *      Parameters:     oppF - first object
  354.  *                      oppS - second object
  355.  *
  356.  *      Return Value:   -ve if 2nd object is further away than the first
  357.  *                      0 if they occupy the same location
  358.  *                      +ve if the 2nd object is nearer that the first
  359.  *
  360.  ************************************************************************/
  361. int FMaxSMinTMin(const Object **oppF,const Object **oppS)
  362. {
  363.     RwReal nVal;
  364.  
  365.     /* Compare the position of the 2 objects in the Most Significant Axis */
  366.  
  367.     if (nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nFirst] +
  368.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nFirst] )
  369.     {
  370.         return RETURNINT(nVal);
  371.     }
  372.  
  373.     /* Most significant Axis comarison was zero so try the next one */
  374.  
  375.     if (nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nSecond] -
  376.                ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nSecond] )
  377.     {
  378.         return RETURNINT(nVal);
  379.     }
  380.  
  381.     /* Try the least significant axis */
  382.  
  383.     nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nThird] -
  384.            ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nThird];
  385.     
  386.     return RETURNINT(nVal);
  387. }
  388.  
  389.  
  390. /************************************************************************
  391.  *
  392.  *      Function:       FMinSMinTMin()
  393.  *                      
  394.  *      Description:    qsort comparison function. 
  395.  *
  396.  *      Parameters:     oppF - first object
  397.  *                      oppS - second object
  398.  *
  399.  *      Return Value:   -ve if 2nd object is further away than the first
  400.  *                      0 if they occupy the same location
  401.  *                      +ve if the 2nd object is nearer that the first
  402.  *
  403.  ************************************************************************/
  404. static int 
  405. FMinSMinTMin(const Object **oppF, const Object **oppS)
  406. {
  407.     RwReal nVal;
  408.  
  409.     /* Compare the position of the 2 objects in the Most Significant Axis */
  410.  
  411.     if (nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nFirst] -
  412.                ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nFirst] )
  413.     {
  414.         return RETURNINT(nVal);
  415.     }
  416.  
  417.     /* Most significant Axis comarison was zero so try the next one */
  418.  
  419.     if (nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nSecond] -
  420.                ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nSecond] ) 
  421.     {
  422.         return RETURNINT(nVal);
  423.     }
  424.  
  425.     /* Try the least significant axis */
  426.  
  427.     nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nThird] -
  428.            ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nThird];
  429.   
  430.     return RETURNINT(nVal);
  431. }
  432.  
  433. /************************************************************************
  434.  *
  435.  *      Function:       FMinSMaxTMin()
  436.  *                      
  437.  *      Description:    qsort comparison function. 
  438.  *
  439.  *      Parameters:     oppF - first object
  440.  *                      oppS - second object
  441.  *
  442.  *      Return Value:   -ve if 2nd object is further away than the first
  443.  *                      0 if they occupy the same location
  444.  *                      +ve if the 2nd object is nearer that the first
  445.  *
  446.  ************************************************************************/
  447. static int 
  448. FMinSMaxTMin(const Object **oppF, const Object **oppS)
  449. {
  450.     RwReal nVal;
  451.  
  452.     /* Compare the position of the 2 objects in the Most Significant Axis */
  453.  
  454.     if (nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nFirst] -
  455.                ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nFirst] ) 
  456.     {
  457.         return RETURNINT(nVal);
  458.     }
  459.  
  460.     /* Most significant Axis comarison was zero so try the next one */
  461.  
  462.     if (nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nSecond] +
  463.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nSecond] )
  464.     {
  465.         return RETURNINT(nVal);
  466.     }
  467.  
  468.     /* Try the least significant axis */
  469.  
  470.     nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nThird] -
  471.            ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nThird];
  472.     
  473.     return RETURNINT(nVal);
  474. }
  475.  
  476. /************************************************************************
  477.  *
  478.  *      Function:       FMaxSMaxTMin()
  479.  *                      
  480.  *      Description:    qsort comparison function. 
  481.  *
  482.  *      Parameters:     oppF - first object
  483.  *                      oppS - second object
  484.  *
  485.  *      Return Value:   -ve if 2nd object is further away than the first
  486.  *                      0 if they occupy the same location
  487.  *                      +ve if the 2nd object is nearer that the first
  488.  *
  489.  ************************************************************************/
  490. static int 
  491. FMaxSMaxTMin(const Object **oppF, const Object **oppS)
  492. {
  493.     RwReal nVal;
  494.  
  495.     /* Compare the position of the 2 objects in the Most Significant Axis */
  496.  
  497.     if (nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nFirst] +
  498.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nFirst] )
  499.     {
  500.         return RETURNINT(nVal);
  501.     }
  502.  
  503.     /* Most significant Axis comarison was zero so try the next one */
  504.  
  505.     if (nVal = -((RwReal *)(&((*oppF)->vPos)))[aoGAll.nSecond] +
  506.                 ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nSecond] )
  507.     {
  508.         return RETURNINT(nVal);
  509.     }
  510.  
  511.     /* Try the least significant axis */
  512.  
  513.     nVal = ((RwReal *)(&((*oppF)->vPos)))[aoGAll.nThird] -
  514.            ((RwReal *)(&((*oppS)->vPos)))[aoGAll.nThird];
  515.   
  516.     return RETURNINT(nVal);
  517. }
  518.  
  519.  
  520. /************************************************************************
  521.  *
  522.  *      Function:       ObjectDelete()
  523.  *                      
  524.  *      Description:    Delete and object from the cyberstreet scene. Rather
  525.  *                      than remove it from it current place in the scene and 
  526.  *                      have to shuffle the list about, we just move it to a
  527.  *                      distant point and then delete all of the objects at 
  528.  *                      this point once the list has been reordered on the 
  529.  *                      next render. 
  530.  *
  531.  *      Parameters:     opObj - object to delete
  532.  *
  533.  *      Return Value:   None
  534.  *
  535.  ************************************************************************/
  536. void ObjectDelete(Object *opObj)
  537. {
  538.     opObj->vPos = aoGAll.vDeletePos;
  539. }
  540.  
  541. /************************************************************************
  542.  *
  543.  *      Function:       ObjectSetup()
  544.  *                      
  545.  *      Description:    Initialise an objects data structure. 
  546.  *
  547.  *      Parameters:     opObj - object to set up
  548.  *                      x, y, z - Initial position for the object
  549.  *                      cpClump - The RenderWare clump data for the object
  550.  *
  551.  *      Return Value:   None
  552.  *
  553.  ************************************************************************/
  554. void 
  555. ObjectSetup(Object *opObj, RwReal x, RwReal y, RwReal z, RwClump *cpClump)
  556. {
  557.     /* define the functions that will be used to render, update and
  558.      * destroy the object. Not these functions may be overloaded with
  559.      * an object specific routine
  560.      */
  561.     opObj->fpRender = DefaultRender;
  562.     opObj->fpUpdate = DefaultUpdate;
  563.     opObj->fpDestroy = DefaultDestroy;
  564.  
  565.     /* Initialise the objects position
  566.      */
  567.     opObj->vPos.x = x;
  568.     opObj->vPos.y = y;
  569.     opObj->vPos.z = z;
  570.  
  571.     /* The object has no extra information initially. This value may
  572.      * be overloaded later
  573.      */
  574.     opObj->pExtra = NULL;
  575.  
  576.     /* Define the objects clump
  577.      */
  578.     opObj->cpClump = cpClump;
  579. }
  580.  
  581. /************************************************************************
  582.  *
  583.  *      Function:       AllObjectsUpdate()
  584.  *                      
  585.  *      Description:    Update the position of all of the objects
  586.  *
  587.  *      Parameters:     None
  588.  *
  589.  *      Return Value:   None
  590.  *
  591.  ************************************************************************/
  592. void 
  593. AllObjectsUpdate(void)
  594. {
  595.     int nCount;         /* Temporary loop control variable */
  596.     Object **oppObj;    /* Object pointer used in loop iteration */
  597.     RwV3d vAt;          /* The camera look at vector */
  598.     RwV3d vSize;        /* The absolute x, y, and z for the camera look at 
  599.                            vector */
  600.  
  601.     /* Get the camera's look at vector */
  602.  
  603.     RwGetCameraLookAt(cpGCamera,&vAt);
  604.  
  605.     /* based on the camera's look at vector, determine the position that 
  606.      * will be used as the 'delete position' for this frame. Any objects
  607.      * that are moved to this position will be deleted after the scene
  608.      * has been sorted.
  609.      */
  610.  
  611.     if (vAt.x < CREAL(0.0)) 
  612.     {
  613.         aoGAll.vDeletePos.x = CREAL(+MAX_NUM);
  614.         vSize.x = -vAt.x;
  615.     } 
  616.     else 
  617.     {
  618.         aoGAll.vDeletePos.x = CREAL(-MAX_NUM);
  619.         vSize.x = +vAt.x;
  620.     }
  621.  
  622.     if (vAt.y < CREAL(0.0)) 
  623.     {
  624.         aoGAll.vDeletePos.y = CREAL(+MAX_NUM);
  625.         vSize.y = -vAt.y;
  626.     } 
  627.     else 
  628.     {
  629.         aoGAll.vDeletePos.y = CREAL(-MAX_NUM);
  630.         vSize.y = +vAt.y;
  631.     }
  632.  
  633.     if (vAt.z < CREAL(0.0)) 
  634.     {
  635.         aoGAll.vDeletePos.z = CREAL(+MAX_NUM);
  636.         vSize.z = -vAt.z;
  637.     }
  638.     else 
  639.     {
  640.         aoGAll.vDeletePos.z = CREAL(-MAX_NUM);
  641.         vSize.z = +vAt.z;
  642.     }
  643.  
  644.     /* Determine the order that the axis will be compared in when performing
  645.      * the depth sort. 
  646.      */
  647.  
  648.     if (vSize.x > vSize.y) 
  649.     {
  650.         if (vSize.y > vSize.z) 
  651.         {
  652.             /* x > y > z */
  653.             aoGAll.nFirst = 0;
  654.             aoGAll.nSecond = 1;
  655.             aoGAll.nThird = 2;
  656.         } 
  657.         else 
  658.         {
  659.             /* y smallest */
  660.             aoGAll.nThird = 1;
  661.             if (vSize.x > vSize.z) 
  662.             {
  663.                 /* x > z > y */
  664.                 aoGAll.nFirst = 0;
  665.                 aoGAll.nSecond = 2;
  666.             } 
  667.             else 
  668.             {
  669.                 /* z > x > y */
  670.                 aoGAll.nFirst = 2;
  671.                 aoGAll.nSecond = 0;
  672.             }
  673.         }
  674.     }
  675.     else 
  676.     {
  677.         /* y > x */
  678.         if (vSize.y > vSize.z) 
  679.         {
  680.             /* y largest */
  681.             aoGAll.nFirst = 1;
  682.             if (vSize.x > vSize.z) 
  683.             {
  684.                 /* y > x > z */
  685.                 aoGAll.nSecond = 0;
  686.                 aoGAll.nThird = 2;
  687.             }
  688.             else 
  689.             {
  690.                 /* y > z > x */
  691.                 aoGAll.nSecond = 2;
  692.                 aoGAll.nThird = 0;
  693.             }
  694.         } 
  695.         else 
  696.         {
  697.             /* z > y > x */
  698.             aoGAll.nFirst = 2;
  699.             aoGAll.nSecond = 1;
  700.             aoGAll.nThird = 0;
  701.         }
  702.     }
  703.  
  704.     /* Determine the sort function that we will use based on the cameras
  705.      * at vector
  706.      */
  707.  
  708.     if (((RwReal *)&vAt)[aoGAll.nFirst] > CREAL(0.0)) 
  709.     {
  710.         /* Max1 */
  711.         if (((RwReal *)&vAt)[aoGAll.nSecond]>CREAL(0.0)) 
  712.         {
  713.             /* Max2 */
  714.             if (((RwReal *)&vAt)[aoGAll.nThird]>CREAL(0.0)) 
  715.             {
  716.                 /* Max 3*/
  717.                 aoGAll.fpCompare = FMaxSMaxTMax;
  718.             } 
  719.             else 
  720.             {
  721.                 /* Min 3 */
  722.                 aoGAll.fpCompare = FMaxSMaxTMin;
  723.             }
  724.         } 
  725.         else 
  726.         {
  727.             /* Min2 */
  728.             if (((RwReal *)&vAt)[aoGAll.nThird] > CREAL(0.0)) 
  729.             {
  730.                 /* Max 3*/
  731.                 aoGAll.fpCompare = FMaxSMinTMax;
  732.             } 
  733.             else 
  734.             {
  735.                 /* Min 3 */
  736.                 aoGAll.fpCompare = FMaxSMinTMin;
  737.             }
  738.         }
  739.     } 
  740.     else 
  741.     {
  742.         /* Min 1 */
  743.         if (((RwReal *)&vAt)[aoGAll.nSecond]>CREAL(0.0)) 
  744.         {
  745.             /* Max2 */
  746.             if (((RwReal *)&vAt)[aoGAll.nThird]>CREAL(0.0)) 
  747.             {
  748.                 /* Max 3*/
  749.                 aoGAll.fpCompare = FMinSMaxTMax;
  750.             } 
  751.             else 
  752.             {
  753.                 /* Min 3 */
  754.                 aoGAll.fpCompare = FMinSMaxTMin;
  755.             }
  756.         } 
  757.         else 
  758.         {
  759.             /* Min2 */
  760.             if (((RwReal *)&vAt)[aoGAll.nThird]>CREAL(0.0)) 
  761.             {
  762.                 /* Max 3*/
  763.                 aoGAll.fpCompare = FMinSMinTMax;
  764.             } 
  765.             else 
  766.             {
  767.                 /* Min 3 */
  768.                 aoGAll.fpCompare = FMinSMinTMin;
  769.             }
  770.         }
  771.     }
  772.  
  773.     /* Call the object update function for all of the objects in the street */
  774.  
  775.     oppObj = aoGAll.oppObjects;
  776.  
  777.     for (nCount=0; nCount < aoGAll.nEndObject; nCount++, oppObj++)
  778.     {
  779.         (*oppObj)->fpUpdate(*oppObj);
  780.     }
  781. }
  782.  
  783.  
  784. /************************************************************************
  785.  *
  786.  *      Function:       AllObjectsSetup()
  787.  *                      
  788.  *      Description:    Initialise the global object data structure
  789.  *
  790.  *      Parameters:     None
  791.  *
  792.  *      Return Value:   None
  793.  *
  794.  ************************************************************************/
  795. int AllObjectsSetup(void)
  796. {
  797.     aoGAll.oppObjects = (Object **) malloc(sizeof(Object *)*INITIAL_OBJECTS);
  798.     aoGAll.nAmoObjects = INITIAL_OBJECTS;
  799.     aoGAll.nEndObject = 0;
  800.  
  801.   return TRUE;
  802. }
  803.  
  804. /************************************************************************
  805.  *
  806.  *      Function:       AllObjectsAddObject()
  807.  *                      
  808.  *      Description:    Add an object to the list of global objects
  809.  *
  810.  *      Parameters:     opObj - the object to add to the global list
  811.  *
  812.  *      Return Value:   None
  813.  *
  814.  ************************************************************************/
  815. void AllObjectsAddObject(Object *opObj)
  816. {
  817.     if (aoGAll.nEndObject == aoGAll.nAmoObjects) 
  818.     {
  819.         /* The object list is full. Grow it a bit */
  820.         aoGAll.oppObjects = realloc(aoGAll.oppObjects,
  821.                                     sizeof(Object *) * (aoGAll.nAmoObjects + OBJ_INCREASE));
  822.         aoGAll.nAmoObjects += OBJ_INCREASE;
  823.     }
  824.  
  825.     /* Add the object to the list */
  826.     aoGAll.oppObjects[aoGAll.nEndObject++] = opObj;
  827. }
  828.  
  829. /************************************************************************
  830.  *
  831.  *      Function:       AllObjectsDestroy()
  832.  *                      
  833.  *      Description:    Destroy the global object data structure
  834.  *
  835.  *      Parameters:     None
  836.  *
  837.  *      Return Value:   None
  838.  *
  839.  ************************************************************************/
  840. void 
  841. AllObjectsDestroy(void)
  842. {
  843.     int nCount;
  844.     Object **oppObj;
  845.  
  846.     /* Destroy all of the objects first */
  847.  
  848.     oppObj = aoGAll.oppObjects;
  849.  
  850.     for (nCount=0; nCount < aoGAll.nEndObject; nCount++, oppObj++)
  851.     {
  852.         (*oppObj)->fpDestroy(*oppObj);
  853.     }
  854.  
  855.     /* Destroy the All Object structure */
  856.  
  857.     free(aoGAll.oppObjects);
  858. }
  859.  
  860. /************************************************************************
  861.  *
  862.  *      Function:       AllObjectsRender()
  863.  *                      
  864.  *      Description:    Sort the objects in the scene and then render them
  865.  *                      from furthest to nearest
  866.  *
  867.  *      Parameters:     None
  868.  *
  869.  *      Return Value:   None
  870.  *
  871.  ************************************************************************/
  872. void 
  873. AllObjectsRender(void)
  874. {
  875.     int nCount;     /* temporary loop control variable */
  876.     int nNewEnd;    /* the last object that was rendered */
  877.     Object **oppObj;
  878.  
  879.     /* Order all of the objects */
  880.  
  881.     qsort(aoGAll.oppObjects, aoGAll.nEndObject, sizeof(Object *),
  882.          aoGAll.fpCompare);
  883.  
  884.     /* Render each object using its own render function. We don't 
  885.      * attempt to render objects that are at the delete position
  886.      */
  887.  
  888.     nCount = 0;
  889.     oppObj = aoGAll.oppObjects;
  890.  
  891.     while ((nCount < aoGAll.nEndObject) &&
  892.            ((*oppObj)->vPos.x != CREAL(MAX_NUM)) &&
  893.            ((*oppObj)->vPos.x != CREAL(-MAX_NUM)) )
  894.     {
  895.         (*oppObj)->fpRender(*oppObj);
  896.  
  897.         oppObj++;
  898.         nCount++;
  899.     }
  900.  
  901.     /* Delete all the unwanted objects */
  902.  
  903.     nNewEnd = nCount;
  904.  
  905.     while (nCount < aoGAll.nEndObject)
  906.     {
  907.         (*oppObj)->fpDestroy(*oppObj);
  908.  
  909.         oppObj++;
  910.         nCount++;
  911.     }
  912.  
  913.     /* This is the last object now */
  914.     aoGAll.nEndObject = nNewEnd;
  915. }
  916.  
  917. /************************************************************************
  918.  *
  919.  *      Function:       AddStaticObject()
  920.  *                      
  921.  *      Description:    Read a clump and position it at a fixed location
  922.  *                      in the scene
  923.  *
  924.  *      Parameters:     x, y, z - fixed position for the object
  925.  *                      name - the RenderWare script file name
  926.  *
  927.  *      Return Value:   None
  928.  *
  929.  ************************************************************************/
  930. int 
  931. AddStaticObject(RwReal x, RwReal y, RwReal z, char *name)
  932. {
  933.     Object *opObj;
  934.     RwClump *cpClump;
  935.  
  936.     if (!(cpClump = DoRwReadShape(name))) 
  937.     {
  938.         return FALSE;
  939.     }
  940.     
  941.     /* Create the object data structure */
  942.     opObj = malloc(sizeof(Object));
  943.  
  944.     /* Setup the object and add it to the list of global objects */
  945.  
  946.     ObjectSetup(opObj, x, y, z, cpClump);
  947.     AllObjectsAddObject(opObj);
  948.  
  949.     return TRUE;
  950. }
  951.  
  952.