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

  1. /**********************************************************************
  2.  *
  3.  * File :     viewsub.c
  4.  *
  5.  * Abstract : Functions associated with rfView mostly taken from rwView. 
  6.  *
  7.  *            This application had been written to be compatible with
  8.  *            both the fixed and floating-point versions of the
  9.  *            RenderWare library, i.e., it uses the macros CREAL,
  10.  *            INT2REAL, RAdd, RDiv, RSub etc. If your application is
  11.  *            intended for the floating-point version of the library
  12.  *            only these macros are not necessary.
  13.  *
  14.  *            Please note that this application is intended for
  15.  *            demonstration purposes only. No support will be
  16.  *            provided for this code and it comes with no warranty.
  17.  *
  18.  **********************************************************************
  19.  *
  20.  * This file is a product of Richard F. Ferraro
  21.  *
  22.  * This file is provided as is with no warranties of any kind and is
  23.  * provided without any obligation on Richard F. Ferraro. or Criterion Software or
  24.  * Canon Inc. to assist in its use or modification.
  25.  *
  26.  * Richard F. Ferraro or Criterion Software Ltd. will not, under any
  27.  * circumstances, be liable for any lost revenue or other damages arising
  28.  * from the use of this file.
  29.  *
  30.  * Copyright (c) 1995 Richard F. Ferraro
  31.  * All Rights Reserved.
  32.  *
  33.  * RenderWare is a trademark of Canon Inc.
  34.  *
  35.  **********************************************************************/
  36.  
  37. #include <windows.h>
  38.  
  39. #include <stdlib.h>
  40. #include <stdio.h>
  41. #include <math.h>
  42. #include <string.h>
  43.  
  44. #include <rwlib.h>
  45. #include <rwwin.h>
  46.  
  47. #include "resource.h"
  48. #include "rfview.h"
  49. #include "booksub.h"
  50. #include "spline.h"
  51.  
  52. #include "pal.h"
  53. #include "settings.h"
  54.  
  55. /*
  56.  * Create a viewer scene. This involves pushing a new texture dictionary
  57.  * to hold the textures loaded into the scene (so we can discard these
  58.  * textures when the scene is destroyed), creating a scene and an
  59.  * initial light source.
  60.  */
  61. RwScene *
  62. CreateViewerScene(void)
  63. {
  64.     RwScene *scene;
  65.     RwLight *light;
  66.     
  67.     /*
  68.      * Create a new texture dictionary to store the textures loaded
  69.      * when objects are added to scene.
  70.      */
  71.     if (!RwTextureDictBegin())
  72.         return NULL;
  73.         
  74.     /*
  75.      * Create the scene to hold the clumps and lights the viewer
  76.      * views.
  77.      */
  78.     scene = RwCreateScene();
  79.     if (scene == NULL)
  80.     {
  81.         RwTextureDictEnd();
  82.         return NULL;
  83.     }
  84.     
  85.     /*
  86.      * Create the default light.
  87.      */
  88.     light = CreateLightObj(rwDIRECTIONAL);
  89.     if (light == NULL)
  90.     {
  91.         RwDestroyScene(scene);
  92.         RwTextureDictEnd();
  93.         return NULL;
  94.     }
  95.     
  96.     /*
  97.      * Add the light and its associated clump to the scene.
  98.      */
  99.     SetLightObjVisibleState(light, (ShowLights ? rwON : rwOFF));
  100.     AddLightObjToScene(scene, light);
  101.  
  102.     /*
  103.      * Create the bird's eye sprite and texture.
  104.      */
  105.     if (CreateBirdsEyeSprite() == NULL)
  106.     {
  107.         RwDestroyScene(scene);
  108.         RwTextureDictEnd();
  109.         return NULL;
  110.     }
  111.     
  112.     RwAddClumpToScene(scene, BirdsEyeSprite);
  113.      
  114.     /*
  115.      * Create the palette sprite and texture.
  116.      */
  117.     if (CreatePaletteSprite() == NULL)
  118.     {
  119.         RwDestroyScene(scene);
  120.         RwTextureDictEnd();
  121.         return NULL;
  122.     }
  123.     
  124.     RwAddClumpToScene(scene, PaletteSprite);
  125.     RwSetClumpState(PaletteSprite, rwOFF);
  126.     
  127.    return scene;    
  128. }
  129.  
  130. /**********************************************************************/
  131.  
  132. /*
  133.  * Destroy the viewer scene. This function discard the scene (and all
  134.  * its clumps and lights) and all the textures loaded by the objects
  135.  * in this world.
  136.  */
  137. void
  138. DestroyViewerScene(RwScene *scene)
  139. {
  140.       /*
  141.      * Destroy the bird's eye texture and sprite.
  142.      */
  143.     DestroyBirdsEyeSprite();
  144.     DestroyPaletteSprite();     
  145.    
  146.     /*
  147.      * Destory all the clumps (and thier lights if applicable). We
  148.      * would normally just let RwDestoryScene() do this for us but
  149.      * in this case we need to free the user-data associated with
  150.      * each clump. We do this by enumerating the DestoryClumpObj()
  151.      * function over all the clumps in the scene.
  152.      */
  153.     RwForAllClumpsInScene(scene, (RwClumpFuncVoid)DestroyClumpObj);
  154.     
  155.     /*
  156.      * Destory the scene.
  157.      */
  158.     RwDestroyScene(scene);
  159.     
  160.     /*
  161.      * Discard all the textures loaded by the objects in this scene
  162.      * (all the textures loaded are stored in the topmost texture
  163.      * dictionary - by popping this dictionary we free all the loaded
  164.      * textures as well).
  165.      */
  166.     RwTextureDictEnd();
  167. }
  168. /**********************************************************************/
  169.  
  170. void 
  171. DeselectClump(HWND window)
  172. {
  173.     SelectedClump = NULL;
  174.     SpinClump = FALSE;
  175.     
  176.     /*
  177.      * Update the menus to reflect no picked clump.
  178.      */
  179.     EnableMenuItem(GetMenu(window), IDM_FILE_SAVE,        MF_BYCOMMAND | MF_GRAYED);
  180.     EnableMenuItem(GetMenu(window), IDM_FILE_SAVEAS,      MF_BYCOMMAND | MF_GRAYED);
  181.     EnableMenuItem(GetMenu(window), IDM_EDIT_DELETE,      MF_BYCOMMAND | MF_GRAYED);
  182.     EnableMenuItem(GetMenu(window), IDM_EDIT_DUPLICATE,   MF_BYCOMMAND | MF_GRAYED);
  183.     EnableMenuItem(GetMenu(window), IDM_LIGHT_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
  184.     EnableMenuItem(GetMenu(window), IDM_CLUMP_RESET,      MF_BYCOMMAND | MF_GRAYED);
  185.     EnableMenuItem(GetMenu(window), IDM_CLUMP_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
  186.     EnableMenuItem(GetMenu(window), IDM_CAMERA_LOOKAT,    MF_BYCOMMAND | MF_GRAYED);
  187.     EnableMenuItem(GetMenu(window), IDM_CAMERA_MOVETO,    MF_BYCOMMAND | MF_GRAYED);
  188. }
  189.  
  190.  
  191.  
  192. void CreateNewScene(HWND window)
  193. {
  194.  /*
  195.   * Discard the existing scene.
  196.   */
  197.   DestroyViewerScene(Scene);
  198.                 
  199.  /*
  200.   * We also need to discard the camera's backdrop (as this too
  201.   * is a bitmap which has been matched against the existing palette.*/
  202.  if (RwGetCameraBackdrop(Camera) != NULL)
  203.  {
  204.    RwDestroyRaster(RwGetCameraBackdrop(Camera));
  205.    RwSetCameraBackdrop(Camera, NULL);
  206.    EnableMenuItem(GetMenu(window), IDM_SCENE_BACKDROPDELETE, MF_BYCOMMAND | MF_ENABLED);
  207.    BackdropFileName[0] = '\0';
  208.    SettingsChanged = TRUE;
  209.  }
  210.             
  211.  /*
  212.   * Create a new scene.
  213.   */
  214.   Scene = CreateViewerScene();
  215.   if (Scene == NULL)
  216.   {
  217.   /*
  218.    * Failing to create the new scene is a fatal error. So
  219.    * we display an error message and exit.
  220.    */
  221.    MessageBox(window, "Could not create the new 3D Scene",
  222.        WINDOWTITLE, MB_OK | MB_APPLMODAL | MB_ICONSTOP);
  223.    SendMessage(window, WM_CLOSE, 0, 0L);
  224.   }
  225.             
  226.  /*
  227.   * This is a new world so there is no longer any picked object.
  228.   */
  229.  DeselectClump(window);
  230.                 
  231. }
  232.  
  233.    void ReadFailed(HWND window, char *path)
  234.     {
  235.     char buffer[128];
  236.     switch (RwGetError())
  237.    {                    
  238.      case E_RW_NOFILE: case E_RW_BADOPEN:
  239.           /* Could not open the file... */
  240.           sprintf(buffer, "The file %s could not be opened",path );
  241.           MessageBox(window, buffer, WINDOWTITLE,
  242.                      MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  243.      break;
  244.  
  245.      case E_RW_NOMEM:
  246.           /* Ran out of memory... */
  247.           sprintf(buffer, "Insufficient memory to load object %s",
  248.                   path);
  249.           MessageBox(window, buffer, WINDOWTITLE,
  250.                        MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  251.      break;
  252.                     
  253.      default:
  254.           /* Generic, catch all error message. */
  255.           sprintf(buffer, "The 3D object %s could not be read",
  256.                   path);
  257.           MessageBox(window, buffer, WINDOWTITLE,
  258.                        MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  259.      break;
  260.      }   
  261.   }
  262.     
  263.  
  264.  
  265. /**********************************************************************/
  266.  
  267. void
  268. UpdateCameraBackdropPosition(RwCamera *camera)
  269. {
  270.     RwRaster *raster;
  271.     RwInt32   offsetX;
  272.     RwInt32   offsetY;
  273.     RwInt32   x;
  274.     RwInt32   y;
  275.     RwInt32   w;
  276.     RwInt32   h;
  277.     RwInt32   vpw;
  278.     RwInt32   vph;
  279.     
  280.     if (RwGetCameraBackdrop(camera) != NULL)
  281.     {
  282.         /*
  283.          * Get the viewport size of the camera.
  284.          */
  285.         RwGetCameraViewport(camera, NULL, NULL, &vpw, &vph);
  286.         
  287.         if (CenterBackdrop)
  288.         {
  289.             /*
  290.              * We are centering the backdrop so get the dimensions
  291.              * of the backdrop raster.
  292.              */
  293.             raster  = RwGetCameraBackdrop(camera);
  294.             w       = RwGetRasterWidth(raster);
  295.             h       = RwGetRasterHeight(raster);
  296.             x = (vpw - w) / 2;
  297.             y = (vph - h) / 2;
  298.  
  299.             if (x < 0)
  300.             {
  301.                 /*
  302.                  * The backdrop is wider than the viewport so set the
  303.                  * width of the viewport rectangle to the width of the
  304.                  * viewport and set the offset of the backdrop to ensure
  305.                  * the center of the backdrop raster is visible.
  306.                  */
  307.                 offsetX = -x;
  308.                 x = 0;
  309.                 w = vpw;
  310.             }
  311.             else
  312.             {
  313.                 offsetX = 0;
  314.             }
  315.             
  316.             if (y < 0)
  317.             {
  318.                 /*
  319.                  * The backdrop is higher than the viewport so set the
  320.                  * height of the viewport rectangle to the height of the
  321.                  * viewport and set the offset of the backdrop to ensure
  322.                  * the center of the backdrop raster is visible.
  323.                  */
  324.                 offsetY = -y;
  325.                 y = 0;
  326.                 h = vph;
  327.             }
  328.             else
  329.             {
  330.                 offsetY = 0;
  331.             }
  332.             
  333.             RwSetCameraBackdropOffset(camera, offsetX, offsetY);
  334.             RwSetCameraBackdropViewportRect(camera, x, y, w, h);
  335.         }
  336.         else
  337.         {
  338.             /*
  339.              * The backdrop is tiled so fill the entire viewport with the
  340.              * backdrop.
  341.              */
  342.             RwSetCameraBackdropOffset(camera, 0, 0);
  343.             RwSetCameraBackdropViewportRect(camera, 0, 0, vpw, vph);
  344.         }
  345.     }
  346. }
  347.  
  348.  
  349. /*
  350.  * Render the scene and copy it to the window and device context
  351.  * given. This function encapsulates the very common RenderWare
  352.  * for rendering and updating the display.
  353.  */
  354. void
  355. RenderScene(HWND window)
  356. {
  357.     HDC dc;
  358.     RwV3d pos;
  359.     RwV3d up;
  360.     RwV3d at;
  361.     RwV3d right;
  362.     
  363.    if(rfBirdsEye)
  364.     {
  365.     /*
  366.      * Render the bird's eye camera view. We turn the bird's eye
  367.      * sprite off before rendering to avoid that nasty recursive
  368.      * image thing.
  369.      */
  370.     RwSetClumpState(BirdsEyeSprite, rwOFF);
  371.     RwBeginCameraUpdate(BirdsEyeCamera, (void *)window);
  372.         RwClearCameraViewport(BirdsEyeCamera);
  373.         RwRenderScene(Scene);
  374.     RwEndCameraUpdate(BirdsEyeCamera);
  375.     RwSetClumpState(BirdsEyeSprite, rwON);
  376.     
  377.     /*
  378.      * We don't show the camera's image here. Instead we copy the results
  379.      * of the camera's rendering to the bird's eye sprite's texture. This
  380.      * will then show up on the bird's eye sprite when the scene is
  381.      * rendered with the main camer
  382.      */
  383.     RwGetCameraViewportRaster(BirdsEyeCamera, RwGetTextureRaster(BirdsEyeTexture));
  384.     
  385.     /*
  386.      * Position the bird's eye sprite so that is always in the bottom
  387.      * left of the camera's viewport.
  388.      */
  389.     RwGetCameraPosition(Camera, &pos);
  390.     RwGetCameraLookAt(Camera, &at);
  391.     RwGetCameraLookRight(Camera, &right);
  392.     RwGetCameraLookUp(Camera, &up);
  393.     pos.x = RAdd(pos.x, RMul(CREAL(1.0), at.x));
  394.     pos.y = RAdd(pos.y, RMul(CREAL(1.0), at.y));
  395.     pos.z = RAdd(pos.z, RMul(CREAL(1.0), at.z));
  396.     pos.x = RAdd(pos.x, RMul(CREAL(0.25), right.x));
  397.     pos.y = RAdd(pos.y, RMul(CREAL(0.25), right.y));
  398.     pos.z = RAdd(pos.z, RMul(CREAL(0.25), right.z));
  399.     pos.x = RAdd(pos.x, RMul(CREAL(-0.15), up.x));
  400.     pos.y = RAdd(pos.y, RMul(CREAL(-0.15), up.y));
  401.     pos.z = RAdd(pos.z, RMul(CREAL(-0.15), up.z));
  402.     RwPushScratchMatrix();
  403.         RwScaleMatrix(RwScratchMatrix(), CREAL(0.2), CREAL(0.2), CREAL(0.2), rwREPLACE);
  404.         RwTranslateMatrix(RwScratchMatrix(), pos.x, pos.y, pos.z, rwPOSTCONCAT);
  405.         RwTransformClump(BirdsEyeSprite, RwScratchMatrix(), rwREPLACE);
  406.     RwPopScratchMatrix();
  407.     }
  408.     else
  409.     {
  410.    RwSetClumpState(BirdsEyeSprite, rwOFF); 
  411.     }
  412.     
  413.     /*
  414.      * Setup the current camera and perform all necessary initialization
  415.      * before rendering takes place.
  416.      */
  417.     RwBeginCameraUpdate(Camera, (void *)window);
  418.  
  419.         /*
  420.          * Clear the areas of the camera's viewport which were damaged
  421.          * last time round. If this call is not made, ghost images of
  422.          * previous rendering will remain.
  423.          */
  424.         RwClearCameraViewport(Camera);
  425.  
  426.         /*
  427.          * Re-render the entire scene.
  428.          */
  429.         RwRenderScene(Scene);
  430.         
  431.         /*
  432.          * If there is a picked clump then display the highlight clump
  433.          * over the picked clump.
  434.          */
  435.         if ( ( (SelectedClump != NULL) && ShowHighlight) && (!rfRepeatMode))
  436.         {
  437.             RwPushScratchMatrix();
  438.                 RwGetClumpLTM(SelectedClump, RwScratchMatrix());
  439.                 RwTransformClump(HighlightClump, RwScratchMatrix(), rwREPLACE);
  440.             RwPopScratchMatrix();
  441.             RwRenderClump(HighlightClump);
  442.         }
  443.  
  444.     /*
  445.      * Perform all necessary housekeeping after rendering is complete.
  446.      * After this call, the camera's image buffer will be ready to be
  447.      * copied to the display.
  448.      */
  449.     RwEndCameraUpdate(Camera);
  450.  
  451.     /*
  452.      * Copy the camera's image buffer to the output window. Under
  453.      * Windows, RenderWare requires a device context for the client
  454.      * area of the window. This is passed in as the device specific 
  455.      * parameter of the RwShowCameraImage() call.
  456.      */
  457.     dc = GetDC(window);
  458.     RwShowCameraImage(Camera, (void*)(DWORD)dc);
  459.     ReleaseDC(window, dc);
  460. }
  461.  
  462.  
  463. /**********************************************************************/
  464.  /*
  465.  * Attempt to load an object from the given file. The actual object type
  466.  * to load is determined from the file extension. This function will
  467.  * read RenderWare clumps (.rwx), Backdrops (.bmp), Palettes (.pal) and Splines
  468.  */
  469. BOOL
  470. LoadObject(HWND window, char *pathName)
  471. {
  472.     HCURSOR         oldCursor;
  473.     RwClump        *clump;
  474.     RwRaster       *backdrop;
  475.     char            buffer[128];
  476.     char            drive[_MAX_DRIVE];
  477.     char            dir[_MAX_DIR];
  478.     char            fName[_MAX_FNAME];
  479.     char            ext[_MAX_EXT];
  480.     RwInt32         numPalEntries;
  481.     RwPaletteEntry  palEntries[256];
  482.     RwInt32         firstEntry;
  483.     RwInt32         lastEntry;
  484.     int len;
  485.     FILE *file;
  486.         
  487.     /*
  488.      * We use the file extension to decide what kind of object we
  489.      * are reading so we decompose the filename into its components.
  490.      */
  491.     _splitpath(pathName, drive, dir, fName, ext);
  492.     
  493.     if (stricmp(ext, ".rwx") == 0)
  494.     {
  495.         /*
  496.          * Its a RenderWare script file so read the clump
  497.          * and add it to the viewer's scene.
  498.          */
  499.          
  500.         /*
  501.          * This may take some time so show the wait cursor.
  502.          */
  503.         oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  504.         clump = ReadClumpObj(pathName);
  505.         SetCursor(oldCursor);
  506.         if (clump != NULL)
  507.         {
  508.             AddClumpObjToScene(Scene, clump);
  509.             return TRUE;
  510.         }
  511.         else
  512.         {
  513.             /*
  514.              * The read failed. There are a large number of reasons why this
  515.              * could happen. We will issue specific messages for the most
  516.              * common errors and a generic catch all for the rest.
  517.              */
  518.             switch (RwGetError())
  519.             {                    
  520.                 case E_RW_NOFILE:
  521.                 case E_RW_BADOPEN:
  522.                     /*
  523.                      * Could not open the file...
  524.                      */
  525.                     sprintf(buffer, "The file %s could not be opened", pathName);
  526.                     MessageBox(window, buffer, WINDOWTITLE,
  527.                                MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  528.                     break;
  529.  
  530.                 case E_RW_NOMEM:
  531.                     /*
  532.                      * Ran out of memory...
  533.                      */
  534.                     sprintf(buffer, "Insufficient memory to load object %s",
  535.                             pathName);
  536.                     MessageBox(window, buffer, WINDOWTITLE,
  537.                                MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  538.                     break;
  539.                     
  540.                 default:
  541.                     /*
  542.                      * Generic, catch all error message.
  543.                      */
  544.                     sprintf(buffer, "The 3D object %s could not be read",
  545.                             pathName);
  546.                     MessageBox(window, buffer, WINDOWTITLE,
  547.                                MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  548.                     break;
  549.             }
  550.             return FALSE;
  551.         }        
  552.     }
  553.     else 
  554.        if (stricmp(ext, ".bmp") == 0)
  555.        {
  556.   if(!rfReadSprite)
  557.    {
  558.         /*
  559.          * Its a Windows bitmap file so read the bitmap as a
  560.          * raster and make it the backdrop of the camera.
  561.          */
  562.  
  563.         /*
  564.          * This may take some time so show the wait cursor.
  565.          */
  566.         oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  567.         backdrop = RwReadRaster(pathName, rwGAMMARASTER | rwDITHERRASTER);
  568.         SetCursor(oldCursor);
  569.         if (backdrop != NULL)
  570.            {
  571.             if (RwGetCameraBackdrop(Camera) != NULL)
  572.                 /*
  573.                  * The camera has an existing backdrop so destroy it.
  574.                  */
  575.                 RwDestroyRaster(RwGetCameraBackdrop(Camera));
  576.             RwSetCameraBackdrop(Camera, backdrop);
  577.             EnableMenuItem(GetMenu(window), IDM_SCENE_BACKDROPDELETE, MF_BYCOMMAND | MF_ENABLED);
  578.             
  579.             /*
  580.              * Update the setting's backdrop filename and flag the fact
  581.              * that the settings have changed.
  582.              */
  583.             strcpy(BackdropFileName, pathName);
  584.             SettingsChanged = TRUE;
  585.             
  586.             UpdateCameraBackdropPosition(Camera);
  587.             return TRUE;
  588.         }
  589.  }
  590.  else
  591.  {
  592.         oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  593.         clump = CreateSpriteObj(pathName);
  594.         SetCursor(oldCursor);
  595.         if (clump != NULL)
  596.         {
  597.             RwAddClumpToScene(Scene, clump);
  598.             return TRUE;
  599.         }
  600.   }
  601.  
  602.             /*
  603.              * The read failed. There are a large number of reasons why this
  604.              * could happen. We will issue specific messages for the most
  605.              * common errors and a generic catch all for the rest.
  606.              */
  607.             switch (RwGetError())
  608.             {                    
  609.                 case E_RW_NOFILE:
  610.                 case E_RW_BADOPEN:
  611.                     /*
  612.                      * Could not open the file...
  613.                      */
  614.                     sprintf(buffer, "The file %s could not be opened", pathName);
  615.                     MessageBox(window, buffer, WINDOWTITLE,
  616.                                MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  617.                     break;
  618.  
  619.                 case E_RW_NOMEM:
  620.                     /*
  621.                      * Ran out of memory...
  622.                      */
  623.                     sprintf(buffer, "Insufficient memory to load backdrop %s",
  624.                             pathName);
  625.                     MessageBox(window, buffer, WINDOWTITLE,
  626.                                MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  627.                     break;
  628.                     
  629.                 default:
  630.                     /*
  631.                      * Generic, catch all error message.
  632.                      */
  633.                     sprintf(buffer, "The backdrop %s could not be read",
  634.                             pathName);
  635.                     MessageBox(window, buffer, WINDOWTITLE,
  636.                                MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  637.                     break;
  638.             }
  639.             return FALSE;
  640.  
  641.     }
  642.     else if (stricmp(ext, ".pal") == 0)
  643.     {
  644.         /*
  645.          * This may take some time so show the wait cursor.
  646.          */
  647.         oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  648.         numPalEntries = ReadPalette(pathName, palEntries);
  649.         SetCursor(oldCursor);
  650.         
  651.         if (numPalEntries > 0)
  652.         {
  653.             /*
  654.              * We have successfully read a new palette. Textures are
  655.              * not rematched when we load a new palette so they will
  656.              * look strange if we simply set the new palette. To avoid
  657.              * this potential visual strangeness we discard all textures
  658.              * and geometry when we load a new palette. We obviously
  659.              * don't want to do this without user confirmation, so ask
  660.              * the user if she or he really wishes to change the palette.
  661.              */
  662.             if (MessageBox(window,
  663.                            "In order to load a new palette the viewer must\n"
  664.                            "discard the contents of the 3D Scene.\n"
  665.                            "Do you wish to continue?",
  666.                            WINDOWTITLE,
  667.                            MB_YESNO | MB_APPLMODAL | MB_ICONQUESTION) == IDYES)
  668.             {
  669.                 /*
  670.                  * Destroy the current scene.
  671.                  */
  672.                 DestroyViewerScene(Scene);
  673.                  
  674.                 /*
  675.                  * It is also necessary to destory the camera's backdrop (as it
  676.                  * will have been matched against the previous palette).
  677.                  */
  678.                 if (RwGetCameraBackdrop(Camera) != NULL)
  679.                 {
  680.                     RwDestroyRaster(RwGetCameraBackdrop(Camera));
  681.                     RwSetCameraBackdrop(Camera, NULL);
  682.                 }
  683.  
  684.                 /*
  685.                  * Create the new scene.
  686.                  */
  687.                 Scene = CreateViewerScene();
  688.                 if (Scene == NULL)
  689.                 {
  690.                     /*
  691.                      * Failing to create the new scene is a fatal error.
  692.                      * Display an error message and exit.
  693.                      */
  694.                     MessageBox(window, "Could not create the new 3D Scene",
  695.                                WINDOWTITLE, MB_OK | MB_APPLMODAL | MB_ICONSTOP);
  696.                     SendMessage(window, WM_CLOSE, 0, 0L);
  697.                     return FALSE;
  698.                 }
  699.                 
  700.                 /*
  701.                  * As this is a new world there is no picked object yet.
  702.                  */
  703.                 DeselectClump(window);
  704.                 
  705.                 /*
  706.                  * Set the new palette.
  707.                  */
  708.                 RwGetDeviceInfo(rwFIRSTPALETTEENTRY, &firstEntry, sizeof(firstEntry));
  709.                 RwGetDeviceInfo(rwLASTPALETTEENTRY, &lastEntry, sizeof(lastEntry));
  710.                 if (numPalEntries > ((lastEntry - firstEntry)))
  711.                     numPalEntries = ((lastEntry - firstEntry));
  712.                 RwSetPaletteEntries(firstEntry, numPalEntries, palEntries, 0L);
  713.                 
  714.                 return TRUE;
  715.             }
  716.             return FALSE;
  717.         }
  718.         else
  719.         {
  720.             /*
  721.              * Generic, catch all error message.
  722.              */
  723.             sprintf(buffer, "The palette %s could not be read",
  724.                     pathName);
  725.             MessageBox(window, buffer, WINDOWTITLE,
  726.                        MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  727.             return FALSE;
  728.         }
  729.     }
  730.     else if (stricmp(ext, ".rrc") == 0)  // RF SPLINE
  731.     {
  732.      file = fopen(pathName, "r");
  733.      if (file != NULL) {
  734.       /*
  735.        * The file should be a spline
  736.       */
  737.       coaster = (RollerCoasterType *)malloc(sizeof(RollerCoasterType));
  738.       if(coaster!=NULL)
  739.        {
  740.          /* Read the description of the rollercoaster. */
  741.          fgets(coaster->description, sizeof(coaster->description), file);
  742.          len = strlen(coaster->description);
  743.          if ((len > 0) && (coaster->description[len - 1] == '\n'))
  744.            coaster->description[len - 1] = '\0';
  745.   
  746.          coaster->spline = ReadCoasterSpline(file);
  747.          if (coaster->spline == NULL)
  748.           {
  749.            free(coaster);
  750.            fclose(file);
  751.            return FALSE;
  752.           }
  753.            
  754.          /* Create the clumps representing the control points of the spline. */
  755.          if (!CreateCoasterControlPointClumps(coaster))
  756.           {
  757.            free(coaster);
  758.            fclose(file);
  759.            return FALSE;
  760.           }
  761.           
  762.          /* Convert the spline description into a coaster clump. */
  763.          coaster->coasterClump = CreateCoasterClump(coaster);
  764.          if (coaster->coasterClump == NULL)
  765.          {
  766.            RwDestroySpline(coaster->spline);
  767.            free(coaster);
  768.            fclose(file);
  769.            return FALSE;
  770.          }
  771.          RwAddClumpToScene(Scene, coaster->coasterClump);
  772.         
  773.         /* Initialize the spline parameter and spline parameter delta. */
  774.         coaster->t      = CREAL(0.0);
  775.         coaster->tDelta = DEFAULTSPLINEDELTA;
  776.         
  777.         /* Save the filename. */
  778.         strcpy(coaster->filename, pathName);
  779.         RenderScene(window); 
  780.        }
  781.       }
  782.      fclose(file);
  783.      return TRUE;
  784.      }
  785.     else
  786.      {
  787.         /*
  788.          * The file type was unknown so flag an error and fail.
  789.          */
  790.         wsprintf(buffer, "The format of %s is unknown", pathName); 
  791.         MessageBox(window, buffer, WINDOWTITLE,
  792.                    MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
  793.         return FALSE;
  794.      }
  795.