home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * File : viewsub.c
- *
- * Abstract : Functions associated with rfView mostly taken from rwView.
- *
- * 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 Richard F. Ferraro
- *
- * This file is provided as is with no warranties of any kind and is
- * provided without any obligation on Richard F. Ferraro. or Criterion Software or
- * Canon Inc. to assist in its use or modification.
- *
- * Richard F. Ferraro or 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) 1995 Richard F. Ferraro
- * All Rights Reserved.
- *
- * RenderWare is a trademark of Canon Inc.
- *
- **********************************************************************/
-
- #include <windows.h>
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <string.h>
-
- #include <rwlib.h>
- #include <rwwin.h>
-
- #include "resource.h"
- #include "rfview.h"
- #include "booksub.h"
- #include "spline.h"
-
- #include "pal.h"
- #include "settings.h"
-
- /*
- * Create a viewer scene. This involves pushing a new texture dictionary
- * to hold the textures loaded into the scene (so we can discard these
- * textures when the scene is destroyed), creating a scene and an
- * initial light source.
- */
- RwScene *
- CreateViewerScene(void)
- {
- RwScene *scene;
- RwLight *light;
-
- /*
- * Create a new texture dictionary to store the textures loaded
- * when objects are added to scene.
- */
- if (!RwTextureDictBegin())
- return NULL;
-
- /*
- * Create the scene to hold the clumps and lights the viewer
- * views.
- */
- scene = RwCreateScene();
- if (scene == NULL)
- {
- RwTextureDictEnd();
- return NULL;
- }
-
- /*
- * Create the default light.
- */
- light = CreateLightObj(rwDIRECTIONAL);
- if (light == NULL)
- {
- RwDestroyScene(scene);
- RwTextureDictEnd();
- return NULL;
- }
-
- /*
- * Add the light and its associated clump to the scene.
- */
- SetLightObjVisibleState(light, (ShowLights ? rwON : rwOFF));
- AddLightObjToScene(scene, light);
-
- /*
- * Create the bird's eye sprite and texture.
- */
- if (CreateBirdsEyeSprite() == NULL)
- {
- RwDestroyScene(scene);
- RwTextureDictEnd();
- return NULL;
- }
-
- RwAddClumpToScene(scene, BirdsEyeSprite);
-
- /*
- * Create the palette sprite and texture.
- */
- if (CreatePaletteSprite() == NULL)
- {
- RwDestroyScene(scene);
- RwTextureDictEnd();
- return NULL;
- }
-
- RwAddClumpToScene(scene, PaletteSprite);
- RwSetClumpState(PaletteSprite, rwOFF);
-
- return scene;
- }
-
- /**********************************************************************/
-
- /*
- * Destroy the viewer scene. This function discard the scene (and all
- * its clumps and lights) and all the textures loaded by the objects
- * in this world.
- */
- void
- DestroyViewerScene(RwScene *scene)
- {
- /*
- * Destroy the bird's eye texture and sprite.
- */
- DestroyBirdsEyeSprite();
- DestroyPaletteSprite();
-
- /*
- * Destory all the clumps (and thier lights if applicable). We
- * would normally just let RwDestoryScene() do this for us but
- * in this case we need to free the user-data associated with
- * each clump. We do this by enumerating the DestoryClumpObj()
- * function over all the clumps in the scene.
- */
- RwForAllClumpsInScene(scene, (RwClumpFuncVoid)DestroyClumpObj);
-
- /*
- * Destory the scene.
- */
- RwDestroyScene(scene);
-
- /*
- * Discard all the textures loaded by the objects in this scene
- * (all the textures loaded are stored in the topmost texture
- * dictionary - by popping this dictionary we free all the loaded
- * textures as well).
- */
- RwTextureDictEnd();
- }
- /**********************************************************************/
-
- void
- DeselectClump(HWND window)
- {
- SelectedClump = NULL;
- SpinClump = FALSE;
-
- /*
- * Update the menus to reflect no picked clump.
- */
- EnableMenuItem(GetMenu(window), IDM_FILE_SAVE, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_FILE_SAVEAS, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_EDIT_DELETE, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_EDIT_DUPLICATE, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_LIGHT_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_CLUMP_RESET, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_CLUMP_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_CAMERA_LOOKAT, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_CAMERA_MOVETO, MF_BYCOMMAND | MF_GRAYED);
- }
-
-
-
- void CreateNewScene(HWND window)
- {
- /*
- * Discard the existing scene.
- */
- DestroyViewerScene(Scene);
-
- /*
- * We also need to discard the camera's backdrop (as this too
- * is a bitmap which has been matched against the existing palette.*/
- if (RwGetCameraBackdrop(Camera) != NULL)
- {
- RwDestroyRaster(RwGetCameraBackdrop(Camera));
- RwSetCameraBackdrop(Camera, NULL);
- EnableMenuItem(GetMenu(window), IDM_SCENE_BACKDROPDELETE, MF_BYCOMMAND | MF_ENABLED);
- BackdropFileName[0] = '\0';
- SettingsChanged = TRUE;
- }
-
- /*
- * Create a new scene.
- */
- Scene = CreateViewerScene();
- if (Scene == NULL)
- {
- /*
- * Failing to create the new scene is a fatal error. So
- * we display an error message and exit.
- */
- MessageBox(window, "Could not create the new 3D Scene",
- WINDOWTITLE, MB_OK | MB_APPLMODAL | MB_ICONSTOP);
- SendMessage(window, WM_CLOSE, 0, 0L);
- }
-
- /*
- * This is a new world so there is no longer any picked object.
- */
- DeselectClump(window);
-
- }
-
- void ReadFailed(HWND window, char *path)
- {
- char buffer[128];
- switch (RwGetError())
- {
- case E_RW_NOFILE: case E_RW_BADOPEN:
- /* Could not open the file... */
- sprintf(buffer, "The file %s could not be opened",path );
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
-
- case E_RW_NOMEM:
- /* Ran out of memory... */
- sprintf(buffer, "Insufficient memory to load object %s",
- path);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
-
- default:
- /* Generic, catch all error message. */
- sprintf(buffer, "The 3D object %s could not be read",
- path);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
- }
- }
-
-
-
- /**********************************************************************/
-
- void
- UpdateCameraBackdropPosition(RwCamera *camera)
- {
- RwRaster *raster;
- RwInt32 offsetX;
- RwInt32 offsetY;
- RwInt32 x;
- RwInt32 y;
- RwInt32 w;
- RwInt32 h;
- RwInt32 vpw;
- RwInt32 vph;
-
- if (RwGetCameraBackdrop(camera) != NULL)
- {
- /*
- * Get the viewport size of the camera.
- */
- RwGetCameraViewport(camera, NULL, NULL, &vpw, &vph);
-
- if (CenterBackdrop)
- {
- /*
- * We are centering the backdrop so get the dimensions
- * of the backdrop raster.
- */
- raster = RwGetCameraBackdrop(camera);
- w = RwGetRasterWidth(raster);
- h = RwGetRasterHeight(raster);
- x = (vpw - w) / 2;
- y = (vph - h) / 2;
-
- if (x < 0)
- {
- /*
- * The backdrop is wider than the viewport so set the
- * width of the viewport rectangle to the width of the
- * viewport and set the offset of the backdrop to ensure
- * the center of the backdrop raster is visible.
- */
- offsetX = -x;
- x = 0;
- w = vpw;
- }
- else
- {
- offsetX = 0;
- }
-
- if (y < 0)
- {
- /*
- * The backdrop is higher than the viewport so set the
- * height of the viewport rectangle to the height of the
- * viewport and set the offset of the backdrop to ensure
- * the center of the backdrop raster is visible.
- */
- offsetY = -y;
- y = 0;
- h = vph;
- }
- else
- {
- offsetY = 0;
- }
-
- RwSetCameraBackdropOffset(camera, offsetX, offsetY);
- RwSetCameraBackdropViewportRect(camera, x, y, w, h);
- }
- else
- {
- /*
- * The backdrop is tiled so fill the entire viewport with the
- * backdrop.
- */
- RwSetCameraBackdropOffset(camera, 0, 0);
- RwSetCameraBackdropViewportRect(camera, 0, 0, vpw, vph);
- }
- }
- }
-
-
- /*
- * Render the scene and copy it to the window and device context
- * given. This function encapsulates the very common RenderWare
- * for rendering and updating the display.
- */
- void
- RenderScene(HWND window)
- {
- HDC dc;
- RwV3d pos;
- RwV3d up;
- RwV3d at;
- RwV3d right;
-
- if(rfBirdsEye)
- {
- /*
- * Render the bird's eye camera view. We turn the bird's eye
- * sprite off before rendering to avoid that nasty recursive
- * image thing.
- */
- RwSetClumpState(BirdsEyeSprite, rwOFF);
- RwBeginCameraUpdate(BirdsEyeCamera, (void *)window);
- RwClearCameraViewport(BirdsEyeCamera);
- RwRenderScene(Scene);
- RwEndCameraUpdate(BirdsEyeCamera);
- RwSetClumpState(BirdsEyeSprite, rwON);
-
- /*
- * We don't show the camera's image here. Instead we copy the results
- * of the camera's rendering to the bird's eye sprite's texture. This
- * will then show up on the bird's eye sprite when the scene is
- * rendered with the main camer
- */
- RwGetCameraViewportRaster(BirdsEyeCamera, RwGetTextureRaster(BirdsEyeTexture));
-
- /*
- * Position the bird's eye sprite so that is always in the bottom
- * left of the camera's viewport.
- */
- RwGetCameraPosition(Camera, &pos);
- RwGetCameraLookAt(Camera, &at);
- RwGetCameraLookRight(Camera, &right);
- RwGetCameraLookUp(Camera, &up);
- pos.x = RAdd(pos.x, RMul(CREAL(1.0), at.x));
- pos.y = RAdd(pos.y, RMul(CREAL(1.0), at.y));
- pos.z = RAdd(pos.z, RMul(CREAL(1.0), at.z));
- pos.x = RAdd(pos.x, RMul(CREAL(0.25), right.x));
- pos.y = RAdd(pos.y, RMul(CREAL(0.25), right.y));
- pos.z = RAdd(pos.z, RMul(CREAL(0.25), right.z));
- pos.x = RAdd(pos.x, RMul(CREAL(-0.15), up.x));
- pos.y = RAdd(pos.y, RMul(CREAL(-0.15), up.y));
- pos.z = RAdd(pos.z, RMul(CREAL(-0.15), up.z));
- RwPushScratchMatrix();
- RwScaleMatrix(RwScratchMatrix(), CREAL(0.2), CREAL(0.2), CREAL(0.2), rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), pos.x, pos.y, pos.z, rwPOSTCONCAT);
- RwTransformClump(BirdsEyeSprite, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- }
- else
- {
- RwSetClumpState(BirdsEyeSprite, rwOFF);
- }
-
- /*
- * Setup the current camera and perform all necessary initialization
- * before rendering takes place.
- */
- RwBeginCameraUpdate(Camera, (void *)window);
-
- /*
- * Clear the areas of the camera's viewport which were damaged
- * last time round. If this call is not made, ghost images of
- * previous rendering will remain.
- */
- RwClearCameraViewport(Camera);
-
- /*
- * Re-render the entire scene.
- */
- RwRenderScene(Scene);
-
- /*
- * If there is a picked clump then display the highlight clump
- * over the picked clump.
- */
- if ( ( (SelectedClump != NULL) && ShowHighlight) && (!rfRepeatMode))
- {
- RwPushScratchMatrix();
- RwGetClumpLTM(SelectedClump, RwScratchMatrix());
- RwTransformClump(HighlightClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- RwRenderClump(HighlightClump);
- }
-
- /*
- * Perform all necessary housekeeping after rendering is complete.
- * After this call, the camera's image buffer will be ready to be
- * copied to the display.
- */
- RwEndCameraUpdate(Camera);
-
- /*
- * Copy the camera's image buffer to the output window. Under
- * Windows, RenderWare requires a device context for the client
- * area of the window. This is passed in as the device specific
- * parameter of the RwShowCameraImage() call.
- */
- dc = GetDC(window);
- RwShowCameraImage(Camera, (void*)(DWORD)dc);
- ReleaseDC(window, dc);
- }
-
-
- /**********************************************************************/
- /*
- * Attempt to load an object from the given file. The actual object type
- * to load is determined from the file extension. This function will
- * read RenderWare clumps (.rwx), Backdrops (.bmp), Palettes (.pal) and Splines
- */
- BOOL
- LoadObject(HWND window, char *pathName)
- {
- HCURSOR oldCursor;
- RwClump *clump;
- RwRaster *backdrop;
- char buffer[128];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fName[_MAX_FNAME];
- char ext[_MAX_EXT];
- RwInt32 numPalEntries;
- RwPaletteEntry palEntries[256];
- RwInt32 firstEntry;
- RwInt32 lastEntry;
- int len;
- FILE *file;
-
- /*
- * We use the file extension to decide what kind of object we
- * are reading so we decompose the filename into its components.
- */
- _splitpath(pathName, drive, dir, fName, ext);
-
- if (stricmp(ext, ".rwx") == 0)
- {
- /*
- * Its a RenderWare script file so read the clump
- * and add it to the viewer's scene.
- */
-
- /*
- * This may take some time so show the wait cursor.
- */
- oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
- clump = ReadClumpObj(pathName);
- SetCursor(oldCursor);
- if (clump != NULL)
- {
- AddClumpObjToScene(Scene, clump);
- return TRUE;
- }
- else
- {
- /*
- * The read failed. There are a large number of reasons why this
- * could happen. We will issue specific messages for the most
- * common errors and a generic catch all for the rest.
- */
- switch (RwGetError())
- {
- case E_RW_NOFILE:
- case E_RW_BADOPEN:
- /*
- * Could not open the file...
- */
- sprintf(buffer, "The file %s could not be opened", pathName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
-
- case E_RW_NOMEM:
- /*
- * Ran out of memory...
- */
- sprintf(buffer, "Insufficient memory to load object %s",
- pathName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
-
- default:
- /*
- * Generic, catch all error message.
- */
- sprintf(buffer, "The 3D object %s could not be read",
- pathName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
- }
- return FALSE;
- }
- }
- else
- if (stricmp(ext, ".bmp") == 0)
- {
- if(!rfReadSprite)
- {
- /*
- * Its a Windows bitmap file so read the bitmap as a
- * raster and make it the backdrop of the camera.
- */
-
- /*
- * This may take some time so show the wait cursor.
- */
- oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
- backdrop = RwReadRaster(pathName, rwGAMMARASTER | rwDITHERRASTER);
- SetCursor(oldCursor);
- if (backdrop != NULL)
- {
- if (RwGetCameraBackdrop(Camera) != NULL)
- /*
- * The camera has an existing backdrop so destroy it.
- */
- RwDestroyRaster(RwGetCameraBackdrop(Camera));
- RwSetCameraBackdrop(Camera, backdrop);
- EnableMenuItem(GetMenu(window), IDM_SCENE_BACKDROPDELETE, MF_BYCOMMAND | MF_ENABLED);
-
- /*
- * Update the setting's backdrop filename and flag the fact
- * that the settings have changed.
- */
- strcpy(BackdropFileName, pathName);
- SettingsChanged = TRUE;
-
- UpdateCameraBackdropPosition(Camera);
- return TRUE;
- }
- }
- else
- {
- oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
- clump = CreateSpriteObj(pathName);
- SetCursor(oldCursor);
- if (clump != NULL)
- {
- RwAddClumpToScene(Scene, clump);
- return TRUE;
- }
- }
-
- /*
- * The read failed. There are a large number of reasons why this
- * could happen. We will issue specific messages for the most
- * common errors and a generic catch all for the rest.
- */
- switch (RwGetError())
- {
- case E_RW_NOFILE:
- case E_RW_BADOPEN:
- /*
- * Could not open the file...
- */
- sprintf(buffer, "The file %s could not be opened", pathName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
-
- case E_RW_NOMEM:
- /*
- * Ran out of memory...
- */
- sprintf(buffer, "Insufficient memory to load backdrop %s",
- pathName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
-
- default:
- /*
- * Generic, catch all error message.
- */
- sprintf(buffer, "The backdrop %s could not be read",
- pathName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- break;
- }
- return FALSE;
-
- }
- else if (stricmp(ext, ".pal") == 0)
- {
- /*
- * This may take some time so show the wait cursor.
- */
- oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
- numPalEntries = ReadPalette(pathName, palEntries);
- SetCursor(oldCursor);
-
- if (numPalEntries > 0)
- {
- /*
- * We have successfully read a new palette. Textures are
- * not rematched when we load a new palette so they will
- * look strange if we simply set the new palette. To avoid
- * this potential visual strangeness we discard all textures
- * and geometry when we load a new palette. We obviously
- * don't want to do this without user confirmation, so ask
- * the user if she or he really wishes to change the palette.
- */
- if (MessageBox(window,
- "In order to load a new palette the viewer must\n"
- "discard the contents of the 3D Scene.\n"
- "Do you wish to continue?",
- WINDOWTITLE,
- MB_YESNO | MB_APPLMODAL | MB_ICONQUESTION) == IDYES)
- {
- /*
- * Destroy the current scene.
- */
- DestroyViewerScene(Scene);
-
- /*
- * It is also necessary to destory the camera's backdrop (as it
- * will have been matched against the previous palette).
- */
- if (RwGetCameraBackdrop(Camera) != NULL)
- {
- RwDestroyRaster(RwGetCameraBackdrop(Camera));
- RwSetCameraBackdrop(Camera, NULL);
- }
-
- /*
- * Create the new scene.
- */
- Scene = CreateViewerScene();
- if (Scene == NULL)
- {
- /*
- * Failing to create the new scene is a fatal error.
- * Display an error message and exit.
- */
- MessageBox(window, "Could not create the new 3D Scene",
- WINDOWTITLE, MB_OK | MB_APPLMODAL | MB_ICONSTOP);
- SendMessage(window, WM_CLOSE, 0, 0L);
- return FALSE;
- }
-
- /*
- * As this is a new world there is no picked object yet.
- */
- DeselectClump(window);
-
- /*
- * Set the new palette.
- */
- RwGetDeviceInfo(rwFIRSTPALETTEENTRY, &firstEntry, sizeof(firstEntry));
- RwGetDeviceInfo(rwLASTPALETTEENTRY, &lastEntry, sizeof(lastEntry));
- if (numPalEntries > ((lastEntry - firstEntry)))
- numPalEntries = ((lastEntry - firstEntry));
- RwSetPaletteEntries(firstEntry, numPalEntries, palEntries, 0L);
-
- return TRUE;
- }
- return FALSE;
- }
- else
- {
- /*
- * Generic, catch all error message.
- */
- sprintf(buffer, "The palette %s could not be read",
- pathName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- return FALSE;
- }
- }
- else if (stricmp(ext, ".rrc") == 0) // RF SPLINE
- {
- file = fopen(pathName, "r");
- if (file != NULL) {
- /*
- * The file should be a spline
- */
- coaster = (RollerCoasterType *)malloc(sizeof(RollerCoasterType));
- if(coaster!=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';
-
- coaster->spline = ReadCoasterSpline(file);
- if (coaster->spline == NULL)
- {
- free(coaster);
- fclose(file);
- return FALSE;
- }
-
- /* Create the clumps representing the control points of the spline. */
- if (!CreateCoasterControlPointClumps(coaster))
- {
- free(coaster);
- fclose(file);
- return FALSE;
- }
-
- /* Convert the spline description into a coaster clump. */
- coaster->coasterClump = CreateCoasterClump(coaster);
- if (coaster->coasterClump == NULL)
- {
- RwDestroySpline(coaster->spline);
- free(coaster);
- fclose(file);
- return FALSE;
- }
- 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, pathName);
- RenderScene(window);
- }
- }
- fclose(file);
- return TRUE;
- }
- else
- {
- /*
- * The file type was unknown so flag an error and fail.
- */
- wsprintf(buffer, "The format of %s is unknown", pathName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- return FALSE;
- }
- }
-