home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwwin / object.c1_ / object.bin
Text File  |  1995-11-14  |  20KB  |  613 lines

  1. /**********************************************************************
  2.  *
  3.  * File :     object.c
  4.  *
  5.  * Abstract : An implementation of a "sub-class" of RenderWare clumps
  6.  *            which provides enhanced functionality such as binding a
  7.  *            light to a clump which acts as the visual representation
  8.  *            of a light and also stores the filename of the file from
  9.  *            which the clump was loaded.
  10.  *
  11.  *            This application had been written to be compatible with
  12.  *            both the fixed and floating-point versions of the
  13.  *            RenderWare library, i.e., it uses the macros CREAL,
  14.  *            INT2REAL, RAdd, RDiv, RSub etc. If your application is
  15.  *            intended for the floating-point version of the library
  16.  *            only these macros are not necessary.
  17.  *
  18.  *            Please note that this application is intended for
  19.  *            demonstration purposes only. No support will be
  20.  *            provided for this code and it comes with no warranty.
  21.  *
  22.  **********************************************************************
  23.  *
  24.  * This file is a product of Criterion Software Ltd.
  25.  *
  26.  * This file is provided as is with no warranties of any kind and is
  27.  * provided without any obligation on Criterion Software Ltd. or
  28.  * Canon Inc. to assist in its use or modification.
  29.  *
  30.  * Criterion Software Ltd. will not, under any
  31.  * circumstances, be liable for any lost revenue or other damages arising
  32.  * from the use of this file.
  33.  *
  34.  * Copyright (c) 1994, 1995 Criterion Software Ltd.
  35.  * All Rights Reserved.
  36.  *
  37.  * RenderWare is a trademark of Canon Inc.
  38.  *
  39.  **********************************************************************/
  40.  
  41. /**********************************************************************
  42.  *
  43.  * Comment:
  44.  *
  45.  * This code demonstrates the use of the user data pointer which is
  46.  * supported by most RenderWare objects. The user data pointer allows
  47.  * additional information to be stored with an object by setting the
  48.  * user data pointer to an application defined structure.
  49.  *
  50.  * The viewer manipulates two main kinds of RenderWare objects, clumps
  51.  * and lights. RenderWare lights are normally invisible but to make
  52.  * manipulation uniform between the two object types we create a clump
  53.  * to represent each light. We therefore need some mechanism to tie
  54.  * a light and the clump which represents it together (and vice-versa).
  55.  * This is one of the uses to which we put the user data to.
  56.  *
  57.  * Also, in order to give object's identifiable names and to allow us
  58.  * to save them under their original filenames we need to be able to
  59.  * store the filename of the file storing the clump. We also use the
  60.  * user-data field for this purpose.
  61.  *
  62.  * We define a structure which holds a filename string and a light
  63.  * object handle (which may be NULL if the clump does not represent
  64.  * a light). An instance of this structure is stored in the user
  65.  * data field of each clump. For lights, however, we simply store
  66.  * the handle of the clump representing the light directly in the
  67.  * user data field.
  68.  *
  69.  **********************************************************************/
  70.  
  71. /**********************************************************************
  72.  *
  73.  * Header files.
  74.  *
  75.  **********************************************************************/
  76.  
  77. /**********************************************************************
  78.  *
  79.  * Header files.
  80.  *
  81.  **********************************************************************/
  82.  
  83. #include <windows.h>
  84. #include <stdlib.h>
  85. #include <string.h>
  86.  
  87. #include <rwlib.h>
  88. #include <rwwin.h>
  89.  
  90. #include "common.h"
  91. #include "object.h"
  92.  
  93. /**********************************************************************
  94.  *
  95.  * Functions.
  96.  *
  97.  **********************************************************************/
  98.  
  99. /**********************************************************************/
  100.  
  101. /*
  102.  * Read a clump from the given file. This function creates and
  103.  * initializes the user data structure of the clump.
  104.  *
  105.  * RenderWare API Equivalent: RwReadShape()
  106.  */
  107. RwClump *
  108. ReadClumpObj(char *fileName)
  109. {
  110.     ClumpUserData *userData;
  111.     RwClump       *clump;
  112.  
  113.     /*
  114.      * Allocate the user data for the new clump.
  115.      */
  116.     userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
  117.     if (userData == NULL)
  118.         return NULL;
  119.         
  120.     /*
  121.      * Read the clump.
  122.      */
  123.     clump = RwReadShape(fileName);
  124.     
  125.     /*
  126.      * If all went well then intialize the user data pointer and attach
  127.      * it to the clump.
  128.      */
  129.     if (clump == NULL)
  130.     {
  131.         free((void *)userData);
  132.         return NULL;
  133.     }
  134.     else
  135.     {
  136.         /*
  137.          * This clump does not represent a light.
  138.          */
  139.         userData->light = NULL;
  140.         strcpy(userData->fileName, fileName);
  141.         RwSetClumpData(clump, (void *)userData);
  142.         return clump;
  143.     }
  144. }
  145.  
  146. /**********************************************************************/
  147.  
  148. /*
  149.  * Create a light of the given type. A clump is built which represents
  150.  * this light and is attached to the user data field of the light.
  151.  *
  152.  * NOTE: We return a pointer to the clump build rather than the light
  153.  * as clump's are the main object type of the viewer.
  154.  *
  155.  * RenderWare API Equivalent: RwCreateLight()
  156.  */
  157. RwLight *
  158. CreateLightObj(RwLightType kind)
  159. {
  160.     ClumpUserData *userData;
  161.     RwLight       *light;
  162.     RwClump       *clump;
  163.     
  164.     /*
  165.      * Allocate the user data for the new clump.
  166.      */
  167.     userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
  168.     if (userData == NULL)
  169.         return NULL;
  170.         
  171.     /*
  172.      * Create the RenderWare light. The supplied vector is just a dummy
  173.      * as it will be overwritten when we copy the clump's matrix to the
  174.      * light.
  175.      */
  176.     light = RwCreateLight(kind, CREAL(0.0), CREAL(0.0), CREAL(1.0),
  177.                           CREAL(1.0));
  178.     if (light == NULL)
  179.     {
  180.         free((void *)userData);
  181.         return NULL;
  182.     }
  183.     
  184.     /*
  185.      * Build the clump. For each light type the clump is unshaded, white
  186.      * wireframe so there surface conditions are set up globally.
  187.      */
  188.     RwModelBegin();
  189.         RwClumpBegin();
  190.             /*
  191.              * We don't want the lights to take part in shading (it would
  192.              * look strange if lights illuminated themselves) so we turn
  193.              * of shading by setting diffuse and specular reflection to
  194.              * CREAL(0.0) and we ensure a nice bright white by setting
  195.              * ambient to CREAL(1.0).
  196.              */
  197.             RwSetSurface(CREAL(1.0), CREAL(0.0), CREAL(0.0));
  198.             RwSetSurfaceColor(CREAL(1.0), CREAL(1.0), CREAL(1.0));
  199.             RwSetSurfaceGeometrySampling(rwWIREFRAME);
  200.             
  201.             /*
  202.              * The RenderWare geometric primitives are designed to be
  203.              * oriented up the Y axis by default. Here, however, we
  204.              * want them point down the Z axis as the clump's local
  205.              * Z axis will be same as the light's direction. So the
  206.              * first thing we do is perform a rotation around X of
  207.              * CREAL(90.0).
  208.              */     
  209.             RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(90.0));
  210.  
  211.             switch (kind)
  212.             {
  213.                 case rwDIRECTIONAL:
  214.                     /*
  215.                      * The directional light is represented as a 3D
  216.                      * arrow built from a cone and a cylinder. We want
  217.                      * the tip of the arrow to be the origin of the
  218.                      * clump (the point about which we will rotate the
  219.                      * clump) so we translate down and build the arrow
  220.                      * so the tip of the cone is at the origin of local
  221.                      * space.
  222.                      */
  223.                     RwTranslateCTM(CREAL(0.0), CREAL(-0.4), CREAL(0.0));
  224.                     
  225.                     /*
  226.                      * The arrow head.
  227.                      */
  228.                     RwCone(CREAL(0.4), CREAL(0.2), 12);
  229.                     
  230.                     /*
  231.                      * We want to cap the cone. Rather than using a disc
  232.                      * we will use a cylinder of zero height. This is 
  233.                      * a useful trick for building a circle with a hole
  234.                      * in it.
  235.                      */
  236.                     RwCylinder(CREAL(0.0), CREAL(0.1), CREAL(0.2), 12);
  237.                     
  238.                     /*
  239.                      * The shaft of the arrow.
  240.                      */
  241.                     RwTranslateCTM(CREAL(0.0), CREAL(-0.4), CREAL(0.0));
  242.                     RwCylinder(CREAL(0.4), CREAL(0.1), CREAL(0.1), 12);
  243.                     
  244.                     /*
  245.                      * Cap the shaft of the arrow with a disc. The negative
  246.                      * radius looks a little odd but this is a good trick for
  247.                      * flipping the polygons to point the other way, i.e., 
  248.                      * to make the polygons point down rather than up.
  249.                      */
  250.                     RwDisc(CREAL(0.0), CREAL(-0.1), 12);
  251.                     
  252.                     break;
  253.                     
  254.                 case rwPOINT:
  255.                     /*
  256.                      * A point light source is represented as a simple
  257.                      * sphere. The origin of the sphere is the position
  258.                      * of the light.
  259.                      */
  260.                     RwSphere(CREAL(0.2), 3);
  261.                     
  262.                     break;
  263.                     
  264.                 case rwCONICAL:
  265.                     /*
  266.                      * A conical light source is represented as an inverse
  267.                      * cone. The sharp end points in the opposite direction
  268.                      * from the light vector. The tip of the cone is also the
  269.                      * position of the light.The normal orientation of a cone
  270.                      * is to have the base at the bottom and the tip at the
  271.                      * top (in Y). We want the base at the top and the tip
  272.                      * pointing down so we rotate everything 180 degrees about
  273.                      * X before building the code.
  274.                      */
  275.                     RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.0));
  276.                     RwCone(CREAL(0.4), CREAL(0.2), 12);
  277.                     
  278.                     /*
  279.                      * Cap the cone with a disc. The negative radius looks a
  280.                      * little odd but this is a good trick for flipping the
  281.                      * polygons to point the other way, i.e., to make the
  282.                      * polygons point down rather than up
  283.                      */
  284.                     RwDisc(CREAL(0.0), CREAL(-0.2), 12);
  285.                     
  286.                     break;
  287.             }
  288.         
  289.         RwClumpEnd(&clump);
  290.     RwModelEnd();
  291.     
  292.     if (clump == NULL)
  293.     {
  294.         /*
  295.          * If the clump failed for any reason cleanup and exit with
  296.          * failure.
  297.          */
  298.         free((void *)userData);
  299.         RwDestroyLight(light);
  300.         return NULL;
  301.     }
  302.     else
  303.     {
  304.         /*
  305.          * Initialize the user data field of the clump and attach it.
  306.          * This clump has no filename as it has not been loaded from
  307.          * a file.
  308.          */
  309.         userData->fileName[0] = '\0';
  310.         userData->light       = light;
  311.         RwSetClumpData(clump, (void *)userData);
  312.         
  313.         /*
  314.          * Attach the back pointer from the light to the clump.
  315.          */
  316.         RwSetLightData(light, (void *)clump);
  317.         
  318.         RwPushScratchMatrix();
  319.             /*
  320.              * Move the clump to the default position.
  321.              */
  322.             RwTranslateMatrix(RwScratchMatrix(),
  323.                               CREAL(1.0), CREAL(1.0), CREAL(1.0), rwREPLACE);
  324.             RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
  325.             RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
  326.                            CREAL(225.0), rwREPLACE);
  327.             RwRotateMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(0.0), CREAL(0.0),
  328.                            CREAL(-45.0), rwPOSTCONCAT);
  329.             RwTransformClumpJoint(clump, RwScratchMatrix(), rwREPLACE);
  330.             RwGetClumpLTM(clump, RwScratchMatrix());
  331.     
  332.             /*
  333.              * Make the position and/or orientation of the light match the
  334.              * clump.
  335.              */
  336.             RwTransformLight(light, RwScratchMatrix(), rwREPLACE);
  337.         RwPopScratchMatrix();
  338.     
  339.         return light;
  340.     }
  341. }
  342.  
  343. /**********************************************************************/
  344.  
  345. /*
  346.  * Duplicate the given clump object and its associated light (if it has
  347.  * one).
  348.  *
  349.  * RenderWare API Equivalent: RwDuplicateClump(), RwDuplicateLight().
  350.  */
  351. RwClump *
  352. DuplicateClumpObj(RwClump *clump)
  353. {
  354.     ClumpUserData *userData;
  355.     ClumpUserData *newUserData;
  356.     RwClump       *newClump;
  357.     RwLight       *light;
  358.     RwLight       *newLight;
  359.     
  360.     /*
  361.      * Allocate the user data for the new clump.
  362.      */
  363.     newUserData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
  364.     if (newUserData == NULL)
  365.         return NULL;
  366.         
  367.     /*
  368.      * Duplicate the clump.
  369.      */
  370.     newClump = RwDuplicateClump(clump);
  371.     if (newClump == NULL)
  372.     {
  373.         free((void *)newUserData);
  374.         return NULL;
  375.     }
  376.  
  377.     if (ISCLUMPLIGHT(clump))
  378.     {
  379.         /*
  380.          * The original clump represents a light so get the source
  381.          * light and duplicate it.
  382.          */
  383.         light = GETCLUMPLIGHT(clump);
  384.         newLight = RwDuplicateLight(light);
  385.         if (light != NULL)
  386.         {
  387.             /*
  388.              * Initialize the user data and attach it to the clump.
  389.              */
  390.             newUserData->fileName[0] = '\0';
  391.             newUserData->light = newLight;
  392.             RwSetClumpData(newClump, (void *)newUserData);
  393.             
  394.             /*
  395.              * Set the back pointer from the light to the clump.
  396.              */
  397.             RwSetLightData(newLight, (void *)newClump);
  398.             
  399.             return newClump;
  400.         }
  401.         else
  402.         {
  403.             RwDestroyClump(clump);
  404.             free((void *)newUserData);
  405.             return NULL;
  406.         }
  407.     }
  408.     else
  409.     {
  410.         /*
  411.          * The clump does not represent a light so simply copy
  412.          * the filename across and set the user data.
  413.          */
  414.         userData = GETCLUMPUSERDATA(clump);
  415.         strcpy(newUserData->fileName, userData->fileName);
  416.         newUserData->light = NULL;
  417.         RwSetClumpData(newClump, (void *)newUserData);
  418.         
  419.         return newClump;
  420.     }    
  421. }
  422.  
  423. /**********************************************************************/
  424.  
  425. /*
  426.  * Add a clump object to the given scene. This function will also add the
  427.  * light object to the scene if the the clump represents a light.
  428.  *
  429.  * RenderWare API Equivalent: RwAddClumpToScene(), RwAddLightToScene().
  430.  */
  431. RwScene *
  432. AddClumpObjToScene(RwScene *scene, RwClump *clump)
  433. {
  434.     /*
  435.      * Add the clump to the scene.
  436.      */
  437.     RwAddClumpToScene(scene, clump);
  438.     
  439.     if (ISCLUMPLIGHT(clump))
  440.     {    
  441.         /*
  442.          * If this clump represents a light then add the light to the
  443.          * scene also.
  444.          */
  445.         RwAddLightToScene(scene, GETCLUMPLIGHT(clump));
  446.     }
  447.     
  448.     return scene;
  449. }
  450.  
  451. /**********************************************************************/
  452.  
  453. /*
  454.  * Add a light object to the given scene. This function will also add the
  455.  * clump object representing a light to the scene.
  456.  *
  457.  * RenderWare API Equivalent: RwAddLightToScene(), RwAddClumpToScene().
  458.  */
  459. RwScene *
  460. AddLightObjToScene(RwScene *scene, RwLight *light)
  461. {
  462.     RwClump *clump;
  463.     
  464.     /*
  465.      * Get the clump which represents this light.
  466.      */
  467.     clump = GETLIGHTCLUMP(light);
  468.     
  469.     /*
  470.      * Add both objects to the scene.
  471.      */
  472.     RwAddLightToScene(scene, light);
  473.     RwAddClumpToScene(scene, clump);
  474.     
  475.     return scene;
  476. }
  477.  
  478. /**********************************************************************/
  479.  
  480. /*
  481.  * Set the brightness of the given light object. This function also
  482.  * updates the visual appearance of the clump object representing the
  483.  * light to reflect the new brightness.
  484.  *
  485.  * RenderWare API Equivalent: RwSetLightBrightness().
  486.  */
  487. RwLight *
  488. SetLightObjBrightness(RwLight *light, RwReal bright)
  489. {
  490.     RwClump *clump;
  491.  
  492.     /*
  493.      * Set the brightness of the light.
  494.      */
  495.     RwSetLightBrightness(light, bright);
  496.  
  497.     /*
  498.      * Update the materials of the associated clump to reflect the new
  499.      * brightness.
  500.      */
  501.     clump = GETLIGHTCLUMP(light);
  502.     RwPushCurrentMaterial();
  503.         RwSetMaterialSurface(RwCurrentMaterial(), bright, CREAL(0.0), CREAL(0.0));
  504.         RwSetMaterialColor(RwCurrentMaterial(), CREAL(1.0), CREAL(1.0), CREAL(1.0));
  505.         RwSetMaterialGeometrySampling(RwCurrentMaterial(), rwWIREFRAME);
  506.         RwForAllPolygonsInClumpPointer(clump, (RwPolygon3dFuncPointer)RwSetPolygonMaterial,
  507.                                        RwCurrentMaterial());
  508.     RwPopCurrentMaterial();
  509.     
  510.     return light;
  511. }
  512.  
  513. /**********************************************************************/
  514.  
  515. /*
  516.  * Set the color of the given light object. This function also
  517.  * updates the visual appearance of the clump object representing the
  518.  * light to reflect the new color.
  519.  *
  520.  * RenderWare API Equivalent: RwSetLightColor().
  521.  */
  522. RwLight *
  523. SetLightObjColor(RwLight *light, RwReal r, RwReal g, RwReal b)
  524. {
  525.     RwClump *clump;
  526.  
  527.     /*
  528.      * Set the color of the light.
  529.      */
  530.     RwSetLightColor(light, r, g, b);
  531.  
  532.     /*
  533.      * Update the materials of the associated clump to reflect the new
  534.      * brightness.
  535.      */
  536.     clump = GETLIGHTCLUMP(light);
  537.     RwPushCurrentMaterial();
  538.         RwSetMaterialSurface(RwCurrentMaterial(), CREAL(0.70), CREAL(0.0), CREAL(0.0));
  539.         RwSetMaterialColor(RwCurrentMaterial(), r, g, b);
  540.         RwSetMaterialGeometrySampling(RwCurrentMaterial(), rwWIREFRAME);
  541.         RwForAllPolygonsInClumpPointer(clump, (RwPolygon3dFuncPointer)RwSetPolygonMaterial,
  542.                                        RwCurrentMaterial());
  543.     RwPopCurrentMaterial();
  544.     
  545.     return light;
  546. }
  547.  
  548. /**********************************************************************/
  549.  
  550. /*
  551.  * Turn the clump which is the visible representation of a light on or off.
  552.  * This function does not turn the light itself on or off, it only
  553.  * shows or hides the visible representation of that light.
  554.  *
  555.  * RenderWare API Equivalent: RwSetClumpState().
  556.  */
  557. RwLight *
  558. SetLightObjVisibleState(RwLight *light, RwState state)
  559. {
  560.     RwSetClumpState(GETLIGHTCLUMP(light), state);
  561.     
  562.     return light;
  563. }
  564.  
  565. /**********************************************************************/
  566.  
  567. /*
  568.  * Destory the given clump object (and its associated light if it has
  569.  * one). This function will also free the user data structure allocated
  570.  * for the clump.
  571.  *
  572.  * RenderWare API Equivalent: RwDestoryClump()
  573.  */
  574. void
  575. DestroyClumpObj(RwClump *clump)
  576. {
  577.     ClumpUserData *userData;
  578.     
  579.     /*
  580.      * If this clump is a root clump and it is the representation
  581.      * of a light then we must destory the associated light and
  582.      * the user data. Otherwise all we need to do is to destroy
  583.      * the clump itself.
  584.      */
  585.     if (RwGetClumpParent(clump) == NULL)
  586.     { 
  587.         userData = GETCLUMPUSERDATA(clump);
  588.         if (userData != NULL)
  589.         {
  590.             if (userData->light != NULL)
  591.             {
  592.                 /*
  593.                  * If this clump represents a light blow the associated
  594.                  * light away.
  595.                  */
  596.                 RwDestroyLight(userData->light);
  597.             }
  598.  
  599.             /*
  600.              * Free the user data.
  601.              */
  602.             free((void *)userData);
  603.         }
  604.     }
  605.     
  606.     /*
  607.      * Blow the clump away...
  608.      */
  609.     RwDestroyClump(clump);
  610. }
  611.  
  612. /**********************************************************************/
  613.