home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-14 | 31.3 KB | 1,041 lines |
- /**********************************************************************
- *
- * File : rolltype.c
- *
- * Abstract : Implementation of the data type encapsulating an
- * inidividual rollercoaster.
- *
- * 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 Criterion Software Ltd.
- * All Rights Reserved.
- *
- * RenderWare is a trademark of Canon Inc.
- *
- **********************************************************************/
-
- /**********************************************************************
- *
- * Header files.
- *
- **********************************************************************/
-
- #include <windows.h>
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
-
- #include <rwlib.h>
- #include <rwwin31.h>
-
- #include "rolltype.h"
-
- /**********************************************************************
- *
- * Constants.
- *
- **********************************************************************/
-
- /*
- * Default description of the rollercoaster.
- */
- #define DEFAULTCOASTERDESCRIPTION "New Rollercoaster"
-
- #define TRACKPOLYGONTAG 1
- #define GROUNDPOLYGONTAG 2
-
- /**********************************************************************
- *
- * Type definitions.
- *
- **********************************************************************/
-
- /**********************************************************************
- *
- * Functions.
- *
- **********************************************************************/
-
- /**********************************************************************/
-
- /*
- * Create a default spline (a spline with the given number of control
- * pointer arranged in a circle of the given radius).
- */
- static RwSpline *
- CreateCoasterDefaultSpline(void)
- {
- RwReal angleDelta;
- int i;
- RwReal angle;
- RwV3d controlPoints[DEFAULTNUMCONTROLPOINTS];
-
- angleDelta = RDiv(RMul(CREAL(2.0), CREAL(M_PI)), INT2REAL(DEFAULTNUMCONTROLPOINTS));
- for (i = 0; i < DEFAULTNUMCONTROLPOINTS; i++)
- {
- angle = RMul(INT2REAL(i), angleDelta);
- controlPoints[i].x = RMul(DEFAULTSPLINERADIUS, FL2REAL(cos(REAL2FL(angle))));
- controlPoints[i].y = DEFAULTMINCONTROLPOINTHEIGHT;
- controlPoints[i].z = RMul(DEFAULTSPLINERADIUS, FL2REAL(sin(REAL2FL(angle))));
- }
-
- return RwCreateSpline(DEFAULTNUMCONTROLPOINTS, rwCLOSEDLOOP, &controlPoints[0]);
- }
-
- /**********************************************************************/
-
- /*
- * Rwad a spline from the given file.
- */
- static RwSpline *
- ReadCoasterSpline(FILE *file)
- {
- int numControlPoints;
- RwV3d *controlPoints;
- int i;
- double x;
- double y;
- double z;
- RwSpline *spline;
-
- if (fscanf(file, "%d", &numControlPoints) != 1)
- return NULL;
-
- controlPoints = (RwV3d*)malloc(sizeof(RwV3d) * numControlPoints);
- if (controlPoints == NULL)
- return NULL;
-
- for (i = 0; i < numControlPoints; i++)
- {
- if (fscanf(file, "%lf %lf %lf", &x, &y, &z) != 3)
- {
- free(controlPoints);
- return NULL;
- }
- controlPoints[i].x = FL2REAL(x);
- controlPoints[i].y = FL2REAL(y);
- controlPoints[i].z = FL2REAL(z);
- }
-
- spline = RwCreateSpline(numControlPoints, rwCLOSEDLOOP, controlPoints);
-
- free(controlPoints);
-
- return spline;
- }
-
- /**********************************************************************/
-
- /*
- * Convert the control points of the rollercoaster's spline into clumps
- * in coaster's scene.
- */
- static BOOL
- CreateCoasterControlPointClumps(RollerCoasterType *coaster)
- {
- RwClump *prototypeClump;
- int numControlPoints;
- int i;
- RwClump *clump;
- RwV3d point;
-
- RwModelBegin();
- RwClumpBegin();
- RwSetTag(CONTROLPOINTTAG);
- RwSetSurface(CREAL(0.75), CREAL(0.4), CREAL(0.0));
- RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(1.0));
- RwSetSurfaceLightSampling(rwVERTEX);
- RwSetSurfaceGeometrySampling(rwSOLID);
- RwSetSurfaceTexture(NULL);
-
- RwCone(CREAL(0.1), CREAL(0.05), 6);
- RwDisc(CREAL(0.0), CREAL(-0.05), 6);
- RwClumpEnd(&prototypeClump);
- RwModelEnd();
-
- numControlPoints = (int)RwGetSplineNumPoints(coaster->spline);
- for (i = 0; i < numControlPoints; i++)
- {
- clump = RwDuplicateClump(prototypeClump);
- if (clump == NULL)
- {
- RwDestroyClump(prototypeClump);
- return FALSE;
- }
- RwSetClumpData(clump, (void *)(i + 1));
- RwGetSplinePoint(coaster->spline, i + 1, &point);
- RwPushScratchMatrix();
- RwTranslateMatrix(RwScratchMatrix(), point.x, point.y, point.z, rwREPLACE);
- RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
-
- coaster->controlPointClumps[i] = clump;
-
- RwAddClumpToScene(coaster->scene, clump);
- }
-
- RwDestroyClump(prototypeClump);
-
- return TRUE;
- }
-
- /**********************************************************************/
-
- /*
- * Create the clump representing the roller coaster itself. Note this
- * builds a clump from the given coaster's spline but does not destroy
- * the coaster's existing clump (if any) or add the new clump to the
- * coater's scene.
- */
- static RwClump *
- CreateCoasterClump(RollerCoasterType *coaster)
- {
- RwReal delta;
- RwV3d vector;
- RwV3d point;
- RwV3d tangent;
- RwV3d nextPoint;
- RwV3d nextTangent;
- RwV3d right;
- int i;
- int j;
- RwReal t;
- RwClump *clump;
- RwUV uv;
-
- delta = RDiv(CREAL(1.0), INT2REAL(DEFAULTNUMSPLINESAMPLES));
-
- RwModelBegin();
- RwClumpBegin();
- RwSetTag(TRACKTAG);
- RwSetHints(rwHS | rwEDITABLE);
- for (i = 0; i < DEFAULTNUMSPLINESAMPLES; i++)
- {
- t = RMul(delta, INT2REAL(i + 1));
- RwSplinePoint(coaster->spline, rwSMOOTH, t, &point, &tangent);
- if (point.y < DEFAULTGROUNDLEVEL)
- point.y = DEFAULTGROUNDLEVEL;
- t = RMul(delta, INT2REAL(i + 2));
- RwSplinePoint(coaster->spline, rwSMOOTH, t, &nextPoint, &nextTangent);
- if (nextPoint.y < DEFAULTGROUNDLEVEL)
- nextPoint.y = DEFAULTGROUNDLEVEL;
- vector.x = RSub(nextPoint.x, point.x);
- vector.y = RSub(nextPoint.y, point.y);
- vector.z = RSub(nextPoint.z, point.z);
- RwNormalize(&vector);
- tangent.x = CREAL(0.0);
- tangent.y = CREAL(1.0);
- tangent.z = CREAL(0.0);
- RwCrossProduct(&vector, &tangent, &right);
- RwNormalize(&right);
- RwScaleVector(&right, CREAL(0.05), &right);
-
- if (i & 1)
- uv.v = CREAL(1.0);
- else
- uv.v = CREAL(0.0);
- uv.u = CREAL(0.0);
- RwVertexExt(RSub(point.x, right.x),
- RSub(point.y, right.y),
- RSub(point.z, right.z), &uv, NULL);
- uv.u = CREAL(1.0);
- RwVertexExt(RAdd(point.x, right.x),
- RAdd(point.y, right.y),
- RAdd(point.z, right.z), &uv, NULL);
- RwVertex(RSub(point.x, right.x),
- CREAL(0.0),
- RSub(point.z, right.z));
- RwVertex(RAdd(point.x, right.x),
- CREAL(0.0),
- RAdd(point.z, right.z));
- }
-
- for (i = 0; i < DEFAULTNUMSPLINESAMPLES; i++)
- {
- j = (((i + 1) == DEFAULTNUMSPLINESAMPLES) ? 0 : i + 1);
-
- /*
- * Add the polygon representing the track surface.
- */
- RwPushCurrentMaterial();
- RwSetSurfaceGeometrySampling(rwSOLID);
- RwSetSurfaceOpacity(CREAL(1.0));
- RwSetSurface(CREAL(0.5), CREAL(0.4), CREAL(0.0));
- RwSetSurfaceTextureModes(rwFORESHORTEN);
- RwSetSurfaceTexture("track1");
- RwQuadExt((i * 4) + 1, (i * 4) + 2, (j * 4) + 2, (j * 4) + 1, TRACKPOLYGONTAG);
- RwPopCurrentMaterial();
-
- /*
- * Add the polygons representing the sides of the track.
- */
- RwPushCurrentMaterial();
- RwSetSurfaceGeometrySampling(rwSOLID);
- RwSetSurfaceOpacity(CREAL(1.0));
- RwSetSurface(CREAL(0.5), CREAL(0.5), CREAL(0.0));
- if (i & 1)
- RwSetSurfaceColor(CREAL(1.0), CREAL(0.0), CREAL(0.0));
- else
- RwSetSurfaceColor(CREAL(1.0), CREAL(1.0), CREAL(1.0));
- RwSetSurfaceTexture(NULL);
- RwQuad((i * 4) + 4, (j * 4) + 4, (j * 4) + 2, (i * 4) + 2);
- RwQuad((i * 4) + 3, (i * 4) + 1, (j * 4) + 1, (j * 4) + 3);
- RwPopCurrentMaterial();
- }
- RwClumpEnd(&clump);
- RwModelEnd();
-
- return clump;
- }
-
- /**********************************************************************/
-
- /*
- * Create the rollercoaster's ground plane.
- */
- static RwClump *
- CreateCoasterGroundPlaneClump(RollerCoasterType *coaster)
- {
- RwClump *clump;
- RwUV uv;
-
- RwModelBegin();
- RwClumpBegin();
- RwSetTag(GROUNDPLANETAG);
- RwSetHints(rwCONTAINER);
- uv.u = CREAL(0.0);
- uv.v = CREAL(0.0);
- RwVertexExt(CREAL(-6.0), CREAL(-0.02), CREAL(6.0), &uv, NULL);
- uv.u = CREAL(32.0);
- uv.v = CREAL(0.0);
- RwVertexExt(CREAL( 6.0), CREAL(-0.02), CREAL(6.0), &uv, NULL);
- uv.u = CREAL(32.0);
- uv.v = CREAL(32.0);
- RwVertexExt(CREAL( 6.0), CREAL(-0.02), CREAL(-6.0), &uv, NULL);
- uv.u = CREAL(0.0);
- uv.v = CREAL(32.0);
- RwVertexExt(CREAL(-6.0), CREAL(-0.02), CREAL(-6.0), &uv, NULL);
-
- RwSetSurfaceTextureModes(rwFORESHORTEN);
- RwSetSurfaceTexture("rcgrass");
- RwQuadExt(1, 2, 3, 4, GROUNDPOLYGONTAG);
- RwClumpEnd(&clump);
- RwModelEnd();
-
- return clump;
- }
-
- /**********************************************************************/
-
- RollerCoasterType *
- CreateRollerCoaster(void)
- {
- RollerCoasterType *coaster;
-
- coaster = (RollerCoasterType *)malloc(sizeof(RollerCoasterType));
- if (coaster != NULL)
- {
- /*
- * Create the scene for this coaster.
- */
- coaster->scene = RwCreateScene();
- if (coaster->scene == NULL)
- {
- return NULL;
- }
-
- /*
- * Create the holding scene.
- */
- coaster->holdingScene = RwCreateScene();
- if (coaster->holdingScene == NULL)
- {
- RwDestroyScene(coaster->scene);
- return NULL;
- }
-
- /*
- * Create the light for this coaster.
- */
- coaster->light = RwCreateLight(rwDIRECTIONAL,
- CREAL(-1.0), CREAL(-1.0), CREAL(-1.0),
- CREAL(1.0));
- if (coaster->light == NULL)
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroyScene(coaster->scene);
- return NULL;
- }
- RwAddLightToScene(coaster->scene, coaster->light);
-
- /*
- * Create a default spline.
- */
- coaster->spline = CreateCoasterDefaultSpline();
- if (coaster->spline == NULL)
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroyScene(coaster->scene);
- return NULL;
- }
-
- /*
- * Create the clumps representing the control points
- * of the spline.
- */
- if (!CreateCoasterControlPointClumps(coaster))
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroyScene(coaster->scene);
- RwDestroySpline(coaster->spline);
- return NULL;
- }
-
- /*
- * Convert the spline description into a coaster clump.
- */
- coaster->coasterClump = CreateCoasterClump(coaster);
- if (coaster->coasterClump == NULL)
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroyScene(coaster->scene);
- RwDestroySpline(coaster->spline);
- return NULL;
- }
- RwAddClumpToScene(coaster->scene, coaster->coasterClump);
-
- /*
- * Create the coaster's ground plane.
- */
- coaster->groundPlaneClump = CreateCoasterGroundPlaneClump(coaster);
- if (coaster->groundPlaneClump == NULL)
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroyScene(coaster->scene);
- RwDestroySpline(coaster->spline);
- return NULL;
- }
- RwAddClumpToScene(coaster->scene, coaster->groundPlaneClump);
-
- /*
- * Create the car clump. If it fails we just ignore it and
- * continue on regardless.
- */
- coaster->carClump = RwReadShape("car.rwx");
- if (coaster->carClump != NULL)
- {
- RwSetClumpTag(coaster->carClump, CARTAG);
- RwSetClumpState(coaster->carClump, rwON);
- RwAddClumpToScene(coaster->scene, coaster->carClump);
- }
-
- /*
- * Initialize the default elevation and plan positions.
- */
- coaster->elevationPosition.x = CREAL( 0.0);
- coaster->elevationPosition.y = CREAL( 0.1);
- coaster->elevationPosition.z = CREAL(-1.5);
-
- coaster->planPosition.x = CREAL( 0.0);
- coaster->planPosition.y = CREAL( 2.0);
- coaster->planPosition.z = CREAL( 0.0);
-
- /*
- * Initialize the spline parameter and spline parameter delta.
- */
- coaster->t = CREAL(0.0);
- coaster->tDelta = CREAL(0.01);
-
- /*
- * Initialize the name and description.
- */
- coaster->filename[0] = '\0';
- strcpy(coaster->description, DEFAULTCOASTERDESCRIPTION);
-
- return coaster;
- }
- else
- {
- return NULL;
- }
- }
-
- /**********************************************************************/
-
- RollerCoasterType *
- ReadRollerCoaster(char *filename)
- {
- FILE *file;
- int len;
-
- RollerCoasterType *coaster;
-
- file = fopen(filename, "r");
- if (file == NULL)
- return NULL;
-
- coaster = (RollerCoasterType *)malloc(sizeof(RollerCoasterType));
- if (coaster == NULL)
- {
- fclose(file);
- return NULL;
- }
-
- /*
- * Read the description of the rollercoaster.
- */
- fgets(coaster->description, sizeof(coaster->description), file);
- len = strlen(coaster->description);
- if ((len > 0) && (coaster->description[len - 1] == '\n'))
- coaster->description[len - 1] = '\0';
-
- /*
- * Create the scene for this coaster.
- */
- coaster->scene = RwCreateScene();
- if (coaster->scene == NULL)
- {
- free(coaster);
- fclose(file);
- return NULL;
- }
-
- /*
- * Create the holding scene for this coaster.
- */
- coaster->holdingScene = RwCreateScene();
- if (coaster->holdingScene == NULL)
- {
- RwDestroyScene(coaster->scene);
- free(coaster);
- fclose(file);
- return NULL;
- }
-
- /*
- * Create the light for this coaster.
- */
- coaster->light = RwCreateLight(rwDIRECTIONAL,
- CREAL(-1.0), CREAL(-1.0), CREAL(-1.0),
- CREAL(1.0));
- if (coaster->light == NULL)
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroyScene(coaster->scene);
- free(coaster);
- fclose(file);
- return NULL;
- }
- RwAddLightToScene(coaster->scene, coaster->light);
-
- /*
- * Create a default spline.
- */
- coaster->spline = ReadCoasterSpline(file);
- if (coaster->spline == NULL)
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroyScene(coaster->scene);
- free(coaster);
- fclose(file);
- return NULL;
- }
-
- /*
- * Create the clumps representing the control points
- * of the spline.
- */
- if (!CreateCoasterControlPointClumps(coaster))
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroySpline(coaster->spline);
- RwDestroyScene(coaster->scene);
- free(coaster);
- fclose(file);
- return NULL;
- }
-
- /*
- * Convert the spline description into a coaster clump.
- */
- coaster->coasterClump = CreateCoasterClump(coaster);
- if (coaster->coasterClump == NULL)
- {
- RwDestroyScene(coaster->holdingScene);
- RwDestroySpline(coaster->spline);
- RwDestroyScene(coaster->scene);
- free(coaster);
- fclose(file);
- return NULL;
- }
- RwAddClumpToScene(coaster->scene, coaster->coasterClump);
-
- /*
- * Create the coaster's ground plane.
- */
- coaster->groundPlaneClump = CreateCoasterGroundPlaneClump(coaster);
- if (coaster->groundPlaneClump == NULL)
- {
- RwDestroySpline(coaster->spline);
- RwDestroyScene(coaster->holdingScene);
- RwDestroyScene(coaster->scene);
- free(coaster);
- fclose(file);
- return NULL;
- }
- RwAddClumpToScene(coaster->scene, coaster->groundPlaneClump);
-
- /*
- * Create the car clump. If it fails we just ignore it and
- * continue on regardless.
- */
- coaster->carClump = RwReadShape("car.rwx");
- if (coaster->carClump != NULL)
- {
- RwSetClumpTag(coaster->carClump, CARTAG);
- RwSetClumpState(coaster->carClump, rwON);
- RwAddClumpToScene(coaster->scene, coaster->carClump);
- }
-
- /*
- * Initialize the default elevation and plan positions.
- */
- coaster->elevationPosition.x = CREAL( 0.0);
- coaster->elevationPosition.y = CREAL( 0.1);
- coaster->elevationPosition.z = CREAL(-1.5);
-
- coaster->planPosition.x = CREAL( 0.0);
- coaster->planPosition.y = CREAL( 2.0);
- coaster->planPosition.z = CREAL( 0.0);
-
- /*
- * Initialize the spline parameter and spline parameter delta.
- */
- coaster->t = CREAL(0.0);
- coaster->tDelta = DEFAULTSPLINEDELTA;
-
- /*
- * Save the filename.
- */
- strcpy(coaster->filename, filename);
-
- fclose(file);
-
- return coaster;
- }
-
- /**********************************************************************/
-
- void
- DestroyRollerCoaster(RollerCoasterType *coaster)
- {
- if (coaster != NULL)
- {
- if (coaster->scene != NULL)
- RwDestroyScene(coaster->scene);
- if (coaster->holdingScene != NULL)
- RwDestroyScene(coaster->holdingScene);
- if (coaster->spline != NULL)
- RwDestroySpline(coaster->spline);
- free(coaster);
- }
- }
-
- /**********************************************************************/
-
- BOOL
- WriteRollerCoaster(RollerCoasterType *coaster, char *filename)
- {
- int i;
- int numControlPoints;
- RwV3d point;
- FILE *file;
-
- file = fopen(filename, "w");
- if (file == NULL)
- return FALSE;
-
- /*
- * Write the coaster description.
- */
- fputs(coaster->description, file);
- fputc('\n', file);
-
- numControlPoints = (int)RwGetSplineNumPoints(coaster->spline);
- fprintf(file, "%d\n", numControlPoints);
-
- for (i = 0; i < numControlPoints; i++)
- {
- RwGetSplinePoint(coaster->spline, i + 1, &point);
- fprintf(file, "%lf %lf %lf\n", REAL2FL(point.x), REAL2FL(point.y), REAL2FL(point.z));
- }
-
- /*
- * Store the filename.
- */
- strcpy(coaster->filename, filename);
-
- fclose(file);
-
- return TRUE;
- }
-
- /**********************************************************************/
-
- static RwClump *
- ShowControlPoint(RwClump *clump, RollerCoasterType *coaster)
- {
- if (RwGetClumpTag(clump) == CONTROLPOINTTAG)
- {
- RwAddClumpToScene(coaster->scene, clump);
- RwSetClumpState(clump, rwON);
- }
- return clump;
- }
-
- /**********************************************************************/
-
- static RwClump *
- HideControlPoint(RwClump *clump, RollerCoasterType *coaster)
- {
- if (RwGetClumpTag(clump) == CONTROLPOINTTAG)
- {
- RwAddClumpToScene(coaster->holdingScene, clump);
- RwSetClumpState(clump, rwOFF);
- }
- return clump;
- }
-
- /**********************************************************************/
-
- void
- SwitchToCoasterRideMode(RollerCoasterType *coaster)
- {
- DisableCoasterControlPoints(coaster);
-
- /*
- * Ensure the coaster itself is fully opaque.
- */
- RwForAllPolygonsInClumpReal(coaster->coasterClump,
- RwSetPolygonOpacity, CREAL(1.0));
- }
-
- /**********************************************************************/
-
- void
- SwitchToCoasterEditMode(RollerCoasterType *coaster)
- {
- EnableCoasterControlPoints(coaster);
-
- /*
- * Make the coaster semi-transparent so we can see the control points more
- * easily.
- */
- RwForAllPolygonsInClumpReal(coaster->coasterClump,
- RwSetPolygonOpacity, CREAL(0.75));
- }
-
- /**********************************************************************/
-
- /*
- * The function tests whether a control point has been picked or not.
- * It does a conventional pick and then examines the clump picked (if
- * any) to see if it is a control point clump. If it is a control
- * point clump then the index of that control point is returned,
- * otherwise, 0 is returned.
- */
- int
- IsCoasterControlPointPicked(RollerCoasterType *coaster, RwCamera *camera, int x, int y)
- {
- RwPickRecord pick;
-
- if (RwPickScene(coaster->scene, x, y, camera, &pick))
- {
- if (pick.type == rwPICKCLUMP)
- {
- if (RwGetClumpTag(pick.object.clump.clump) == CONTROLPOINTTAG)
- {
- return (int)RwGetClumpData(pick.object.clump.clump);
- }
- else
- {
- return FALSE;
- }
- }
- else
- {
- return FALSE;
- }
- }
- else
- {
- return FALSE;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Transform the given spline control point of the given rollercoaster.
- * Note, this function does not rebuild the coaster's clump. That is
- * delayed until UpdateCoasterClump() is called.
- */
- void
- TransformCoasterControlPoint(RollerCoasterType *coaster, int index, RwMatrix4d *matrix)
- {
- RwClump *clump;
- RwV3d origin;
-
- clump = coaster->controlPointClumps[index - 1];
-
- RwTransformClump(clump, matrix, rwREPLACE);
- RwGetClumpOrigin(clump, &origin);
- if (origin.y < DEFAULTMINCONTROLPOINTHEIGHT)
- {
- RwPushScratchMatrix();
- RwTranslateMatrix(RwScratchMatrix(),
- CREAL(0.0), RSub(DEFAULTMINCONTROLPOINTHEIGHT, origin.y), CREAL(0.0),
- rwREPLACE);
- RwTransformClump(clump, RwScratchMatrix(), rwPOSTCONCAT);
- RwPopScratchMatrix();
- origin.y = DEFAULTMINCONTROLPOINTHEIGHT;
- }
- else if (origin.y > DEFAULTMAXCONTROLPOINTHEIGHT)
- {
- RwPushScratchMatrix();
- RwTranslateMatrix(RwScratchMatrix(),
- CREAL(0.0), RSub(DEFAULTMAXCONTROLPOINTHEIGHT, origin.y), CREAL(0.0),
- rwREPLACE);
- RwTransformClump(clump, RwScratchMatrix(), rwPOSTCONCAT);
- RwPopScratchMatrix();
- origin.y = DEFAULTMAXCONTROLPOINTHEIGHT;
- }
- RwSetSplinePoint(coaster->spline, index, &origin);
- }
-
- /**********************************************************************/
-
- /*
- * Update the coaster's clump from the coaster's spline.
- */
- BOOL
- UpdateCoasterClump(RollerCoasterType *coaster)
- {
- RwClump *clump;
-
- clump = CreateCoasterClump(coaster);
- if (clump != NULL)
- {
- RwDestroyClump(coaster->coasterClump);
- coaster->coasterClump = clump;
- RwAddClumpToScene(coaster->scene, clump);
- RwForAllPolygonsInClumpReal(coaster->coasterClump, RwSetPolygonOpacity, CREAL(0.75));
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
-
- /**********************************************************************/
-
- void
- UpdateViewParameters(RollerCoasterType *coaster)
- {
- RwV3d vector;
- RwReal elements[4][4];
-
- /*
- * Get the spline transform. We derive the position and
- * orientation of both car and camera from the resulting
- * matrix.
- */
- vector.x = CREAL(0.0);
- vector.y = CREAL(1.0);
- vector.z = CREAL(0.0);
- RwPushScratchMatrix();
- RwSplineTransform(coaster->spline, rwSMOOTH, coaster->t, &vector, RwScratchMatrix());
- RwGetMatrixElements(RwScratchMatrix(), elements);
- RwPopScratchMatrix();
-
- /*
- * Compute the true look-up.
- */
- coaster->tUp.x = CREAL(0.0);
- coaster->tUp.y = CREAL(1.0);
- coaster->tUp.z = CREAL(0.0);
- coaster->tAt.x = elements[2][0];
- coaster->tAt.y = elements[2][1];
- coaster->tAt.z = elements[2][2];
- RwCrossProduct(&coaster->tAt, &coaster->tUp, &coaster->tRight);
- RwNormalize(&coaster->tRight);
- RwCrossProduct(&coaster->tRight, &coaster->tAt, &coaster->tUp);
- RwNormalize(&coaster->tUp);
-
- /*
- * Get the position.
- */
- coaster->tPosition.x = elements[3][0];
- coaster->tPosition.y = elements[3][1];
- coaster->tPosition.z = elements[3][2];
- if (coaster->tPosition.y < DEFAULTGROUNDLEVEL)
- coaster->tPosition.y = DEFAULTGROUNDLEVEL;
-
- /*
- * If the coaster has a car and the car is enabled, position the
- * car w.r.t. the viewing parameters.
- */
- if ((coaster->carClump != NULL) &&
- (RwGetClumpState(coaster->carClump) == rwON))
- {
- RwPushScratchMatrix();
- elements[0][0] = -coaster->tRight.x;
- elements[0][1] = -coaster->tRight.y;
- elements[0][2] = -coaster->tRight.z;
- elements[0][3] = CREAL(0.0);
- elements[1][0] = coaster->tUp.x;
- elements[1][1] = coaster->tUp.y;
- elements[1][2] = coaster->tUp.z;
- elements[1][3] = CREAL(0.0);
- elements[2][0] = coaster->tAt.x;
- elements[2][1] = coaster->tAt.y;
- elements[2][2] = coaster->tAt.z;
- elements[2][3] = CREAL(0.0);
- elements[3][0] = coaster->tPosition.x;
- elements[3][1] = coaster->tPosition.y;
- elements[3][2] = coaster->tPosition.z;
- elements[3][3] = CREAL(1.0);
- RwSetMatrixElements(RwScratchMatrix(), elements);
- RwTransformClump(coaster->carClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- }
- }
-
- /**********************************************************************/
-
- void
- TrackCameraToCoaster(RollerCoasterType *coaster, RwCamera *camera)
- {
- RwReal x;
- RwReal y;
- RwReal z;
-
- RwSetCameraLookUp(camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
- RwSetCameraLookAt(camera, coaster->tAt.x, coaster->tAt.y, coaster->tAt.z);
-
- x = RAdd(coaster->tPosition.x, RMul(coaster->tUp.x, CREAL(0.1)));
- y = RAdd(coaster->tPosition.y, RMul(coaster->tUp.y, CREAL(0.1)));
- z = RAdd(coaster->tPosition.z, RMul(coaster->tUp.z, CREAL(0.1)));
- RwSetCameraPosition(camera, x, y, z);
- }
-
- /**********************************************************************/
-
- void
- UpdateCoasterVelocity(RollerCoasterType *coaster)
- {
- if (coaster->tAt.y < CREAL(-0.0025))
- {
- /*
- * Falling...
- */
- coaster->tDelta = RAdd(coaster->tDelta, SPLINEDELTAACCELERATION);
- if (coaster->tDelta > MAXSPLINEDELTA)
- coaster->tDelta = MAXSPLINEDELTA;
- }
- else if (coaster->tAt.y > CREAL(0.0025))
- {
- /*
- * Climbing...
- */
- coaster->tDelta = RSub(coaster->tDelta, SPLINEDELTADECCELERATION);
- if (coaster->tDelta < MINSPLINEDELTA)
- coaster->tDelta = MINSPLINEDELTA;
- }
- else
- {
- /*
- * Level motion...
- */
- if (coaster->tDelta > DEFAULTSPLINEDELTA)
- {
- coaster->tDelta = RSub(coaster->tDelta, SPLINEDELTADECCELERATION);
- if (coaster->tDelta < DEFAULTSPLINEDELTA)
- coaster->tDelta = DEFAULTSPLINEDELTA;
- }
- }
-
- /*
- * Advance the position based on the computed delta.
- */
- coaster->t = RAdd(coaster->t, coaster->tDelta);
-
- /*
- * Clump the delta to 0.0 => 1.0 (we could let the spline stuff do
- * this, but eventuallywe would wrap the real rep.).
- */
- if (coaster->t > CREAL(1.0))
- coaster->t = RSub(coaster->t, CREAL(1.0));
- }
-
- /**********************************************************************/
-
- void
- EnableCoasterCar(RollerCoasterType *coaster)
- {
- if (coaster->carClump != NULL)
- {
- RwAddClumpToScene(coaster->scene, coaster->carClump);
- RwSetClumpState(coaster->carClump, rwON);
- }
- }
-
- /**********************************************************************/
-
- void
- DisableCoasterCar(RollerCoasterType *coaster)
- {
- if (coaster->carClump != NULL)
- {
- RwAddClumpToScene(coaster->holdingScene, coaster->carClump);
- RwSetClumpState(coaster->carClump, rwOFF);
- }
- }
-
- /**********************************************************************/
-
- void
- EnableCoasterControlPoints(RollerCoasterType *coaster)
- {
- RwForAllClumpsInScenePointer(coaster->scene, (RwClumpFuncPointer)ShowControlPoint, coaster);
- RwForAllClumpsInScenePointer(coaster->holdingScene, (RwClumpFuncPointer)ShowControlPoint, coaster);
- }
-
- /**********************************************************************/
-
- void
- DisableCoasterControlPoints(RollerCoasterType *coaster)
- {
- RwForAllClumpsInScenePointer(coaster->holdingScene, (RwClumpFuncPointer)HideControlPoint, coaster);
- RwForAllClumpsInScenePointer(coaster->scene, (RwClumpFuncPointer)HideControlPoint, coaster);
- }
-
- /**********************************************************************/
-
- /**********************************************************************
- *
- * End of file.
- *
- **********************************************************************/
-