home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- *
- * File: spline.c
- *
- * Abstract: Spline related functions mostly taken from rwRoller. Some
- * changes were made relating to shape of control point geometry
- * and coaster clump.
- *
- * Author: Colin McCartney
- *
- * Date: 02/03/95
- *
- *********************************************************************/
-
- #include <windows.h>
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
-
- #include <rwlib.h>
- #include <rwwin.h>
-
- #include "rfview.h"
-
-
- /**********************************************************************
- *
- * Constants.
- *
- **********************************************************************/
-
- /*
- * Default description of the rollercoaster.
- */
- #define TRACKPOLYGONTAG 1
- #define GROUNDPOLYGONTAG 2
- #define rfOPAQUE 0.50
-
- #define CONTROLPOINTTAG 1
- #define GROUNDPLANETAG 2
- #define TRACKTAG 3
- #define CARTAG 4
-
- /**********************************************************************/
-
- /*
- * Read a spline from the given file.
- */
- 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.
- */
- BOOL
- CreateCoasterControlPointClumps(RollerCoasterType *coaster)
- {
- RwClump *prototypeClump;
- int numControlPoints;
- int i;
- RwClump *clump;
- RwV3d point;
- ClumpUserData *userData;
- /* Allocate the user data for the new clump. */
- userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
- if (userData == (ClumpUserData *)NULL) return FALSE;
-
- RwModelBegin();
- RwClumpBegin();
-
- RwSetTag(CONTROLPOINTTAG);
- RwSetSurface(CREAL(0.75), CREAL(0.4), CREAL(0.2));
- RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(1.0));
- RwSetSurfaceLightSampling(rwVERTEX);
- RwSetSurfaceGeometrySampling(rwSOLID);
- RwSetSurfaceTexture(NULL);
-
- RwSphere(CREAL(0.02), 6);
- RwClumpEnd(&prototypeClump);
- userData->light = NULL;
- userData->datatype = rfIsSpline;
- RwSetClumpData(prototypeClump, (void *)userData);
-
- 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)); // RF NO USER DATA SET ON SPLINE CONTROL POINTS
- 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(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.
- */
- 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;
- RwSplinePath path;
- ClumpUserData *userData;
-
- if(UseSmoothEnd) path=rwNICEENDS; else path=rwSMOOTH;
-
- /* Allocate the user data for the new clump. */
- userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
- if (userData == NULL) return NULL;
-
- 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, path, t, &point, &tangent);
- t = RMul(delta, INT2REAL(i + 2));
- RwSplinePoint(coaster->spline, path, t, &nextPoint, &nextTangent);
- 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.03), &right); // used to be 0.05
-
- RwVertex(RSub(point.x, right.x),
- RSub(point.y, right.y),RSub(point.z, right.z));
- RwVertex(RAdd(point.x, right.x),
- RAdd(point.y, right.y),RAdd(point.z, right.z));
- }
-
- RwPushCurrentMaterial();
- RwSetSurfaceGeometrySampling(rwSOLID);
- RwSetSurfaceOpacity(CREAL(1.0));
- RwSetSurface(CREAL(0.5), CREAL(0.4), CREAL(0.0));
- RwSetSurfaceTextureModes(rwFORESHORTEN);
- RwSetSurfaceColor(CREAL(0.0),CREAL(0.0),CREAL(0.0));
- RwSetSurfaceTextureModes((RwTextureModes)NULL);
- for (i = 0; i < DEFAULTNUMSPLINESAMPLES; i++)
- {
- j = (((i + 1) == DEFAULTNUMSPLINESAMPLES) ? 0 : i + 1);
-
- /*
- * Add the polygon representing the track surface.
- */
- RwQuadExt((i * 2) + 1, (i * 2) + 2, (j * 2) + 2, (j * 2) + 1, TRACKPOLYGONTAG); // A B C D
- RwQuadExt((i * 2) + 1, (j * 2) + 1, (j * 2) + 2, (i * 2) + 2, TRACKPOLYGONTAG); // try backside A D C B
- }
- RwPopCurrentMaterial();
- RwClumpEnd(&clump);
- userData->light = NULL;
- userData->datatype = rfIsSpline;
- RwSetClumpData(clump, (void *)userData);
- RwModelEnd();
-
- return clump;
- }
-
-
- /**********************************************************************/
- // read a spline from disk based on input filename
- 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 a default spline.
- */
- coaster->spline = ReadCoasterSpline(file);
- if (coaster->spline == NULL)
- {
- free(coaster);
- fclose(file);
- return NULL;
- }
-
- /*
- * Create the clumps representing the control points
- * of the spline.
- */
- if (!CreateCoasterControlPointClumps(coaster))
- {
- RwDestroySpline(coaster->spline);
- free(coaster);
- fclose(file);
- return NULL;
- }
-
- /*
- * Convert the spline description into a coaster clump.
- */
- coaster->coasterClump = CreateCoasterClump(coaster);
- if (coaster->coasterClump == NULL)
- {
- RwDestroySpline(coaster->spline);
- free(coaster);
- fclose(file);
- return NULL;
- }
- RwAddClumpToScene(Scene, coaster->coasterClump);
-
- /*
- * 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;
- }
-
- /**********************************************************************/
- // if there is a spline, destroy the spline
- void
- DestroyRollerCoaster(RollerCoasterType *coaster)
- {
- if (coaster != NULL)
- {
- if (coaster->spline != NULL)
- RwDestroySpline(coaster->spline);
- free(coaster);
- }
- }
-
-
- /**********************************************************************/
- // show the control points
- static RwClump *
- ShowControlPoint(RwClump *clump)
- {
- if (RwGetClumpTag(clump) == CONTROLPOINTTAG)
- {
- RwSetClumpState(clump, rwON);
- }
- return clump;
- }
-
- /**********************************************************************/
- // hide the control points
- static RwClump *
- HideControlPoint(RwClump *clump)
- {
- if (RwGetClumpTag(clump) == CONTROLPOINTTAG)
- {
- RwSetClumpState(clump, rwOFF);
- }
- return clump;
- }
-
- /**********************************************************************/
- // delete the spline track and control points
- static RwClump *
- DeleteCoasterAll(RwClump *clump)
- {
- RwInt32 tag;
- tag = RwGetClumpTag(clump);
- if ((tag == CONTROLPOINTTAG) || (tag == TRACKTAG) )
- {
- RwRemoveClumpFromScene(clump);
- }
- return clump;
- }
-
- /**********************************************************************/
- // show the track
- static RwClump *
- ShowTrack(RwClump *clump)
- {
- if (RwGetClumpTag(clump) == TRACKTAG)
- {
- RwSetClumpState(clump, rwON);
- }
- return clump;
- }
-
- /**********************************************************************/
- // hide the track
- static RwClump *
- HideTrack(RwClump *clump)
- {
- if (RwGetClumpTag(clump) == TRACKTAG)
- {
- RwSetClumpState(clump, rwOFF);
- }
- return clump;
- }
-
-
- /**********************************************************************/
- // position the selected object onto the spline at 0.0
- void
- PositionObjectOnSpline(RollerCoasterType *coaster,RwClump *object)
- {
- RwV3d vector;
-
- RwSplinePath path;
-
- #ifdef XXX
- RwReal elements[4][4];
- #endif
-
- if(UseSmoothEnd) path=rwNICEENDS; else path=rwSMOOTH;
-
- /*
- * 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);
- #ifdef XXX // use if necessary to align Y
-
- RwPushScratchMatrix();
- RwSplineTransform(coaster->spline, path, 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];
-
- 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(object, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- #endif
-
- #define YYY
- #ifdef YYY // use if not necessary to align Y
- RwPushScratchMatrix();
- RwSplineTransform(coaster->spline, path, coaster->t, &vector, RwScratchMatrix());
- RwTransformClump(object, RwScratchMatrix(), rwREPLACE); // used instead
- RwPopScratchMatrix();
- #endif
-
- }
-
- /**********************************************************************/
- // track the camera to the coaster
- 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);
- }
-
-
- /**********************************************************************/
- // show all coaster control points
- void
- EnableCoasterControlPoints(RollerCoasterType *coaster)
- {
- RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)ShowControlPoint, coaster);
- }
-
- /**********************************************************************/
- // hide all coaster control points
- void
- DisableCoasterControlPoints(RollerCoasterType *coaster)
- {
- RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)HideControlPoint, coaster);
- }
-
- /**********************************************************************/
- // delete all coaster control points and track
- void
- DeleteCoaster(RollerCoasterType *coaster)
- {
- RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)DeleteCoasterAll, coaster);
- }
-
-
- /**********************************************************************/
- // display all spine path
- void
- EnableCoasterTrack(RollerCoasterType *coaster)
- {
- RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)ShowTrack, coaster);
- }
-
- /**********************************************************************/
- // disable all spline path
- void
- DisableCoasterTrack(RollerCoasterType *coaster)
- {
- RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)HideTrack, coaster);
- }
-
-