home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * File : object.c
- *
- * Abstract : An implementation of a "sub-class" of RenderWare clumps
- * which provides enhanced functionality such as binding a
- * light to a clump which acts as the visual representation
- * of a light and also stores the filename of the file from
- * which the clump was loaded.
- *
- * This application had been written to be compatible with
- * both the fixed and floating-point versions of the
- * RenderWare library, i.e., it uses the macros CREAL,
- * INT2REAL, RAdd, RDiv, RSub etc. If your application is
- * intended for the floating-point version of the library
- * only these macros are not necessary.
- *
- * Please note that this application is intended for
- * demonstration purposes only. No support will be
- * provided for this code and it comes with no warranty.
- *
- **********************************************************************
- *
- * This file is a product of Criterion Software Ltd.
- *
- * This file is provided as is with no warranties of any kind and is
- * provided without any obligation on Criterion Software Ltd. or
- * Canon Inc. to assist in its use or modification.
- *
- * Criterion Software Ltd. will not, under any
- * circumstances, be liable for any lost revenue or other damages arising
- * from the use of this file.
- *
- * Copyright (c) 1994, 1995 Criterion Software Ltd.
- * All Rights Reserved.
- *
- * RenderWare is a trademark of Canon Inc.
- *
- **********************************************************************/
-
- /**********************************************************************
- *
- * Comment:
- *
- * This code demonstrates the use of the user data pointer which is
- * supported by most RenderWare objects. The user data pointer allows
- * additional information to be stored with an object by setting the
- * user data pointer to an application defined structure.
- *
- * The viewer manipulates two main kinds of RenderWare objects, clumps
- * and lights. RenderWare lights are normally invisible but to make
- * manipulation uniform between the two object types we create a clump
- * to represent each light. We therefore need some mechanism to tie
- * a light and the clump which represents it together (and vice-versa).
- * This is one of the uses to which we put the user data to.
- *
- * Also, in order to give object's identifiable names and to allow us
- * to save them under their original filenames we need to be able to
- * store the filename of the file storing the clump. We also use the
- * user-data field for this purpose.
- *
- * We define a structure which holds a filename string and a light
- * object handle (which may be NULL if the clump does not represent
- * a light). An instance of this structure is stored in the user
- * data field of each clump. For lights, however, we simply store
- * the handle of the clump representing the light directly in the
- * user data field.
- *
- **********************************************************************/
-
- /**********************************************************************
- *
- * Header files.
- *
- **********************************************************************/
-
- /**********************************************************************
- *
- * Header files.
- *
- **********************************************************************/
-
- #include <windows.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <rwlib.h>
- #include <rwwin.h>
-
- #include "common.h"
- #include "object.h"
-
- /**********************************************************************
- *
- * Functions.
- *
- **********************************************************************/
-
- /**********************************************************************/
-
- /*
- * Read a clump from the given file. This function creates and
- * initializes the user data structure of the clump.
- *
- * RenderWare API Equivalent: RwReadShape()
- */
- RwClump *
- ReadClumpObj(char *fileName)
- {
- ClumpUserData *userData;
- RwClump *clump;
-
- /*
- * Allocate the user data for the new clump.
- */
- userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
- if (userData == NULL)
- return NULL;
-
- /*
- * Read the clump.
- */
- clump = RwReadShape(fileName);
-
- /*
- * If all went well then intialize the user data pointer and attach
- * it to the clump.
- */
- if (clump == NULL)
- {
- free((void *)userData);
- return NULL;
- }
- else
- {
- /*
- * This clump does not represent a light.
- */
- userData->light = NULL;
- userData->datatype = rfIsClump;
- strcpy(userData->fileName, fileName);
- RwSetClumpData(clump, (void *)userData);
- return clump;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Create a sprite from the bitmap contained in the given file.
- *
- * RenderWare API Equivalent: RwCreateSprite()
- */
- RwClump *CreateSpriteObj(char *fileName)
- {
- ClumpUserData *userData;
- RwClump *clump;
-
- /*
- * Allocate the user data for the new clump.
- */
- userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
- if (userData == NULL)
- return NULL;
-
- /*
- * Read the clump.
- */
- clump = RwCreateSprite(RwGetNamedTexture(fileName));
-
- /*
- * If all went well then intialize the user data pointer and attach
- * it to the clump.
- */
- if (clump == NULL)
- {
- free((void *)userData);
- return NULL;
- }
- else
- {
- /*
- * This clump does not represent a light.
- */
- userData->light = NULL;
- userData->datatype = rfIsSprite;
- strcpy(userData->fileName, fileName);
- RwSetClumpData(clump, (void *)userData);
- return clump;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Create a light of the given type. A clump is built which represents
- * this light and is attached to the user data field of the light.
- *
- * NOTE: We return a pointer to the clump build rather than the light
- * as clump's are the main object type of the viewer.
- *
- * RenderWare API Equivalent: RwCreateLight()
- */
- RwLight *
- CreateLightObj(RwLightType kind)
- {
- ClumpUserData *userData;
- RwLight *light;
- RwClump *clump;
-
- /*
- * Allocate the user data for the new clump.
- */
- userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
- if (userData == NULL)
- return NULL;
-
- /*
- * Create the RenderWare light. The supplied vector is just a dummy
- * as it will be overwritten when we copy the clump's matrix to the
- * light.
- */
- light = RwCreateLight(kind, CREAL(0.0), CREAL(0.0), CREAL(1.0),
- CREAL(1.0));
- if (light == NULL)
- {
- free((void *)userData);
- return NULL;
- }
-
- /*
- * Build the clump. For each light type the clump is unshaded, white
- * wireframe so there surface conditions are set up globally.
- */
- RwModelBegin();
- RwClumpBegin();
- /*
- * We don't want the lights to take part in shading (it would
- * look strange if lights illuminated themselves) so we turn
- * of shading by setting diffuse and specular reflection to
- * CREAL(0.0) and we ensure a nice bright white by setting
- * ambient to CREAL(1.0).
- */
- //RwSetSurface(CREAL(1.0), CREAL(0.0), CREAL(0.0));
- RwSetSurface(CREAL(0.0), CREAL(0.0), CREAL(0.0));
- RwSetSurfaceColor(CREAL(1.0), CREAL(1.0), CREAL(1.0));
- RwSetSurfaceGeometrySampling(rwWIREFRAME);
-
- /*
- * The RenderWare geometric primitives are designed to be
- * oriented up the Y axis by default. Here, however, we
- * want them point down the Z axis as the clump's local
- * Z axis will be same as the light's direction. So the
- * first thing we do is perform a rotation around X of
- * CREAL(90.0).
- */
- RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(90.0));
-
- switch (kind)
- {
- case rwDIRECTIONAL:
- /*
- * The directional light is represented as a 3D
- * arrow built from a cone and a cylinder. We want
- * the tip of the arrow to be the origin of the
- * clump (the point about which we will rotate the
- * clump) so we translate down and build the arrow
- * so the tip of the cone is at the origin of local
- * space.
- */
- RwTranslateCTM(CREAL(0.0), CREAL(-0.4), CREAL(0.0));
-
- /*
- * The arrow head.
- */
- RwCone(CREAL(0.4), CREAL(0.2), 12);
-
- /*
- * We want to cap the cone. Rather than using a disc
- * we will use a cylinder of zero height. This is
- * a useful trick for building a circle with a hole
- * in it.
- */
- RwCylinder(CREAL(0.0), CREAL(0.1), CREAL(0.2), 12);
-
- /*
- * The shaft of the arrow.
- */
- RwTranslateCTM(CREAL(0.0), CREAL(-0.4), CREAL(0.0));
- RwCylinder(CREAL(0.4), CREAL(0.1), CREAL(0.1), 12);
-
- /*
- * Cap the shaft of the arrow with a disc. The negative
- * radius looks a little odd but this is a good trick for
- * flipping the polygons to point the other way, i.e.,
- * to make the polygons point down rather than up.
- */
- RwDisc(CREAL(0.0), CREAL(-0.1), 12);
-
- break;
-
- case rwPOINT:
- /*
- * A point light source is represented as a simple
- * sphere. The origin of the sphere is the position
- * of the light.
- */
- RwSphere(CREAL(0.2), 3);
-
- break;
-
- case rwCONICAL:
- /*
- * A conical light source is represented as an inverse
- * cone. The sharp end points in the opposite direction
- * from the light vector. The tip of the cone is also the
- * position of the light.The normal orientation of a cone
- * is to have the base at the bottom and the tip at the
- * top (in Y). We want the base at the top and the tip
- * pointing down so we rotate everything 180 degrees about
- * X before building the code.
- */
- RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.0));
- RwCone(CREAL(0.4), CREAL(0.2), 12);
-
- /*
- * Cap the cone with a disc. The negative radius looks a
- * little odd but this is a good trick for flipping the
- * polygons to point the other way, i.e., to make the
- * polygons point down rather than up
- */
- RwDisc(CREAL(0.0), CREAL(-0.2), 12);
-
- break;
- }
-
- RwClumpEnd(&clump);
- RwModelEnd();
-
- if (clump == NULL)
- {
- /*
- * If the clump failed for any reason cleanup and exit with
- * failure.
- */
- free((void *)userData);
- RwDestroyLight(light);
- return NULL;
- }
- else
- {
- /*
- * Initialize the user data field of the clump and attach it.
- * This clump has no filename as it has not been loaded from
- * a file.
- */
- userData->fileName[0] = '\0';
- userData->light = light;
- userData->datatype = rfIsLight;
- RwSetClumpData(clump, (void *)userData);
-
- /*
- * Attach the back pointer from the light to the clump.
- */
- RwSetLightData(light, (void *)clump);
-
- RwPushScratchMatrix();
- /*
- * Move the clump to the default position.
- */
- RwTranslateMatrix(RwScratchMatrix(),
- CREAL(1.0), CREAL(1.0), CREAL(1.0), rwREPLACE);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
- CREAL(225.0), rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(0.0), CREAL(0.0),
- CREAL(-45.0), rwPOSTCONCAT);
- RwTransformClumpJoint(clump, RwScratchMatrix(), rwREPLACE);
- RwGetClumpLTM(clump, RwScratchMatrix());
-
- /*
- * Make the position and/or orientation of the light match the
- * clump.
- */
- RwTransformLight(light, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
-
- return light;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Duplicate the given clump object and its associated light (if it has
- * one).
- *
- * RenderWare API Equivalent: RwDuplicateClump(), RwDuplicateLight().
- */
- RwClump *
- DuplicateClumpObj(RwClump *clump)
- {
- ClumpUserData *userData;
- ClumpUserData *newUserData;
- RwClump *newClump;
- RwLight *light;
- RwLight *newLight;
-
- /*
- * Allocate the user data for the new clump.
- */
- newUserData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
- if (newUserData == NULL)
- return NULL;
-
- /*
- * Duplicate the clump.
- */
- newClump = RwDuplicateClump(clump);
- if (newClump == NULL)
- {
- free((void *)newUserData);
- return NULL;
- }
-
- if (ISCLUMPLIGHT(clump))
- {
- /*
- * The original clump represents a light so get the source
- * light and duplicate it.
- */
- light = GETCLUMPLIGHT(clump);
- newLight = RwDuplicateLight(light);
- if (light != NULL)
- {
- /*
- * Initialize the user data and attach it to the clump.
- */
- newUserData->fileName[0] = '\0';
- newUserData->light = newLight;
- newUserData->datatype = rfIsLight;
- RwSetClumpData(newClump, (void *)newUserData);
-
- /*
- * Set the back pointer from the light to the clump.
- */
- RwSetLightData(newLight, (void *)newClump);
-
- return newClump;
- }
- else
- {
- RwDestroyClump(clump);
- free((void *)newUserData);
- return NULL;
- }
- }
- else
- {
- /*
- * The clump does not represent a light so simply copy
- * the filename across and set the user data.
- */
- userData = GETCLUMPUSERDATA(clump);
- strcpy(newUserData->fileName, userData->fileName);
- newUserData->light = NULL;
- newUserData->datatype = rfIsClump;
- RwSetClumpData(newClump, (void *)newUserData);
-
- return newClump;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Add a clump object to the given scene. This function will also add the
- * light object to the scene if the the clump represents a light.
- *
- * RenderWare API Equivalent: RwAddClumpToScene(), RwAddLightToScene().
- */
- RwScene *
- AddClumpObjToScene(RwScene *scene, RwClump *clump)
- {
- /*
- * Add the clump to the scene.
- */
- RwAddClumpToScene(scene, clump);
-
- if (ISCLUMPLIGHT(clump))
- {
- /*
- * If this clump represents a light then add the light to the
- * scene also.
- */
- RwAddLightToScene(scene, GETCLUMPLIGHT(clump));
- }
-
- return scene;
- }
-
- /**********************************************************************/
-
- /*
- * Add a light object to the given scene. This function will also add the
- * clump object representing a light to the scene.
- *
- * RenderWare API Equivalent: RwAddLightToScene(), RwAddClumpToScene().
- */
- RwScene *
- AddLightObjToScene(RwScene *scene, RwLight *light)
- {
- RwClump *clump;
-
- /*
- * Get the clump which represents this light.
- */
- clump = GETLIGHTCLUMP(light);
-
- /*
- * Add both objects to the scene.
- */
- RwAddLightToScene(scene, light);
- RwAddClumpToScene(scene, clump);
-
- return scene;
- }
-
- /**********************************************************************/
-
- /*
- * Set the brightness of the given light object. This function also
- * updates the visual appearance of the clump object representing the
- * light to reflect the new brightness.
- *
- * RenderWare API Equivalent: RwSetLightBrightness().
- */
- RwLight *
- SetLightObjBrightness(RwLight *light, RwReal bright)
- {
- RwClump *clump;
-
- /*
- * Set the brightness of the light.
- */
- RwSetLightBrightness(light, bright);
-
- /*
- * Update the materials of the associated clump to reflect the new
- * brightness.
- */
- clump = GETLIGHTCLUMP(light);
- RwPushCurrentMaterial();
- RwSetMaterialSurface(RwCurrentMaterial(), bright, CREAL(0.0), CREAL(0.0));
- RwSetMaterialColor(RwCurrentMaterial(), CREAL(1.0), CREAL(1.0), CREAL(1.0));
- RwSetMaterialGeometrySampling(RwCurrentMaterial(), rwWIREFRAME);
- RwForAllPolygonsInClumpPointer(clump, (RwPolygon3dFuncPointer)RwSetPolygonMaterial,
- RwCurrentMaterial());
- RwPopCurrentMaterial();
-
- return light;
- }
-
- /**********************************************************************/
-
- /*
- * Set the color of the given light object. This function also
- * updates the visual appearance of the clump object representing the
- * light to reflect the new color.
- *
- * RenderWare API Equivalent: RwSetLightColor().
- */
- RwLight *
- SetLightObjColor(RwLight *light, RwReal r, RwReal g, RwReal b)
- {
- RwClump *clump;
-
- /*
- * Set the color of the light.
- */
- RwSetLightColor(light, r, g, b);
-
- /*
- * Update the materials of the associated clump to reflect the new
- * brightness.
- */
- clump = GETLIGHTCLUMP(light);
- RwPushCurrentMaterial();
- RwSetMaterialSurface(RwCurrentMaterial(), CREAL(0.70), CREAL(0.0), CREAL(0.0));
- RwSetMaterialColor(RwCurrentMaterial(), r, g, b);
- RwSetMaterialGeometrySampling(RwCurrentMaterial(), rwWIREFRAME);
- RwForAllPolygonsInClumpPointer(clump, (RwPolygon3dFuncPointer)RwSetPolygonMaterial,
- RwCurrentMaterial());
- RwPopCurrentMaterial();
-
- return light;
- }
-
- /**********************************************************************/
-
- /*
- * Turn the clump which is the visible representation of a light on or off.
- * This function does not turn the light itself on or off, it only
- * shows or hides the visible representation of that light.
- *
- * RenderWare API Equivalent: RwSetClumpState().
- */
- RwLight *
- SetLightObjVisibleState(RwLight *light, RwState state)
- {
- RwSetClumpState(GETLIGHTCLUMP(light), state);
-
- return light;
- }
-
- /**********************************************************************/
-
- /*
- * Destory the given clump object (and its associated light if it has
- * one). This function will also free the user data structure allocated
- * for the clump.
- *
- * RenderWare API Equivalent: RwDestoryClump()
- */
- void
- DestroyClumpObj(RwClump *clump)
- {
- ClumpUserData *userData;
-
- /*
- * If this clump is a root clump and it is the representation
- * of a light then we must destory the associated light and
- * the user data. Otherwise all we need to do is to destroy
- * the clump itself.
- */
- if (RwGetClumpParent(clump) == NULL)
- {
- userData = GETCLUMPUSERDATA(clump);
- if (userData != NULL)
- {
- if (userData->light != NULL)
- {
- /*
- * If this clump represents a light blow the associated
- * light away.
- */
- RwDestroyLight(userData->light);
- }
-
- /*
- * Free the user data.
- */
- free((void *)userData);
- }
- }
-
- /*
- * Blow the clump away...
- */
- RwDestroyClump(clump);
- }
-
- /**********************************************************************/
-