home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwwin / spline.c_ / spline.bin
Text File  |  1995-11-14  |  16KB  |  540 lines

  1. /*********************************************************************
  2.  *
  3.  * File:     spline.c
  4.  *
  5.  * Abstract: Spline related functions mostly taken from rwRoller.  Some
  6.  *           changes were made relating to shape of control point geometry
  7.  *           and coaster clump.
  8.  *
  9.  * Author:   Colin McCartney
  10.  *
  11.  * Date:     02/03/95
  12.  *
  13.  *********************************************************************/
  14.                     
  15. #include <windows.h>
  16.  
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <math.h>
  20. #include <string.h>
  21.  
  22. #include <rwlib.h>
  23. #include <rwwin.h>
  24.  
  25. #include "rfview.h"
  26.  
  27.  
  28. /**********************************************************************
  29.  *
  30.  * Constants.
  31.  *
  32.  **********************************************************************/
  33.  
  34. /*
  35.  * Default description of the rollercoaster.
  36.  */
  37. #define TRACKPOLYGONTAG           1
  38. #define GROUNDPOLYGONTAG          2
  39. #define rfOPAQUE                  0.50
  40.  
  41. #define CONTROLPOINTTAG           1
  42. #define GROUNDPLANETAG            2
  43. #define TRACKTAG                  3
  44. #define CARTAG                    4
  45.  
  46. /**********************************************************************/
  47.  
  48. /*
  49.  * Read a spline from the given file.
  50.  */
  51. RwSpline *
  52. ReadCoasterSpline(FILE *file)
  53. {
  54.     int       numControlPoints;
  55.     RwV3d    *controlPoints;
  56.     int       i;
  57.     double    x;
  58.     double    y;
  59.     double    z;
  60.     RwSpline *spline;
  61.  
  62.     if (fscanf(file, "%d", &numControlPoints) != 1)
  63.         return NULL;
  64.  
  65.     controlPoints = (RwV3d*)malloc(sizeof(RwV3d) * numControlPoints);
  66.     if (controlPoints == NULL)
  67.         return NULL;
  68.             
  69.     for (i = 0; i < numControlPoints; i++)
  70.     {
  71.         if (fscanf(file, "%lf %lf %lf", &x, &y, &z) != 3)
  72.         {
  73.             free(controlPoints);
  74.             return NULL;
  75.         }
  76.         controlPoints[i].x = FL2REAL(x);
  77.         controlPoints[i].y = FL2REAL(y);
  78.         controlPoints[i].z = FL2REAL(z);
  79.     }
  80.     
  81.     spline = RwCreateSpline(numControlPoints, rwCLOSEDLOOP, controlPoints);
  82.     
  83.     free(controlPoints);
  84.     
  85.     return spline;
  86. }
  87.  
  88. /**********************************************************************/
  89. /*
  90.  * Convert the control points of the rollercoaster's spline into clumps
  91.  * in coaster's scene.
  92.  */
  93. BOOL
  94. CreateCoasterControlPointClumps(RollerCoasterType *coaster)
  95. {
  96.     RwClump *prototypeClump;
  97.     int      numControlPoints;
  98.     int      i;
  99.     RwClump *clump;
  100.     RwV3d    point;
  101.     ClumpUserData *userData;
  102.     /* Allocate the user data for the new clump. */
  103.     userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
  104.     if (userData == (ClumpUserData *)NULL) return FALSE;
  105.     
  106.     RwModelBegin();
  107.         RwClumpBegin();
  108.  
  109.             RwSetTag(CONTROLPOINTTAG);
  110.             RwSetSurface(CREAL(0.75), CREAL(0.4), CREAL(0.2));
  111.             RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(1.0));
  112.             RwSetSurfaceLightSampling(rwVERTEX);
  113.             RwSetSurfaceGeometrySampling(rwSOLID);
  114.             RwSetSurfaceTexture(NULL);        
  115.  
  116.             RwSphere(CREAL(0.02), 6);
  117.         RwClumpEnd(&prototypeClump);
  118.         userData->light = NULL;
  119.         userData->datatype = rfIsSpline;
  120.         RwSetClumpData(prototypeClump, (void *)userData);
  121.   
  122.     RwModelEnd();
  123.  
  124.     numControlPoints = (int)RwGetSplineNumPoints(coaster->spline);
  125.     for (i = 0; i < numControlPoints; i++)
  126.     {
  127.         clump = RwDuplicateClump(prototypeClump);
  128.         if (clump == NULL)
  129.         {
  130.             RwDestroyClump(prototypeClump);
  131.             return FALSE;
  132.         }
  133.         //RwSetClumpData(clump, (void *)(i + 1));        // RF  NO USER DATA SET ON SPLINE CONTROL POINTS
  134.         RwGetSplinePoint(coaster->spline, i + 1, &point);
  135.         RwPushScratchMatrix();
  136.             RwTranslateMatrix(RwScratchMatrix(), point.x, point.y, point.z, rwREPLACE);
  137.             RwTransformClump(clump, RwScratchMatrix(), rwREPLACE);
  138.         RwPopScratchMatrix();
  139.         
  140.         coaster->controlPointClumps[i] = clump;
  141.  
  142.         RwAddClumpToScene(Scene, clump);
  143.     }
  144.  
  145.     RwDestroyClump(prototypeClump);
  146.  
  147.     return TRUE;
  148. }
  149.  
  150. /**********************************************************************/
  151. /*
  152.  * Create the clump representing the roller coaster itself. Note this
  153.  * builds a clump from the given coaster's spline but does not destroy
  154.  * the coaster's existing clump (if any) or add the new clump to the
  155.  * coater's scene.
  156.  */
  157. RwClump *
  158. CreateCoasterClump(RollerCoasterType *coaster)
  159. {
  160.     RwReal   delta;
  161.     RwV3d    vector;
  162.     RwV3d    point;
  163.     RwV3d    tangent;
  164.     RwV3d    nextPoint;
  165.     RwV3d    nextTangent;
  166.     RwV3d    right;
  167.     int      i;
  168.     int      j;
  169.     RwReal   t;
  170.     RwClump *clump;
  171.     RwSplinePath path;
  172.     ClumpUserData *userData;
  173.     
  174.     if(UseSmoothEnd) path=rwNICEENDS; else   path=rwSMOOTH;
  175.            
  176.     /* Allocate the user data for the new clump. */
  177.     userData = (ClumpUserData *)malloc(sizeof(ClumpUserData));
  178.     if (userData == NULL) return NULL;
  179.             
  180.     delta = RDiv(CREAL(1.0), INT2REAL(DEFAULTNUMSPLINESAMPLES));
  181.  
  182.     RwModelBegin();
  183.         RwClumpBegin();
  184.             RwSetTag(TRACKTAG);
  185.             RwSetHints(rwHS | rwEDITABLE);
  186.             for (i = 0; i < DEFAULTNUMSPLINESAMPLES; i++)
  187.             {
  188.                 t = RMul(delta, INT2REAL(i + 1));
  189.                 RwSplinePoint(coaster->spline, path, t, &point, &tangent);
  190.                 t = RMul(delta, INT2REAL(i + 2));
  191.                 RwSplinePoint(coaster->spline, path, t, &nextPoint, &nextTangent);
  192.                 vector.x = RSub(nextPoint.x, point.x);
  193.                 vector.y = RSub(nextPoint.y, point.y);
  194.                 vector.z = RSub(nextPoint.z, point.z);
  195.                 RwNormalize(&vector);
  196.                 tangent.x = CREAL(0.0);
  197.                 tangent.y = CREAL(1.0);
  198.                 tangent.z = CREAL(0.0);
  199.                 RwCrossProduct(&vector, &tangent, &right);
  200.                 RwNormalize(&right);
  201.                 RwScaleVector(&right, CREAL(0.03), &right);       // used to be 0.05
  202.               
  203.                 RwVertex(RSub(point.x, right.x),
  204.                      RSub(point.y, right.y),RSub(point.z, right.z));
  205.                 RwVertex(RAdd(point.x, right.x),
  206.                      RAdd(point.y, right.y),RAdd(point.z, right.z));
  207.              }
  208.  
  209.           RwPushCurrentMaterial();
  210.            RwSetSurfaceGeometrySampling(rwSOLID);
  211.            RwSetSurfaceOpacity(CREAL(1.0));
  212.            RwSetSurface(CREAL(0.5), CREAL(0.4), CREAL(0.0));
  213.            RwSetSurfaceTextureModes(rwFORESHORTEN);
  214.            RwSetSurfaceColor(CREAL(0.0),CREAL(0.0),CREAL(0.0));
  215.            RwSetSurfaceTextureModes((RwTextureModes)NULL);
  216.            for (i = 0; i < DEFAULTNUMSPLINESAMPLES; i++)
  217.             {
  218.                j = (((i + 1) == DEFAULTNUMSPLINESAMPLES) ? 0 : i + 1);
  219.                 
  220.                 /*
  221.                  * Add the polygon representing the track surface.
  222.                  */
  223.                RwQuadExt((i * 2) + 1, (i * 2) + 2, (j * 2) + 2, (j * 2) + 1, TRACKPOLYGONTAG);  // A B C D
  224.                RwQuadExt((i * 2) + 1, (j * 2) + 1, (j * 2) + 2, (i * 2) + 2, TRACKPOLYGONTAG);  // try backside A D C B
  225.              }
  226.         RwPopCurrentMaterial();
  227.         RwClumpEnd(&clump);
  228.         userData->light = NULL;
  229.         userData->datatype = rfIsSpline;        
  230.         RwSetClumpData(clump, (void *)userData);
  231.     RwModelEnd();
  232.  
  233.     return clump;
  234. }
  235.  
  236.  
  237. /**********************************************************************/
  238. // read a spline from disk based on input filename
  239. RollerCoasterType *
  240. ReadRollerCoaster(char *filename)
  241. {
  242.     FILE *file;
  243.     int   len;
  244.  
  245.     RollerCoasterType *coaster;
  246.     
  247.     file = fopen(filename, "r");
  248.     if (file == NULL)
  249.         return NULL;
  250.  
  251.     coaster = (RollerCoasterType *)malloc(sizeof(RollerCoasterType));
  252.     if (coaster == NULL)
  253.     {
  254.         fclose(file);
  255.         return NULL;
  256.     }
  257.     
  258.     /*
  259.      * Read the description of the rollercoaster.
  260.      */
  261.     fgets(coaster->description, sizeof(coaster->description), file);
  262.     len = strlen(coaster->description);
  263.     if ((len > 0) && (coaster->description[len - 1] == '\n'))
  264.         coaster->description[len - 1] = '\0';
  265.     
  266.  
  267.     /*
  268.      * Create a default spline.
  269.      */
  270.     coaster->spline = ReadCoasterSpline(file);
  271.     if (coaster->spline == NULL)
  272.     {
  273.         free(coaster);
  274.         fclose(file);
  275.         return NULL;
  276.     }
  277.             
  278.     /*
  279.      * Create the clumps representing the control points
  280.      * of the spline.
  281.      */
  282.     if (!CreateCoasterControlPointClumps(coaster))
  283.     {
  284.         RwDestroySpline(coaster->spline);
  285.         free(coaster);
  286.         fclose(file);
  287.         return NULL;
  288.     }
  289.         
  290.     /*
  291.      * Convert the spline description into a coaster clump.
  292.      */
  293.     coaster->coasterClump = CreateCoasterClump(coaster);
  294.     if (coaster->coasterClump == NULL)
  295.     {
  296.         RwDestroySpline(coaster->spline);
  297.         free(coaster);
  298.         fclose(file);
  299.         return NULL;
  300.     }
  301.     RwAddClumpToScene(Scene, coaster->coasterClump);
  302.         
  303.     /*
  304.      * Initialize the spline parameter and spline parameter delta.
  305.      */
  306.     coaster->t      = CREAL(0.0);
  307.     coaster->tDelta = DEFAULTSPLINEDELTA;
  308.         
  309.     /*
  310.      * Save the filename.
  311.      */
  312.     strcpy(coaster->filename, filename);
  313.     
  314.     fclose(file);
  315.  
  316.     return coaster;
  317. }
  318.  
  319. /**********************************************************************/
  320. // if there is a spline, destroy the spline
  321. void
  322. DestroyRollerCoaster(RollerCoasterType *coaster)
  323. {
  324.     if (coaster != NULL)
  325.     {
  326.        if (coaster->spline != NULL)
  327.             RwDestroySpline(coaster->spline);
  328.         free(coaster);
  329.     }
  330. }
  331.  
  332.  
  333. /**********************************************************************/
  334. // show the control points
  335. static RwClump *
  336. ShowControlPoint(RwClump *clump)
  337. {
  338.     if (RwGetClumpTag(clump) == CONTROLPOINTTAG)
  339.     {
  340.         RwSetClumpState(clump, rwON);
  341.     }
  342.     return clump;
  343. }
  344.  
  345. /**********************************************************************/
  346. // hide the control points
  347. static RwClump *
  348. HideControlPoint(RwClump *clump)
  349. {
  350.     if (RwGetClumpTag(clump) == CONTROLPOINTTAG)
  351.     {
  352.         RwSetClumpState(clump, rwOFF);
  353.     }
  354.     return clump;
  355. }
  356.  
  357. /**********************************************************************/
  358. // delete the spline track and control points
  359. static RwClump *
  360. DeleteCoasterAll(RwClump *clump)
  361. {
  362.  RwInt32 tag;
  363.     tag = RwGetClumpTag(clump);
  364.     if ((tag == CONTROLPOINTTAG) || (tag == TRACKTAG) )
  365.     {
  366.         RwRemoveClumpFromScene(clump);
  367.     }
  368.     return clump;
  369. }
  370.  
  371. /**********************************************************************/
  372. // show the track
  373. static RwClump *
  374. ShowTrack(RwClump *clump)
  375. {
  376.     if (RwGetClumpTag(clump) == TRACKTAG)
  377.     {
  378.         RwSetClumpState(clump, rwON);
  379.     }
  380.     return clump;
  381. }
  382.  
  383. /**********************************************************************/
  384. // hide the track
  385. static RwClump *
  386. HideTrack(RwClump *clump)
  387. {
  388.     if (RwGetClumpTag(clump) == TRACKTAG)
  389.     {
  390.         RwSetClumpState(clump, rwOFF);
  391.     }
  392.     return clump;
  393. }
  394.  
  395.  
  396. /**********************************************************************/
  397. // position the selected object onto the spline at 0.0
  398. void
  399. PositionObjectOnSpline(RollerCoasterType *coaster,RwClump *object)
  400. {
  401.     RwV3d  vector;
  402.  
  403.     RwSplinePath path;
  404.  
  405.  #ifdef XXX 
  406.     RwReal elements[4][4];
  407.  #endif
  408.  
  409.     if(UseSmoothEnd) path=rwNICEENDS; else   path=rwSMOOTH;
  410.             
  411.     /*
  412.      * Get the spline transform. We derive the position and
  413.      * orientation of both car and camera from the resulting
  414.      * matrix.
  415.      */
  416.     vector.x = CREAL(0.0);
  417.     vector.y = CREAL(1.0);
  418.     vector.z = CREAL(0.0);
  419.   #ifdef XXX   // use if necessary to align Y
  420.   
  421.     RwPushScratchMatrix();
  422.         RwSplineTransform(coaster->spline, path, coaster->t, &vector, RwScratchMatrix());
  423.         RwGetMatrixElements(RwScratchMatrix(), elements);
  424.     RwPopScratchMatrix();
  425.     
  426.  
  427.     /*
  428.      * Compute the true look-up.
  429.      */
  430.     coaster->tUp.x = CREAL(0.0);
  431.     coaster->tUp.y = CREAL(1.0);
  432.     coaster->tUp.z = CREAL(0.0);
  433.     coaster->tAt.x = elements[2][0];
  434.     coaster->tAt.y = elements[2][1];
  435.     coaster->tAt.z = elements[2][2];
  436.     RwCrossProduct(&coaster->tAt, &coaster->tUp, &coaster->tRight);
  437.     RwNormalize(&coaster->tRight);
  438.     RwCrossProduct(&coaster->tRight, &coaster->tAt, &coaster->tUp);
  439.     RwNormalize(&coaster->tUp);
  440.     
  441.     /*
  442.      * Get the position.
  443.      */
  444.     coaster->tPosition.x = elements[3][0];
  445.     coaster->tPosition.y = elements[3][1];
  446.     coaster->tPosition.z = elements[3][2];
  447.         
  448.     RwPushScratchMatrix();                                  
  449.             elements[0][0] = -coaster->tRight.x;
  450.             elements[0][1] = -coaster->tRight.y;
  451.             elements[0][2] = -coaster->tRight.z;
  452.             elements[0][3] = CREAL(0.0);
  453.             elements[1][0] = coaster->tUp.x;
  454.             elements[1][1] = coaster->tUp.y;
  455.             elements[1][2] = coaster->tUp.z;
  456.             elements[1][3] = CREAL(0.0);
  457.             elements[2][0] = coaster->tAt.x;
  458.             elements[2][1] = coaster->tAt.y;
  459.             elements[2][2] = coaster->tAt.z;
  460.             elements[2][3] = CREAL(0.0);
  461.             elements[3][0] = coaster->tPosition.x;
  462.             elements[3][1] = coaster->tPosition.y;
  463.             elements[3][2] = coaster->tPosition.z;
  464.             elements[3][3] = CREAL(1.0);
  465.             RwSetMatrixElements(RwScratchMatrix(), elements);
  466.             RwTransformClump(object, RwScratchMatrix(), rwREPLACE);
  467.    RwPopScratchMatrix();
  468.  #endif
  469.  
  470. #define YYY
  471. #ifdef YYY    // use if not necessary to align Y
  472.     RwPushScratchMatrix();
  473.       RwSplineTransform(coaster->spline, path, coaster->t, &vector, RwScratchMatrix());
  474.       RwTransformClump(object, RwScratchMatrix(), rwREPLACE);  // used instead
  475.     RwPopScratchMatrix();
  476.  #endif
  477.  
  478.  }
  479.  
  480. /**********************************************************************/
  481. // track the camera to the coaster
  482. void
  483. TrackCameraToCoaster(RollerCoasterType *coaster, RwCamera *camera)
  484. {
  485.     RwReal x;
  486.     RwReal y;
  487.     RwReal z;
  488.     
  489.     RwSetCameraLookUp(camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
  490.     RwSetCameraLookAt(camera, coaster->tAt.x, coaster->tAt.y, coaster->tAt.z);
  491.  
  492.     x = RAdd(coaster->tPosition.x, RMul(coaster->tUp.x, CREAL(0.1)));
  493.     y = RAdd(coaster->tPosition.y, RMul(coaster->tUp.y, CREAL(0.1)));
  494.     z = RAdd(coaster->tPosition.z, RMul(coaster->tUp.z, CREAL(0.1)));
  495.     RwSetCameraPosition(camera, x, y, z);
  496. }
  497.  
  498.  
  499. /**********************************************************************/
  500. // show all coaster control points
  501. void
  502. EnableCoasterControlPoints(RollerCoasterType *coaster)
  503. {
  504.     RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)ShowControlPoint, coaster);
  505. }
  506.  
  507. /**********************************************************************/
  508. // hide all coaster control points
  509. void
  510. DisableCoasterControlPoints(RollerCoasterType *coaster)
  511. {
  512.     RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)HideControlPoint, coaster);
  513. }
  514.  
  515. /**********************************************************************/
  516. // delete all coaster control points and track
  517. void
  518. DeleteCoaster(RollerCoasterType *coaster)
  519. {
  520.     RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)DeleteCoasterAll, coaster);
  521. }
  522.  
  523.  
  524. /**********************************************************************/
  525. // display all spine path
  526. void
  527. EnableCoasterTrack(RollerCoasterType *coaster)
  528. {
  529.     RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)ShowTrack, coaster);
  530. }
  531.  
  532. /**********************************************************************/
  533. // disable all spline path
  534. void
  535. DisableCoasterTrack(RollerCoasterType *coaster)
  536. {
  537.     RwForAllClumpsInScenePointer(Scene, (RwClumpFuncPointer)HideTrack, coaster);
  538. }
  539.  
  540.