home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-14 | 141.9 KB | 3,775 lines |
- /**********************************************************************
- *
- * File : rfView.c
- *
- * Abstract : Object viewer rfView.c 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 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, 1995 Criterion Software Ltd.
- * All Rights Reserved.
- *
- * RenderWare is a trademark of Canon Inc.
- *
- **********************************************************************/
-
- #if defined(__WINDOWS_386__)
-
- /*
- * Watcom strangeness...
- */
- #define INCLUDE_SHELLAPI_H
- #define INCLUDE_COMMDLG_H
- #include <windows.h>
-
- #else
-
- #include <windows.h>
- #include <shellapi.h>
- #include <commdlg.h>
-
- #endif
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
-
- #include <rwlib.h>
- #include <rwwin.h>
-
- #include "resource.h"
-
- #include "common.h"
- #include "pal.h"
- #include "settings.h"
- #include "object.h"
- #include "popmenu.h"
- #include "lightprp.h"
- #include "clumpprp.h"
- #include "color.h"
- #include "pick.h"
-
- #define MAIN
- #include "rfview.h"
-
- #include "viewdlg.h"
- #include "booksub.h"
- #include "viewsub.h"
- #include "spline.h"
-
-
- LRESULT CALLBACK
- MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
-
-
- /**********************************************************************/
-
- /*
- * Perform any necessary Windows application initialization. Basically,
- * this means registering the window class for this application.
- */
- static BOOL
- InitApplication(HANDLE instance)
- {
- WNDCLASS wndClass;
-
- wndClass.style = CS_BYTEALIGNWINDOW;
- wndClass.lpfnWndProc = (WNDPROC)MainWndProc;
- wndClass.cbClsExtra = 0;
- wndClass.cbWndExtra = 0;
- wndClass.hInstance = instance;
- wndClass.hIcon = NULL;
- wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
- wndClass.hbrBackground = NULL;
- wndClass.lpszMenuName = MAKEINTRESOURCE(IDR_RWVIEW_MENU);
- wndClass.lpszClassName = RWVIEWCLASSNAME;
-
- if (RegisterClass(&wndClass) != (ATOM)0)
- return TRUE;
- else
- return FALSE;
- }
-
- /**********************************************************************/
-
- /*
- * Perform any necessary initialization for this instance of the
- * application. This simply means creating the application's main
- * window.
- */
- static HWND
- InitInstance(HANDLE instance)
- {
- /*
- * Create the MS Window's window instance for this application. The
- * initial window size is given by DEFAULT_WINDOW_WIDTH and
- * DEFAULT_WINDOW_HEIGHT.
- */
- return CreateWindow(RWVIEWCLASSNAME,
- WINDOWTITLE,
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- DEFAULTWINDOWWIDTH, DEFAULTWINDOWHEIGHT,
- NULL, NULL, instance, NULL);
- }
-
- /**********************************************************************/
-
- /*
- * Ensure that the depth of the output display is acceptable.
- * RenderWare will operate correctly at all display depths
- * but it works best when running on an 8-bit or 16-bit
- * display. If the display depth is not 8-bit or 16-bit we
- * will display a message explaining the situation and
- * ask the user if she or he wishes to continue.
- */
- static BOOL
- IsGoodDisplayDepth(HWND window)
- {
- HDC dc;
- int depth;
- char colString[10];
- char buffer[400];
-
- dc = GetDC(window);
- depth = GetDeviceCaps(dc, BITSPIXEL);
- ReleaseDC(window, dc);
- if ((depth != 8) && (depth != 16))
- {
- if (depth < 8)
- wsprintf(colString, "%d", 1 << depth);
- else
- strcpy(colString, "true");
- wsprintf(buffer,
- "Your video adapter is currently running in %s color mode.\n"
- "Although the Viewer will operate correctly in this mode,\n"
- "we recommend that you change the mode of your video adapter\n"
- "to 256 color mode or 65536 color mode.\n"
- "Do you wish to continue?",
- colString);
-
- if (MessageBox(window, buffer, WINDOWTITLE,
- MB_YESNO | MB_APPLMODAL | MB_ICONEXCLAMATION) == IDYES)
- return TRUE;
- else
- return FALSE;
- }
- else
- {
- return TRUE;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Reset the camera to its default position and orientation. We could
- * use RwResetCamera() instead but we wish to leave the other camera
- * settings such as viewwindow alone.
- */
- static void
- ResetCamera(RwCamera *camera)
- {
- RwPushScratchMatrix();
- RwScaleMatrix(RwScratchMatrix(),
- CREAL(-1.0), CREAL(1.0), CREAL(1.0),
- rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(0.0),
- DEFAULTCAMERADISTANCE, rwPOSTCONCAT);
- RwTransformCamera(camera, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- }
-
- /**********************************************************************/
-
- /*
- * Size the highlight box to fit the given clump.
- */
- static RwClump *
- SizeHighlightToFitClump(RwClump *clump)
- {
- RwV3d bll;
- RwV3d fur;
- RwReal w;
- RwReal h;
- RwReal d;
- RwReal x;
- RwReal y;
- RwReal z;
-
- RwGetClumpLocalBBox(clump, &bll, &fur);
-
- /*
- * Scale the highlight clump to fit.
- */
- w = RSub(fur.x, bll.x);
- h = RSub(fur.y, bll.y);
- d = RSub(fur.z, bll.z);
- x = RAdd(bll.x, RDiv(w, CREAL(2.0)));
- y = RAdd(bll.y, RDiv(h, CREAL(2.0)));
- z = RAdd(bll.z, RDiv(d, CREAL(2.0)));
- RwPushScratchMatrix();
- RwScaleMatrix(RwScratchMatrix(), w, h, d, rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), x, y, z, rwPOSTCONCAT);
- RwTransformClumpJoint(HighlightClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
-
- return clump;
- }
-
- /**********************************************************************/
-
- static void
- SelectClump(HWND window, RwClump *clump)
- {
- /*
- * Remember the currently picked object.
- */
- SelectedClump = clump;
-
- /*
- * Don't spin it until the user has rotated the object.
- */
- SpinClump = FALSE;
-
- /*
- * Size the highlight to fit.
- */
- SizeHighlightToFitClump(clump);
-
- /*
- * Update the menus to reflect the picked clump.
- */
- EnableMenuItem(GetMenu(window), IDM_EDIT_DELETE, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_EDIT_DUPLICATE, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_CAMERA_LOOKAT, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_CAMERA_MOVETO, MF_BYCOMMAND | MF_ENABLED);
-
-
- switch(GETOBJECTTYPE(clump))
- {
- case rfIsLight:
- EnableMenuItem(GetMenu(window), IDM_LIGHT_PROPERTIES, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_CLUMP_RESET, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_CLUMP_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_FILE_SAVE, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_FILE_SAVEAS, MF_BYCOMMAND | MF_GRAYED);
- break;
- case rfIsClump: case rfNoMoveClump:
- EnableMenuItem(GetMenu(window), IDM_LIGHT_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_CLUMP_RESET, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_CLUMP_PROPERTIES, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_FILE_SAVE, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_FILE_SAVEAS, MF_BYCOMMAND | MF_ENABLED);
- break;
- case rfIsSprite:
- EnableMenuItem(GetMenu(window), IDM_LIGHT_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(GetMenu(window), IDM_CLUMP_RESET, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_CLUMP_PROPERTIES, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_FILE_SAVE, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(GetMenu(window), IDM_FILE_SAVEAS, MF_BYCOMMAND | MF_ENABLED);
- break;
- }
- }
-
-
-
- /**********************************************************************/
-
- /*
- * This function initializes the 3D (i.e. RenderWare) components of the
- * application. This function opens the RenderWare library, creates a
- * camera, a scene, a light and a matrix for spinning.
- */
- static BOOL
- Init3D(HWND window)
- {
- char shapePath[RWMAXPATHLEN];
- char *s;
- RwRaster *backdrop;
- RwRGBColor color;
- /*
- * Check the display depth and if it is not one of the optimal depths
- * for RenderWare (8-bit or 16-bit). If it is not then warn the user
- * and check whether they wish to continue or not.
- */
- if (!IsGoodDisplayDepth(window)) return FALSE; // CHANGE DISPLAY DEPTH
-
- /*
- * Attempt to open (and initialize) the RenderWare library.
- * Explicitly specifying the Windows driver.
- */
-
- if (!RwOpen("MSWindows", NULL))
- {
- MessageBox(window,
- "Could not open the RenderWare library",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- return FALSE;
- }
-
- /*
- arg.option = rwWINUSEDIBS;
- arg.value = 0L; // ignored for rwWINUSEDUBS
- if (!RwOpenExt("MSWindows", NULL,1,&arg))
- {
- MessageBox(window,
- "Could not open the RenderWare library",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- return FALSE;
- }
- */
-
- /*
- * Create the camera which will be used for rendering. The initial window
- * size the application will create is given by DEFAULT_WINDOW_WIDTH and
- * DEFAULT_WINDOW_HEIGHT. However, when we create a camera we have to
- * specify the largest size that camera's viewport can ever be. As the
- * camera's viewport is the same size as the window's client area we
- * have to specify the size as the maximum size of the window.
- *
- * If we compile with CONSTRAIN_SIZE then we restrict the window size
- * (using WM_GETMINMAXINFO) to MAXIMUMWINDOWWIDTH by MAXIMUMWINDOWHEIGHT.
- * If CONTRAIN_SIZE is not specified we let the window grow to the full
- * size of the screen.
- */
- #if defined(CONSTRAIN_SIZE)
- Camera = RwCreateCamera(MAXIMUMWINDOWWIDTH, MAXIMUMWINDOWHEIGHT, NULL);
- #else
- Camera = RwCreateCamera((RwInt32)GetSystemMetrics(SM_CXFULLSCREEN),
- (RwInt32)GetSystemMetrics(SM_CYFULLSCREEN), NULL);
- #endif
- if (Camera == NULL)
- {
- /*
- * As with RwOpen(), the most common cause for a failure to create
- * a camera is insufficient memory so we will explicitly check for
- * this condition and report it. Otherwise a general error is issued.
- */
- if (RwGetError() == E_RW_NOMEM)
- {
- MessageBox(window,
- "Insufficient memory to create the 3D camera",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- }
- else
- {
- MessageBox(window, "Could not create the 3D camera",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- }
- RwClose();
-
- return FALSE;
- }
-
- /*
- * Set the camera's background color to the color saved in the
- * initialization file. The initialization file stores the
- * colors as a Windows format COLORREF so we need to convert
- * it to a RenderWare RwRGBColor.
- */
- ColorRefToRGB(BackgroundColor, &color);
- RwSetCameraBackColorStruct(Camera, &color);
-
- /*
- * Move the camera to its default position.
- */
- ResetCamera(Camera);
-
- /*
- * If we have read a non-empty backdrop filename from the
- * settings file attempt to load that backdrop raster. If
- * we don't succeed we don't consider it a fatal error -
- * we simply continue.
- */
- if (BackdropFileName[0] != '\0')
- {
- backdrop = RwReadRaster(BackdropFileName,
- rwGAMMARASTER | rwDITHERRASTER);
- if (backdrop != NULL)
- RwSetCameraBackdrop(Camera, backdrop);
- }
-
-
- BirdsEyeCamera = RwCreateCamera(128, 128, NULL);
- if (BirdsEyeCamera == NULL)
- {
- /*
- * As with RwOpen(), the most common cause for a failure to create
- * a camera is insufficient memory so we will explicitly check for
- * this condition and report it. Otherwise a general error is issued.
- */
- if (RwGetError() == E_RW_NOMEM)
- {
- MessageBox(window,
- "Insufficient memory to create the bird's eye camera",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- }
- else
- {
- MessageBox(window, "Could not create the bird's eye camera",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- }
- RwDestroyCamera(Camera);
- RwClose();
-
- return FALSE;
- }
-
- /*
- * Initialize the bird's eye camera for a nice viewpoint and fixed
- * 128 x 128 viewport (the size of a texture).
- */
-
- RwSetCameraPosition(BirdsEyeCamera, CREAL(0.0), CREAL(3.0), CREAL(0.0));
- RwPointCamera(BirdsEyeCamera, CREAL(0.0), CREAL(0.0), CREAL(0.0) );
- RwSetCameraBackColor(BirdsEyeCamera, CREAL(0.0), CREAL(0.0), CREAL(1.0));
- RwSetCameraViewport(BirdsEyeCamera, 0, 0, 128, 128);
-
-
- /*
- * Create the initial scene for the viewer. The initial
- * scene consists of a default light and a new texture
- * dictionary to store the textures loaded by clumps
- * added to the scene.
- */
- Scene = CreateViewerScene();
- if (Scene == NULL)
- {
- RwDestroyCamera(Camera);
- Camera = NULL;
- RwClose();
- MessageBox(window, "Could not create the 3D Scene",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- return FALSE;
- }
-
- /*
- * Create the spin matrix.
- */
- SpinMatrix = RwCreateMatrix();
- if (SpinMatrix == NULL)
- {
- DestroyViewerScene(Scene);
- Scene = NULL;
- RwDestroyCamera(Camera);
- Camera = NULL;
- RwClose();
- MessageBox(window,
- "Could not create the RenderWare matrix",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- return FALSE;
- }
-
- /*
- * Create the highlight clump. The highlight clump is a yellow, wireframe
- * box which surrounds the picked clump.
- */
- RwModelBegin();
- RwClumpBegin();
- RwSetSurface(CREAL(0.75), CREAL(0.0), CREAL(0.0));
- RwSetSurfaceColor(CREAL(1.0), CREAL(1.0), CREAL(0.0));
- RwSetSurfaceGeometrySampling(rwWIREFRAME);
-
- RwBlock(CREAL(1.0), CREAL(1.0), CREAL(1.0));
- RwClumpEnd(&HighlightClump);
- RwModelEnd();
-
- if (HighlightClump == NULL)
- {
- DestroyViewerScene(Scene);
- Scene = NULL;
- RwDestroyCamera(Camera);
- Camera = NULL;
- RwClose();
- MessageBox(window, "Could not create the highlight object",
- WINDOWTITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
- return FALSE;
- }
-
- /*
- * Initialize the last opened filename with the first directory
- * in the RenderWare search path (if any). This gives us a good
- * chance of opening into a directory with interesting scripts
- * in it.
- */
- RwGetShapePath(shapePath);
- if (shapePath[0] == '\0')
- {
- /*
- * The shape path is empty so initialize the last filename
- * opened to empty.
- */
- LastFileName[0] = '\0';
-
- }
- else
- {
- s = strchr(shapePath, ';');
- if (s != NULL)
- {
- /*
- * We have located the end of the first directory.
- * So truncate the shape path to this point.
- */
- *s = '\0';
- }
-
- /*
- * Copy the directory to the last filename. Append a backquote
- * so we know this is a directory and not a full filename.
- */
- strcpy(LastFileName, shapePath);
- strcat(LastFileName, "\\");
- }
-
- /*
- * All the 3D components are now successfully initialized, so
- * work can begin...
- */
- RwIsOpen = TRUE;
-
- return TRUE;
- }
-
- /**********************************************************************/
-
- /*
- * This function shuts down the 3D (i.e. RenderWare) components of the
- * application in a polite fashion.
- */
- static void
- TidyUp3D(void)
- {
- /*
- * Destroy the highlight clump.
- */
- if (HighlightClump != NULL)
- RwDestroyClump(HighlightClump);
-
- /*
- * Destroy the spin matrix.
- */
- if (SpinMatrix != NULL)
- RwDestroyMatrix(SpinMatrix);
-
- /*
- * Destroy the scene. This will destroy the scene itself, the contents of
- * the scene, i.e. any clumps and lights in that scene and any textures
- * loaded by the clumps in the scene.
- */
- if (Scene != NULL)
- DestroyViewerScene(Scene);
-
- if (Camera != NULL)
- {
- /*
- * Destroy the camera's backdrop (if any). Backdrops are not
- * automatically destroyed by RwDestroyCamera() so we must
- * manually destroy the backdrop.
- */
- if (RwGetCameraBackdrop(Camera))
- RwDestroyRaster(RwGetCameraBackdrop(Camera));
-
- /*
- * Destroy the camera.
- */
- RwDestroyCamera(Camera);
- }
-
- /*
- * Close the library. This will free up any internal resources and
- * textures loaded.
- */
- RwClose();
- }
-
-
- /**********************************************************************/
- /*
- * 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 (.rrc)
- */
- static 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 // load (.bmp) onto a sprite
- {
- clump = CreateSpriteObj(pathName); // create the sprite
- 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) // read a 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;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Parse the names of any .rwx files on the command line, read those
- * files and add them to the scene. This allows RwView to be associated
- * with .rwx files in the file manager and be started automatically when
- * a .rwx file is double-clicked.
- */
- static BOOL
- ReadFromCommandLine(HWND window, char *cmdLine)
- {
- char *s1;
- char *s2;
- char fileName[_MAX_PATH];
-
- s1 = &cmdLine[0];
- s2 = &fileName[0];
- while (*s1)
- {
- /*
- * Extract one file name from the list.
- */
- while (*s1 && (*s1 != ' '))
- *s2++ = *s1++;
- *s2 = '\0';
-
- if (fileName[0])
- {
- /*
- * Attempt to load an object. The actual object type is
- * determined by LoadObject() from the extension of the file
- * name.
- *
- * NOTE: We don't include these files in the MRU file list.
- */
- if (!LoadObject(window, fileName))
- return FALSE;
- }
-
- s2 = &fileName[0];
- }
- return TRUE;
- }
-
- /**********************************************************************/
-
- #if defined(CONSTRAIN_SIZE)
-
- /*
- * Handle queries about the window's maximum extent. We only do this
- * if we are constraining the size of the window.
- */
- static void
- OnGetMinMaxInfo(MINMAXINFO FAR *minMaxInfo)
- {
- /*
- * Constraint the window to the maximum size defined by the constants
- * MAXIMUM_WINDOW_WIDTH and MAXIMUM_WINDOW_HEIGHT.
- */
- minMaxInfo->ptMaxSize.x = MAXIMUMWINDOWWIDTH;
- minMaxInfo->ptMaxSize.y = MAXIMUMWINDOWHEIGHT;
- minMaxInfo->ptMaxTrackSize.x = MAXIMUMWINDOWWIDTH;
- minMaxInfo->ptMaxTrackSize.y = MAXIMUMWINDOWHEIGHT;
- }
-
- #endif
-
- /**********************************************************************/
-
- /*
- * Handle measure item requests. Currently we user ownerdraw items for
- * the titles of the popup menus. This function computes the size
- * necessary for these items.
- */
- static void
- OnMeasureItem(HWND window, MEASUREITEMSTRUCT FAR *measureItem)
- {
- HDC dc;
- SIZE size;
-
- switch (measureItem->itemID)
- {
- case IDM_LIGHTPOPUP_LABEL:
- dc = GetDC(window);
- MeasurePopupMenuLabel(dc, "Light", &size);
- ReleaseDC(window, dc);
- measureItem->itemWidth = size.cx;
- measureItem->itemHeight = size.cy;
- break;
- case IDM_CLUMPPOPUP_LABEL:
- dc = GetDC(window);
- MeasurePopupMenuLabel(dc, "Clump", &size);
- ReleaseDC(window, dc);
- measureItem->itemWidth = size.cx;
- measureItem->itemHeight = size.cy;
- break;
- case IDM_BACKGROUNDPOPUP_LABEL:
- dc = GetDC(window);
- MeasurePopupMenuLabel(dc, "Background", &size);
- ReleaseDC(window, dc);
- measureItem->itemWidth = size.cx;
- measureItem->itemHeight = size.cy;
- break;
- }
- }
-
- /**********************************************************************/
-
- static void
- OnDrawItem(HWND window, DRAWITEMSTRUCT FAR *drawItem)
- {
- HDC dc;
- RECT rect;
- window=window; // avoid warning
- /*
- * Cache interesting stuff for eash access.
- */
- dc = drawItem->hDC;
- rect = drawItem->rcItem;
-
- switch (drawItem->itemID)
- {
- case IDM_LIGHTPOPUP_LABEL:
- DrawPopupMenuLabel(dc, &rect, "Light");
- break;
-
- case IDM_CLUMPPOPUP_LABEL:
- DrawPopupMenuLabel(dc, &rect, "Clump");
- break;
-
- case IDM_BACKGROUNDPOPUP_LABEL:
- DrawPopupMenuLabel(dc, &rect, "Background");
- break;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Handle window resize. The most important job here is to change the
- * size of the camera's viewport (if preserving the aspect ratio of
- * the viewport is necessary, then the viewwindow should also be
- * changed at this point to reflect then new aspect ratio of the
- * viewport).
- */
- static void
- OnSize(HWND window, int w, int h)
- {
- RwReal vw;
- RwReal vh;
-
- /*
- * The window has been resized. Therefore, it is necessary to
- * to modify the camera's viewport to be the same size as the
- * client area of the window.
- */
- RwSetCameraViewport(Camera, 0, 0, w, h);
-
- /*
- * Preserve the aspect ratio of the image by resizing the
- * viewindow size in proportion to to viewport size. Be ensuring
- * that the ratios of width to height of the viewport
- * and viewwindow are the same the rendered image will not
- * be distorted or stretched.
- */
- if (w > h)
- {
- vw = DEFAULTVIEWWINDOWSIZE;
- vh = RDiv(RMul(INT2REAL(h), DEFAULTVIEWWINDOWSIZE), INT2REAL(w));
- }
- else
- {
- vw = RDiv(RMul(INT2REAL(w), DEFAULTVIEWWINDOWSIZE), INT2REAL(h));
- vh = DEFAULTVIEWWINDOWSIZE;
- }
- RwSetCameraViewwindow(Camera, vw, vh);
-
- if (RwGetCameraBackdrop(Camera) != NULL)
- UpdateCameraBackdropPosition(Camera);
-
- /*
- * When the viewport has changed size we need to re-render the
- * scene for the new viewport size.
- */
- RenderScene(window);
- }
-
- /**********************************************************************/
-
- /*
- * This functions handles the left mouse button going down. Its main
- * job is to determine the kind of action to be taken when the mouse
- * moves, such as spinning a clump, or panning the camera. This involves
- * examining the virtual keys that were depressed when the mouse button
- * went down and attempting to pick a clump under the mouse pointer
- * position.
- */
- static void
- OnLButtonDown(HWND window, POINT *point, WPARAM vKeys)
- {
- RwPickRecord pick;
- RwV3d p;
- RwV3d o;
-
- /*
- * Turn the bird's eye sprite off to ensure we don't pick on it.
- */
- RwSetClumpState(BirdsEyeSprite, rwOFF);
- /*
- * If the left button is depressed anywhere in the client area of the
- * window then the animated spin is cancelled.
- */
- SpinClump = FALSE;
-
- /*
- * The mouse move action is based on whether an object is picked or
- * not. Therefore, attempt to pick an object in the scene.
- */
- if (RwPickScene(Scene, point->x, point->y, Camera, &pick))
- {
- switch (pick.type)
- {
- case rwNAPICKOBJECT:
- /*
- * No clump was picked. The background was clicked on.
- * The action taken depends on whether the camera has
- * a backdrop or not. If the camera has a backdrop then
- * if CONTROL and SHIFT were held down, the backdrop
- * is destroyed, otherwise the backdrop will be scrolled
- * on mouse move. If the camera has no backdrop then
- * no action will be taken.
- */
- DeselectClump(window);
- RenderScene(window);
-
- if (RwGetCameraBackdrop(Camera))
- {
- MouseMoveMode = mmScrollBackdrop;
- }
- else
- {
- MouseMoveMode = mmNoAction;
- }
- break;
-
- case rwPICKCLUMP:
- /*
- * A clump was picked, so remember which clump was picked
- * in order that it may be manipulated later when the
- * mouse moves.
- */
- SelectClump(window, pick.object.clump.clump);
- RenderScene(window);
-
- /*
- * When we drag a clump we don't want the origin of the
- * clump to jump to the mouse pointer position. We want
- * to keep the drag offset by the distance of the initial
- * pick from the origin of the clump. So we compute the
- * initial pick position and store it away.
- */
- GetClumpPositionUnderPointer(SelectedClump, Camera, point->x, point->y, &p);
- RwGetClumpOrigin(SelectedClump, &o);
- PickOffset.x = RSub(o.x, p.x);
- PickOffset.y = RSub(o.y, p.y);
- PickOffset.z = RSub(o.z, p.z);
-
- /*
- * Determine the exact nature of the manipulation of
- * the clump on mouse move by examining the virtual key
- * state. If the shift key was depressed, then drag
- * the clump, otherwise, spin it.
- */
- if (vKeys & MK_SHIFT)
- MouseMoveMode = mmDragClump;
- else if (vKeys & MK_CONTROL)
- MouseMoveMode = mmDragClumpInZ;
- else
- MouseMoveMode = mmSpinClump;
- break;
- }
- }
-
- /*
- * If any form of action is to be taken on mouse move, remember the
- * the current x and y position of the mouse and capture future
- * mouse movement.
- */
- if (MouseMoveMode != mmNoAction)
- {
- SetCapture(window);
- LastX = point->x;
- LastY = point->y;
- }
-
- /*
- * Turn the bird's eye sprite back on.
- */
- RwSetClumpState(BirdsEyeSprite, rwON);
-
- }
-
- /**********************************************************************/
-
- /*
- * This functions handles the right mouse button going down. Its main
- * job is to determine the kind of action to be taken when the mouse
- * moves such as panning the camera.
- */
- static void
- OnRButtonDown(HWND window, POINT *point, WPARAM vKeys)
- {
- RwPickRecord pick;
- RwClump *clump;
-
- if (vKeys & MK_SHIFT)
- {
- MouseMoveMode = mmMoveAndTurnCamera;
- }
- else if (vKeys & MK_CONTROL)
- {
- MouseMoveMode = mmTiltCamera;
- }
- else
- {
- /*
- * Right mouse button down brings up an appropriate menu
- * for the object picked on (on just tracks the camera if
- * no object is picked).
- */
- if (RwPickScene(Scene, point->x, point->y, Camera, &pick))
- {
- if (pick.type == rwPICKCLUMP)
- {
- clump = pick.object.clump.clump;
-
- /*
- * The object we picked on becomes the currently
- * selected clump and rerender the scene so the
- * highlight clump is displayed.
- */
- SelectClump(window, clump);
- RenderScene(window);
-
- /*
- * We have picked on a clump. Does the clump picked
- * represent a light or is it just a clump?
- */
- if (ISCLUMPLIGHT(clump))
- {
- /*
- * Its a light, so bring up the light pop-up
- * menu.
- */
- ClientToScreen(window, point);
- TrackPopupMenu(LightMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON,
- point->x, point->y, 0, window, NULL);
- }
- else
- {
- /*
- * Its a clump, so bring up the clump pop-up
- * menu.
- */
- ClientToScreen(window, point);
- TrackPopupMenu(ClumpMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON,
- point->x, point->y, 0, window, NULL);
- }
- }
- else
- {
- /*
- * Its the background menu. Depending on whether we are displaying
- * a backdrop or the straight backdrop color we enable and disable
- * pop-up menu options.
- */
- if (RwGetCameraBackdrop(Camera) == NULL)
- {
- EnableMenuItem(BackgroundMenu, IDM_BACKGROUNDPOPUP_COLOR, MF_BYCOMMAND | MF_ENABLED);
- EnableMenuItem(BackgroundMenu, IDM_BACKGROUNDPOPUP_DELETE, MF_BYCOMMAND | MF_GRAYED);
- }
- else
- {
- if (CenterBackdrop)
- EnableMenuItem(BackgroundMenu, IDM_BACKGROUNDPOPUP_COLOR, MF_BYCOMMAND | MF_ENABLED);
- else
- EnableMenuItem(BackgroundMenu, IDM_BACKGROUNDPOPUP_COLOR, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(BackgroundMenu, IDM_BACKGROUNDPOPUP_DELETE, MF_BYCOMMAND | MF_ENABLED);
- }
-
- /*
- * Display the background menu.
- */
- ClientToScreen(window, point);
- TrackPopupMenu(BackgroundMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON,
- point->x, point->y, 0, window, NULL);
- }
- }
- MouseMoveMode = mmNoAction;
- }
-
- /*
- * If any form of action is to be taken on mouse move, remember the
- * the current x and y position of the mouse and capture future
- * mouse movement.
- */
- if (MouseMoveMode != mmNoAction)
- {
- SetCapture(window);
- LastX = point->x;
- LastY = point->y;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Handle a movement of the mouse. If a previous left or right mouse
- * button down event has set a mouse move mode then this function will
- * take the necessary actions. For example, pan and zooming the camera,
- * panning the light, dragging or spinning a clump etc.
- */
- static void
- OnMouseMove(HWND window, POINT *point)
- {
- RwClump *parent;
- RwMatrix4d *tmpMatrix;
- RwMatrix4d *worldToLocal;
- RwV3d up;
- RwV3d right;
- RwV3d at;
- RwReal yDelta;
- RwReal xAngle;
- RwReal yAngle;
- RwInt32 xOffset;
- RwInt32 yOffset;
- RwV3d p;
- RwV3d o;
-
- /*
- * MouseMoveMode tells us what kind of action to perform.
- */
- switch (MouseMoveMode)
- {
- case mmNoAction:
- break;
-
- case mmScrollBackdrop:
- /*
- * We are scrolling the camera's backdrop. Movement of the
- * mouse in X scrolls the backdrop horizontally. Movement of
- * the mouse in Y scrolls the backdrop vertically.
- */
- RwGetCameraBackdropOffset(Camera, &xOffset, &yOffset);
- xOffset += (LastX - point->x);
- yOffset += (LastY - point->y);
- RwSetCameraBackdropOffset(Camera, xOffset, yOffset);
- break;
-
- case mmMoveAndTurnCamera:
- /*
- * We are moving and turning the camera. Movement of the
- * mouse in the X direction will turns the camera to the left
- * and right, and movement of the mouse in the Y direction
- * moves the camera forward (along its look at) or back..
- */
- yDelta = RDiv(INT2REAL(LastY - point->y), CREAL(50.0));
-
- /*
- * Move the camera back to the origin, as we wish to pan about
- * the origin of the world and not about the origin of the
- * camera.
- */
- RwVCMoveCamera(Camera, CREAL(0.0), CREAL(0.0), yDelta);
-
- /*
- * Pan the camera by mouse X delta degrees.
- */
- RwPanCamera(Camera, RDiv(INT2REAL(LastX - point->x), CREAL(4.0)));
- break;
-
- case mmTiltCamera:
- RwTiltCamera(Camera, INT2REAL(point->y - LastY));
- break;
-
- case mmSpinClump:
-
- /* Only spin clumps and lights */
- if((GETOBJECTTYPE(SelectedClump)==rfIsClump) || (GETOBJECTTYPE(SelectedClump)==rfIsLight))
- {
- if(GETOBJECTTYPE(SelectedClump)==rfNoMoveClump) break; // don't move unmoveable clump
- /*
- * Compute the angles of spin (simply derived from the mouse move deltas).
- */
- yAngle = INT2REAL(point->x - LastX);
- xAngle = INT2REAL(point->y - LastY);
-
- /*
- * In RwView, a clump is spun about its own, local coordinate system,
- * origin, rather than the origin of the world coordinate system. There
- * are a number of ways this could be achieved, but the most convenient
- * is to simply apply the rotations to the clump's joint (articulation)
- * transform.
- *
- * A further important point is that the axes of rotation must be the
- * camera's Look Up and Look Right vector rather than simply
- * [CREAL(0.0), CREAL(1.0), CREAL(0.0)] and
- * [CREAL(1.0), CREAL(0.0), CREAL(0.0)]. This ensures that, if the camera
- * has been panned, tilted, revolved or transformed so that it no longer
- * looks down the Z axis, user interaction will still operate correctly,
- * i.e. moving the mouse to the left will spin the clump clockwise etc.
- *
- * Therefore, the first stage is to get the camera's Look Up and
- * Look Right vectors.
- */
- RwGetCameraLookUp(Camera, &up);
- RwGetCameraLookRight(Camera, &right);
-
- /*
- * Unfortunately, rotation about the camera's Look Up and Look Right
- * vectors is complicated if the clump being manipulated is a child
- * clump (i.e. not the root of a clump hierarchy). If this is the
- * case, the camera's vectors have to be transformed into the
- * coordinate space of the parent of the clump being manipulated.
- */
- parent = RwGetClumpParent(SelectedClump);
- if (parent != NULL)
- {
- /*
- * Get a handle to a couple of temporary matrices.
- */
- tmpMatrix = RwPushScratchMatrix();
- worldToLocal = RwPushScratchMatrix();
-
- /*
- * Get the parent clump's LTM (which maps local coordinates to
- * world space).
- */
- RwGetClumpLTM(parent, tmpMatrix);
-
- /*
- * Invert it so that it maps world coordinates to the parent's
- * local coordinate space.
- */
- RwInvertMatrix(tmpMatrix, worldToLocal);
-
- /*
- * And transform the camera's vectors into local space.
- */
- RwTransformVector(&up, worldToLocal);
- RwNormalize(&up);
- RwTransformVector(&right, worldToLocal);
- RwNormalize(&right);
-
- /*
- * Discard the temporary matrices.
- */
- RwPopScratchMatrix();
- RwPopScratchMatrix();
- }
-
- /*
- * Apply the rotations.
- */
- RwRotateMatrix(SpinMatrix, up.x, up.y, up.z, yAngle, rwREPLACE);
- RwRotateMatrix(SpinMatrix, right.x, right.y, right.z, xAngle, rwPOSTCONCAT);
-
- /*
- * Apply the resulting, composite transformation to the clump.
- */
- RwTransformClumpJoint(SelectedClump, SpinMatrix, rwPOSTCONCAT);
-
- /*
- * Does the clump represent a light? If so change the light's
- * orientation to match that of the clump.
- */
- if (ISCLUMPLIGHT(SelectedClump))
- {
- RwGetClumpLTM(SelectedClump, RwScratchMatrix());
- RwTransformLight(GETCLUMPLIGHT(SelectedClump), RwScratchMatrix(), rwREPLACE);
- }
- else
- {
- /*
- * If the clump is not representing a light enable the momentum spin.
- * (Giving a light momentum is a little strange).
- */
- SpinClump = TRUE;
- }
- }
- break;
-
- case mmDragClump:
- /* Don't drag splines */
- if((GETOBJECTTYPE(SelectedClump)==rfIsSpline)|| (GETOBJECTTYPE(SelectedClump)==rfNoMoveClump)) break;
-
- /*
- * Get the 3D position of the mouse pointer on the plane parallel
- * to the camera on which the picked clump lies.
- */
- GetClumpPositionUnderPointer(SelectedClump, Camera, point->x, point->y, &p);
- p.x = RAdd(p.x, PickOffset.x);
- p.y = RAdd(p.y, PickOffset.y);
- p.z = RAdd(p.z, PickOffset.z);
- RwGetClumpOrigin(SelectedClump, &o);
- p.x = RSub(p.x, o.x);
- p.y = RSub(p.y, o.y);
- p.z = RSub(p.z, o.z);
- RwPushScratchMatrix();
- RwTranslateMatrix(RwScratchMatrix(), p.x, p.y, p.z, rwREPLACE);
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
- RwPopScratchMatrix();
-
- /*
- * Does the clump represent a light? If so change the light's
- * orientation to match that of the clump.
- */
- if (ISCLUMPLIGHT(SelectedClump))
- {
- RwGetClumpLTM(SelectedClump, RwScratchMatrix());
- RwTransformLight(GETCLUMPLIGHT(SelectedClump), RwScratchMatrix(), rwREPLACE);
- }
-
- break;
-
- case mmDragClumpInZ:
- /* Don't drag splines in Z */
- if((GETOBJECTTYPE(SelectedClump)==rfIsSpline)|| (GETOBJECTTYPE(SelectedClump)==rfNoMoveClump)) break;
-
- RwPushScratchMatrix();
- /*
- * Compute the amount to translate the object by. This is simply
- * derived from the mouse deltas scaled by some arbitrary quantity
- * to prevent objects moving too "quickly".
- */
- yDelta = RDiv(INT2REAL(LastY - point->y), CREAL(50.0));
-
- /*
- * In a similar fashion to spinning a clump we must take into account
- * the camera's orientation when dragging a clump. This is done by
- * translating along the camera's Look At vector (scaled appropriately)
- * rather than the clump's local axes.
- */
- RwGetCameraLookAt(Camera, &at);
-
- /*
- * See the case for mmSpinClump: for a description of why the
- * following is necessary.
- */
- parent = RwGetClumpParent(SelectedClump);
- if (parent != NULL)
- {
- tmpMatrix = RwPushScratchMatrix();
- worldToLocal = RwPushScratchMatrix();
- RwGetClumpLTM(parent, tmpMatrix);
- RwInvertMatrix(tmpMatrix, worldToLocal);
- RwTransformVector(&at, worldToLocal);
- RwNormalize(&at);
- RwPopScratchMatrix();
- RwPopScratchMatrix();
- }
-
- /*
- * Perform the translation.
- */
- RwTranslateMatrix(RwScratchMatrix(),
- RMul(at.x, yDelta), RMul(at.y, yDelta),
- RMul(at.z, yDelta), rwREPLACE);
-
- /*
- * Apply the resulting, composite transform to the clump.
- */
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
-
- RwPopScratchMatrix();
-
- /*
- * Does the clump represent a light? If so change the light's
- * orientation to match that of the clump.
- */
- if (ISCLUMPLIGHT(SelectedClump))
- {
- RwGetClumpLTM(SelectedClump, RwScratchMatrix());
- RwTransformLight(GETCLUMPLIGHT(SelectedClump), RwScratchMatrix(), rwREPLACE);
- }
-
- break;
- }
-
- if (MouseMoveMode != mmNoAction)
- {
- /*
- * Re-render the scene and copy the results to the display.
- */
- RenderScene(window);
-
- /*
- * Remember the current X and Y for next time.
- */
- LastX = point->x;
- LastY = point->y;
- }
- }
-
- /**********************************************************************/
-
- /*
- * Handle the left mouse button comming back up. The basic action is
- * to turn off mouse move actions and release mouse capture.
- */
- static void
- OnLButtonUp(void)
- {
- /*
- * If we were engaged in a mouse move action and the button has come
- * back up, then terminate the action and release mouse capture.
- */
- if (MouseMoveMode != mmNoAction)
- {
- MouseMoveMode = mmNoAction;
- ReleaseCapture();
- }
- }
-
- /**********************************************************************/
-
- /*
- * Handle the right mouse button comming back up. The basic action is
- * to turn of mouse move actions and release mouse capture.
- */
- static void
- OnRButtonUp(void)
- {
- /*
- * If we were engaged in a mouse move action and the button has come
- * back up, then terminate the action and release mouse capture.
- */
- if (MouseMoveMode != mmNoAction)
- {
- MouseMoveMode = mmNoAction;
- ReleaseCapture();
- }
- }
-
- /**********************************************************************/
-
- /*
- * Handle an MS Window's drop message, this function will attempt to
- * load the file dropped as a RenderWare clump. If that fails, it will
- * then attempt to load the file as a raster and make it the camera's
- * backdrop.
- */
- static void
- OnDrop(HWND window, HDROP drop)
- {
- int i;
- int numFiles;
- char path[_MAX_PATH];
-
- /*
- * Get the number of dropped files.
- */
- numFiles = DragQueryFile(drop, (UINT)-1, NULL, 0U);
-
- /*
- * Attempt to load each file in turn.
- */
- for (i = 0; i < numFiles; i++)
- {
- /*
- * Attempt to load the object whose file was dropped. The
- * actual object type to load is determined by LoadObject()
- * from the file extenstion.
- */
- DragQueryFile(drop, i, path, _MAX_PATH);
- if (LoadObject(window, path))
- {
- /*
- * Update the MRU file list and menus.
- */
- DeleteMRUFileMenuItems(window);
- AddFileToMRUFileList(path);
- AppendMRUFileMenuItems(window);
- }
- else
- {
- DragFinish(drop);
- return;
- }
- }
- DragFinish(drop);
-
- /*
- * As new objects have been loaded we must re-render the scene.
- */
- RenderScene(window);
- }
-
- /**********************************************************************/
-
- /*
- * Handle the WM_PAINT message by simply copying the rendering
- * already performed (an stored in the camera's image buffer) to the
- * output window. There is no need to re-render as nothing in the
- * scene has changed since the last render. HandleSize() re-renders
- * when the viewport changes and HandleDrop() re-renders when
- * clumps are added.
- */
- static void
- OnPaint(HWND window)
- {
- HDC dc;
- PAINTSTRUCT paintStruct;
-
- dc = BeginPaint(window, &paintStruct);
-
- /*
- * The truly optimal thing to do would be to get the damaged area
- * of the window that needs updating and set that to be the damaged
- * area of the viewport. If this was done then only the portion of
- * viewport corresponding to damaged area of the window would be
- * copied. However, as WM_PAINTs are rare in comparison to timer
- * expiries or mouse moves (where the real rendering effort goes)
- * there is little to be gained from damaging only a portion of
- * the display. Therefore, we invalidate the entire viewport and
- * copy it all to the window.
- */
- RwInvalidateCameraViewport(Camera);
-
- /*
- * Copy the viewport to the display.
- */
- RwShowCameraImage(Camera, (void*)(DWORD)dc);
-
- EndPaint(window, &paintStruct);
- }
-
-
- /*
- * Handle menu selections.
- */
- static void
- OnMenu(HWND window, WPARAM item)
- {
- OPENFILENAME ofn;
- int len;
- char fileName[_MAX_PATH];
- char directory[_MAX_PATH];
- char dir[_MAX_DIR];
- char ext[_MAX_EXT];
- FARPROC dialogProc;
- RwV3d point;
- RwV3d right;
- RwV3d up;
- RwClump *newClump;
- RwLight *light;
- HCURSOR oldCursor;
- RwRGBColor color;
- int rfSideCode=rfSideA;
- char buffer[128];
- RwBool status;
- RwTexture *applyTexture;
- RwTextureModes rfTexModes;
- RwPolygon3d *applyPolygon;
- RwClump *rootClump;
- RwReal angle=CREAL(0.0);
- int i;
- RwInt32 rfStart,rfLength,rfRet;
- RwPaletteOptions rfGamma;
- RwPaletteEntry* rfPalette;
- RwCombineOperation combine=rwPOSTCONCAT;
- BOOL badret;
- short rval=0,gval=0,bval=0;
- ClumpUserData * clumpData;
-
-
- switch (item)
- {
- // ********************************************** make a clump unMoveable ******************************************
- /* clumps can be made unMoveable. Once so, they can only be deleted. They can not be changed back to moveable */
- case IDM_NoMoveClump:
- if(GETOBJECTTYPE(SelectedClump)==rfIsClump) { // if selected object is a clump
- rootClump = RwGetClumpRoot(SelectedClump); // get the clump root
- clumpData = RwGetClumpData(rootClump); // get the clump (root) data
- clumpData->datatype = rfNoMoveClump; // change object type to NoMoveClump
- RwSetClumpData(rootClump,clumpData); // set it
- }
- break;
-
- // ********************************************** turn all lights on and off ******************************************
- case RF_LIGHTSON:
- RwForAllLightsInSceneInt(Scene, (RwLightFuncInt)RwSetLightState, rwON);
- break;
- case RF_LIGHTSOFF:
- RwForAllLightsInSceneInt(Scene, (RwLightFuncInt)RwSetLightState, rwOFF);
- break;
-
- // ********************************************** splines ******************************************
- /* Hide or show the spline track on the current spline */
- case IDM_HIDESPLINETRACK:
- if (HideSpline)
- {
- /* We are currently not viewing spline path. So turn it on and uncheck the menu item.*/
- HideSpline = FALSE;
- CheckMenuItem(GetMenu(window), IDM_HIDESPLINETRACK, MF_BYCOMMAND | MF_UNCHECKED);
- EnableCoasterTrack(coaster);
- }
- else
- {
- /* We are currently viewing spline path. So turn it off and check the menu item.*/
- HideSpline = TRUE;
- CheckMenuItem(GetMenu(window), IDM_HIDESPLINETRACK, MF_BYCOMMAND | MF_CHECKED);
- DisableCoasterTrack(coaster);
- }
- RenderScene(window);
- break;
-
- /* hide the control points on the current spline */
- case IDM_HIDESPLINECONTROLPOINTS:
- if (HideControlPoints)
- {
- /* We are currently not viewing control points. So turn them on and uncheck the menu item.*/
- HideControlPoints = FALSE;
- CheckMenuItem(GetMenu(window), IDM_HIDESPLINECONTROLPOINTS, MF_BYCOMMAND | MF_UNCHECKED);
- EnableCoasterControlPoints(coaster);
-
- }
- else
- {
- /* We are currently viewing control points. So turn them off and check the menu item.*/
- HideControlPoints = TRUE;
- CheckMenuItem(GetMenu(window), IDM_HIDESPLINECONTROLPOINTS, MF_BYCOMMAND | MF_CHECKED);
- DisableCoasterControlPoints(coaster);
- }
- RenderScene(window);
- break;
-
- /* delete a spline */
- case IDM_DELSPLINE:
- DeleteCoaster(coaster);
- RenderScene(window);
- break;
-
- /* move the currently selected object on the spline. If the currently selected object is not on the spline,
- then place it at the start of the spline (0.0) and move it.*/
- case IDM_MOVEOBJECTONSPLINE:
- if (TravelSpline)
- {
- /* We are currently moving on spline so stop moving and uncheck the menu item.
- */
- TravelSpline = FALSE;
- rfRepeatMode = FALSE;
- CheckMenuItem(GetMenu(window), IDM_MOVEOBJECTONSPLINE, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else
- {
- /* We are currently notmoving on spline so start moving and check the menu item. */
- TravelSpline = TRUE;
- rfRepeatMode = TRUE;
- CheckMenuItem(GetMenu(window), IDM_MOVEOBJECTONSPLINE, MF_BYCOMMAND | MF_CHECKED);
- }
- break;
-
- /* place the currently selected object onto the start of the spline (0.0). Orient it such that Y is up and
- z points positively along the spline */
- case IDM_PLACEOBJECTONSPLINE: // only place clumps on spline
- if (GETOBJECTTYPE(SelectedClump)==rfIsClump)
- {
- if(GETOBJECTTYPE(SelectedClump)==rfNoMoveClump) break;
- coaster->t = (float)0.0;
- PositionObjectOnSpline(coaster,SelectedClump);
- RenderScene(window);
- }
- break;
-
- /* accelerate at the start of the spline and decelerate at the end of the spline */
- case IDM_SMOOTHEND:
- if (UseSmoothEnd)
- {
- /* We are currently using smooth ends so don't use them and uncheck the menu item.*/
- UseSmoothEnd = FALSE;
- CheckMenuItem(GetMenu(window), IDM_SMOOTHEND, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else
- {
- /* We are currently not using smooth ends so use them So turn them back on and check the menu item. */
- UseSmoothEnd = TRUE;
- CheckMenuItem(GetMenu(window), IDM_SMOOTHEND, MF_BYCOMMAND | MF_CHECKED);
- }
- break;
-
-
- // ********************************************** camera ******************************************
- case ID_BCAM: // bird's eye camera
- CurrentCamera = BirdsEyeCamera; CurrentWindow = window;
-
- dialogProc = MakeProcInstance(CameraDlgProc, AppInstance);
- if (DialogBox(AppInstance, MAKEINTRESOURCE(IDD_CAMERA),
- window, dialogProc)==IDOK)
- {
- RenderScene(window);
- }
- FreeProcInstance(dialogProc);
- break;
-
- case ID_VCAM: // main camera
- CurrentCamera = Camera; CurrentWindow = window;
-
- dialogProc = MakeProcInstance(CameraDlgProc, AppInstance);
- if (DialogBox(AppInstance, MAKEINTRESOURCE(IDD_CAMERA),
- window, dialogProc)==IDOK)
- {
- RenderScene(window);
- }
- FreeProcInstance(dialogProc);
- break;
-
- // ********************************************** debug ******************************************
- /* Display the DEBUG box. */
- case IDM_DEBUG:
- dialogProc = MakeProcInstance(DebugDlgProc, AppInstance);
- DialogBox(AppInstance, MAKEINTRESOURCE(IDD_DEBUG), window, dialogProc);
- FreeProcInstance(dialogProc);
-
- break;
-
- // ********************************************** palette ******************************************
- /* build either a red, green, blue or gray ramp beginning at 10 and ending at 242 */
- case ID_PALETTE_RED: case ID_PALETTE_GREEN: case ID_PALETTE_BLUE: case ID_PALETTE_GRAY:
- rfPalette = (RwPaletteEntry*) malloc(256 * sizeof(RwPaletteEntry));
- rfGamma = rwOFF;
- switch(item)
- {
- case ID_PALETTE_RED:
- rval=1; gval=0; bval=0;
- break;
- case ID_PALETTE_GREEN:
- rval=0; gval=1; bval=0;
- break;
- case ID_PALETTE_BLUE:
- rval=0; gval=0; bval=1;
- break;
- case ID_PALETTE_GRAY:
- rval=1; gval=1; bval=1;
- break;
-
- }
-
- /* build the color ramp from 10 to 242 */
- rfStart = 10; rfLength = 232;
- for (i=0; i<rfLength; i++)
- {
- rfPalette[i].r = (unsigned char)((i+10)*rval);
- rfPalette[i].g = (unsigned char)((i+10)*gval);
- rfPalette[i].b = (unsigned char)((i+10)*bval);
- }
- rfRet = RwSetPaletteEntries(rfStart,rfLength,(RwPaletteEntry *) rfPalette, rfGamma);
- free(rfPalette);
- RenderScene(window);
- break;
-
- /* build a default palette consisting of several ramps */
- case ID_PALETTE_DEFAULT:
- rfPalette = (RwPaletteEntry*) malloc(256 * sizeof(RwPaletteEntry));
- rfGamma = rwOFF;
- RtDefaultPalette(rfPalette);
- rfStart = 10; rfLength = 10*MAXLUM;
- rfRet = RwSetPaletteEntries(rfStart,rfLength,(RwPaletteEntry *) rfPalette, rfGamma);
- free(rfPalette);
- RenderScene(window);
- break;
-
- // ********************************************** textures ******************************************
- // cubic texture map clump
- case ID_CUBIC:
- RwCubicTexturizeClump(SelectedClump);
- RenderScene(window);
- break;
-
- // spherical texture map clump
- case ID_SPHERICAL:
- RwSphericalTexturizeClump(SelectedClump);
- RenderScene(window);
- break;
-
- // environmental texture map the clump
- case ID_ENVIRON:
- /* rotate the selected object according to the user rotate values */
- rfRel.vc.x = CREAL(0.0); rfRel.vc.y = CREAL(1.0); rfRel.vc.z = CREAL(0.0); angle = (RwReal)rfRot.val; combine = rfRot.combine;
-
- /* build the rotate (local or global) matrix */
- RwPushScratchMatrix();
- RwGetClumpOrigin(SelectedClump,&rfRel.pos);
- rfRel.up.x = CREAL(0.0); rfRel.up.y = CREAL(1.0); rfRel.up.z = CREAL(0.0);
- rfRel.at.x = CREAL(0.0); rfRel.at.y = CREAL(0.0); rfRel.at.z = CREAL(1.0);
- rfRel.right.x = CREAL(1.0); rfRel.right.y = CREAL(0.0); rfRel.right.z = CREAL(0.0);
-
- if(combine==rwPRECONCAT) {
- RwGetClumpLTM(SelectedClump,RwScratchMatrix());
- RwTransformVector(&rfRel.up,RwScratchMatrix());
- RwTransformVector(&rfRel.at,RwScratchMatrix());
- RwTransformVector(&rfRel.right,RwScratchMatrix());
-
- RwTranslateMatrix(RwScratchMatrix(),-rfRel.pos.x,-rfRel.pos.y,-rfRel.pos.z,rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(),
- (rfRel.vc.x * rfRel.right.x) + (rfRel.vc.y * rfRel.up.x) + (rfRel.vc.z * rfRel.at.x),
- (rfRel.vc.x * rfRel.right.y) + (rfRel.vc.y * rfRel.up.y) + (rfRel.vc.z * rfRel.at.y),
- (rfRel.vc.x * rfRel.right.z) + (rfRel.vc.y * rfRel.up.z) + (rfRel.vc.z * rfRel.at.z),
- angle,rwPOSTCONCAT);
- RwTranslateMatrix(RwScratchMatrix(),rfRel.pos.x,rfRel.pos.y,rfRel.pos.z,rwPOSTCONCAT);
- }
- else {
- RwRotateMatrix(RwScratchMatrix(),rfRel.vc.x, rfRel.vc.y, rfRel.vc.z, angle, rwREPLACE);
- }
-
- /* rotate the object according to the user rotate value */
- if(rfRot.repeat!=1) rfRepeatMode = TRUE;
- for (i=0; i<rfRot.repeat; i++) {
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
- RwBeginCameraUpdate(Camera,(void *)window); // necessary for EnvMap
- RwEnvMapClump(SelectedClump); // perform environment map
- RwEndCameraUpdate(Camera);
- if(i == rfRot.repeat-1) rfRepeatMode = FALSE;
- RenderScene(window);
- }
- RwPopScratchMatrix();
- break;
-
- // LIT the texture to the tagged side of our selected object
- case ID_LITA: case ID_LITB: case ID_LITC: case ID_LITD:
- switch(item) {
- case ID_LITA: rfSideCode = rfSideA; break;
- case ID_LITB: rfSideCode = rfSideB; break;
- case ID_LITC: rfSideCode = rfSideC; break;
- case ID_LITD: rfSideCode = rfSideD; break;
- }
-
- applyPolygon = RwFindTaggedPolygon(SelectedClump,rfSideCode);
- rfTexModes=RwGetPolygonTextureModes(applyPolygon);
- RwSetPolygonTextureModes(applyPolygon,rfTexModes ^ rwLIT);
- RenderScene(window);
- break;
-
- // Filter the texture to the tagged side of our selected object
- case ID_FILTERA: case ID_FILTERB: case ID_FILTERC: case ID_FILTERD:
- switch(item) {
- case ID_FILTERA: rfSideCode = rfSideA; break;
- case ID_FILTERB: rfSideCode = rfSideB; break;
- case ID_FILTERC: rfSideCode = rfSideC; break;
- case ID_FILTERD: rfSideCode = rfSideD; break;
- }
-
- applyPolygon = RwFindTaggedPolygon(SelectedClump,rfSideCode);
- rfTexModes=RwGetPolygonTextureModes(applyPolygon);
- RwSetPolygonTextureModes(applyPolygon,rfTexModes ^ rwFILTER);
- RenderScene(window);
- break;
-
- // ForeShorten the texture to the tagged side of our selected object
- case ID_FOREA: case ID_FOREB: case ID_FOREC: case ID_FORED:
- switch(item) {
- case ID_FOREA: rfSideCode = rfSideA; break;
- case ID_FOREB: rfSideCode = rfSideB; break;
- case ID_FOREC: rfSideCode = rfSideC; break;
- case ID_FORED: rfSideCode = rfSideD; break;
- }
-
- applyPolygon = RwFindTaggedPolygon(SelectedClump,rfSideCode);
- rfTexModes=RwGetPolygonTextureModes(applyPolygon);
- RwSetPolygonTextureModes(applyPolygon,rfTexModes ^ rwFORESHORTEN);
- RenderScene(window);
- break;
-
- // apply a texture to our selected object
- case ID_APPLYA: case ID_APPLYB: case ID_APPLYC: case ID_APPLYD: case ID_APPLYALL:
-
- _splitpath(LastFileName, directory, dir, fileName, ext);
- strcat(fileName, ext);
- strcat(directory, dir);
- len = strlen(directory);
- if ((len > 0) && (directory[len - 1] == '\\'))
- directory[len - 1] = '\0';
-
- /* select the texture to map onto the selected object */
- memset(&ofn, 0, sizeof(OPENFILENAME));
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = window;
- ofn.lpstrFilter = "Texture (*.bmp)\0*.bmp\0";
- ofn.nFilterIndex = 1;
- ofn.lpstrFile= fileName;
- ofn.nMaxFile = sizeof(fileName);
- ofn.lpstrInitialDir = directory;
- ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
- if (GetOpenFileName(&ofn))
- {
- /* Save the file name for next time */
- strcpy(LastFileName, fileName);
-
- /* Read the texture */
- applyTexture=RwReadTexture(fileName);
-
- /* if successful, then apply the texture to one tagged side or all sides */
- if (applyTexture!=NULL)
- {
- switch(item) {
- case ID_APPLYA:
- rfSideCode = rfSideA;
- break;
- case ID_APPLYB:
- rfSideCode = rfSideB;
- break;
- case ID_APPLYC:
- rfSideCode = rfSideC;
- break;
- case ID_APPLYD:
- rfSideCode = rfSideD;
- break;
- case ID_APPLYALL:
- rfSideCode = rfSideAll;
- break;
- }
- if(rfSideCode==rfSideAll)
- {
- RwForAllPolygonsInClumpPointer(SelectedClump, (RwPolygon3dFuncPointer)RwSetPolygonTexture, NULL);
- RwForAllPolygonsInClumpPointer(SelectedClump, (RwPolygon3dFuncPointer)RwSetPolygonTexture, applyTexture);}
- else
- {
- applyPolygon = RwFindTaggedPolygon(SelectedClump,rfSideCode);
- RwSetPolygonTexture(applyPolygon, NULL);
- RwSetPolygonTexture(applyPolygon, applyTexture);
- }
- RenderScene(window);
- }
- }
- break;
-
- // ******************************************* Pre and Post Concat ***************************************
- // translate then rotate preconcat
- case ID_PRECON1:
- RwPushScratchMatrix();
- RwTranslateMatrix(RwScratchMatrix(),CREAL(0.0),CREAL(0),CREAL(1.2),rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(),CREAL(1),CREAL(0),CREAL(0),CREAL(45.0),rwPRECONCAT);
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- RenderScene(window);
- break;
-
- // translate then rotate postconcat
- case ID_POSTCON1:
- RwPushScratchMatrix();
- RwTranslateMatrix(RwScratchMatrix(),CREAL(0.0),CREAL(0),CREAL(1.2),rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(),CREAL(1),CREAL(0),CREAL(0),CREAL(45.0),rwPOSTCONCAT);
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- RenderScene(window);
- break;
-
- // rotate then translate preconcat
- case ID_PRECON2:
- RwPushScratchMatrix();
- RwRotateMatrix(RwScratchMatrix(),CREAL(1),CREAL(0),CREAL(0),CREAL(45.0),rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(),CREAL(0.0),CREAL(0),CREAL(1.2),rwPRECONCAT);
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- RenderScene(window);
- break;
-
- // rotate then translate postconcat
- case ID_POSTCON2:
- RwPushScratchMatrix();
- RwRotateMatrix(RwScratchMatrix(),CREAL(1),CREAL(0),CREAL(0),CREAL(45.0),rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(),CREAL(0.0),CREAL(0),CREAL(1.2),rwPOSTCONCAT);
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- RenderScene(window);
- break;
-
-
-
- // **************************************** pan, revolve, and tilt *************************************
- /* pan the selected object */
- case IDC_PAN:
- RwPushScratchMatrix();
- RwGetClumpOrigin(SelectedClump,&rfRel.pos);
- // about local Y UP
- rfRel.up.x = CREAL(0.0); rfRel.up.y = CREAL(1.0); rfRel.up.z = CREAL(0.0);
- RwGetClumpLTM(SelectedClump,RwScratchMatrix());
- RwTransformVector(&rfRel.up,RwScratchMatrix());
- RwTranslateMatrix(RwScratchMatrix(),-rfRel.pos.x,-rfRel.pos.y,-rfRel.pos.z,rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(),rfRel.up.x, rfRel.up.y, rfRel.up.z, (RwReal)rfLoc.val,rwPOSTCONCAT);
- RwTranslateMatrix(RwScratchMatrix(),rfRel.pos.x,rfRel.pos.y,rfRel.pos.z,rwPOSTCONCAT);
-
- if(rfLoc.repeat!=1) rfRepeatMode = TRUE;
- for (i=0; i<rfLoc.repeat; i++) {
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
- if(i == rfLoc.repeat-1) rfRepeatMode = FALSE;
- RenderScene(window);
- }
- RwPopScratchMatrix();
- break;
-
- /* revolve the selected object */
- case IDC_REVOLVE:
- RwPushScratchMatrix();
- RwGetClumpOrigin(SelectedClump,&rfRel.pos);
- // about local Z AT
- rfRel.at.x = CREAL(0.0); rfRel.at.y = CREAL(0.0); rfRel.at.z = CREAL(1.0);
- RwGetClumpLTM(SelectedClump,RwScratchMatrix());
- RwTransformVector(&rfRel.at,RwScratchMatrix());
- RwTranslateMatrix(RwScratchMatrix(),-rfRel.pos.x,-rfRel.pos.y,-rfRel.pos.z,rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(),rfRel.at.x, rfRel.at.y, rfRel.at.z, (RwReal)rfLoc.val,rwPOSTCONCAT);
- RwTranslateMatrix(RwScratchMatrix(),rfRel.pos.x,rfRel.pos.y,rfRel.pos.z,rwPOSTCONCAT);
-
- if(rfLoc.repeat!=1) rfRepeatMode = TRUE;
- for (i=0; i<rfLoc.repeat; i++) {
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
- if(i == rfLoc.repeat-1) rfRepeatMode = FALSE;
- RenderScene(window);
- }
- RwPopScratchMatrix();
- break;
-
- /* tilt the selected object */
- case IDC_TILT:
- RwPushScratchMatrix();
- // about local X RIGHT
- RwGetClumpOrigin(SelectedClump,&rfRel.pos);
- rfRel.right.x = CREAL(1.0); rfRel.right.y = CREAL(0.0); rfRel.right.z = CREAL(0.0);
- RwGetClumpLTM(SelectedClump,RwScratchMatrix());
- RwTransformVector(&rfRel.right,RwScratchMatrix());
- RwTranslateMatrix(RwScratchMatrix(),-rfRel.pos.x,-rfRel.pos.y,-rfRel.pos.z,rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(),rfRel.right.x, rfRel.right.y, rfRel.right.z,(RwReal) rfLoc.val, rwPOSTCONCAT);
- RwTranslateMatrix(RwScratchMatrix(),rfRel.pos.x,rfRel.pos.y,rfRel.pos.z,rwPOSTCONCAT);
-
- if(rfLoc.repeat!=1) rfRepeatMode = TRUE;
- for (i=0; i<rfLoc.repeat; i++) {
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
- if(i == rfLoc.repeat-1) rfRepeatMode = FALSE;
- RenderScene(window);
- }
- RwPopScratchMatrix();
- break;
-
- /* pan, revolve and tilt setup */
- case IDD_PRT_SETUP:
- dialogProc = MakeProcInstance(PRTDlgProc, AppInstance);
- if (DialogBox(AppInstance, MAKEINTRESOURCE(IDD_PRT_SETUP),
- window, dialogProc)==IDCANCEL)
- {
- FreeProcInstance(dialogProc);
- return;
- }
- FreeProcInstance(dialogProc);
- break;
-
- // ********************************************** translate ******************************************
- // translate the selected object about the X, Y, Z or User (local or global) defined axis
- case ID_TRANSX: case ID_TRANSY: case ID_TRANSZ: case ID_TRANSU:
- switch(item) {
- case ID_TRANSX:
- rfRel.vc.x = rfTran.x; rfRel.vc.y = CREAL(0.0); rfRel.vc.z = CREAL(0.0); combine = rfTran.combine;
- break;
- case ID_TRANSY:
- rfRel.vc.x = CREAL(0.0); rfRel.vc.y = rfTran.y; rfRel.vc.z = CREAL(0.0); combine = rfTran.combine;
- break;
- case ID_TRANSZ:
- rfRel.vc.x = CREAL(0.0); rfRel.vc.y = CREAL(0.0); rfRel.vc.z = rfTran.z; combine = rfTran.combine;
- break;
- case ID_TRANSU: // user defined through dialog
- dialogProc = MakeProcInstance(TranslateDlgProc, AppInstance);
- if (DialogBoxParam(AppInstance, MAKEINTRESOURCE(RDD_TRANSLATE),
- window, dialogProc, (LPARAM)SelectedClump)==IDCANCEL)
- {
- FreeProcInstance(dialogProc);
- return;
- }
- rfRel.vc.x = rfTran.x; rfRel.vc.y = rfTran.y; rfRel.vc.z = rfTran.z; combine = rfTran.combine;
- break;
- }
-
- rfRel.up.x = CREAL(0.0); rfRel.up.y = CREAL(1.0); rfRel.up.z = CREAL(0.0);
- rfRel.at.x = CREAL(0.0); rfRel.at.y = CREAL(0.0); rfRel.at.z = CREAL(1.0);
- rfRel.right.x = CREAL(1.0); rfRel.right.y = CREAL(0.0); rfRel.right.z = CREAL(0.0);
-
- RwPushScratchMatrix();
- if(combine==rwPRECONCAT) {
- RwGetClumpLTM(SelectedClump,RwScratchMatrix());
- RwTransformVector(&rfRel.up,RwScratchMatrix());
- RwTransformVector(&rfRel.at,RwScratchMatrix());
- RwTransformVector(&rfRel.right,RwScratchMatrix());
- }
-
- RwTranslateMatrix(RwScratchMatrix(),
- (rfRel.vc.x * rfRel.right.x) + (rfRel.vc.y * rfRel.up.x) + (rfRel.vc.z * rfRel.at.x),
- (rfRel.vc.x * rfRel.right.y) + (rfRel.vc.y * rfRel.up.y) + (rfRel.vc.z * rfRel.at.y),
- (rfRel.vc.x * rfRel.right.z) + (rfRel.vc.y * rfRel.up.z) + (rfRel.vc.z * rfRel.at.z),rwREPLACE);
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
-
- RwPopScratchMatrix();
- RenderScene(window);
- break;
-
- // ******************************************* scale ***************************************
- // scale the selected object about the X, Y, Z or User (local or global) defined axis
- case ID_SCALEX: case ID_SCALEY: case ID_SCALEZ: case ID_SCALEU:
- switch(item) {
- case ID_SCALEX:
- rfRel.vc.x = rfScale.x; rfRel.vc.y = CREAL(1.0); rfRel.vc.z = CREAL(1.0); combine = rfScale.combine;
- break;
- case ID_SCALEY:
- rfRel.vc.x = CREAL(1.0); rfRel.vc.y = rfScale.y; rfRel.vc.z = CREAL(1.0); combine = rfScale.combine;
- break;
- case ID_SCALEZ:
- rfRel.vc.x = CREAL(1.0); rfRel.vc.y = CREAL(1.0); rfRel.vc.z = rfScale.z; combine = rfScale.combine;
- break;
- case ID_SCALEU:
- dialogProc = MakeProcInstance(ScaleDlgProc, AppInstance);
- if (DialogBoxParam(AppInstance, MAKEINTRESOURCE(RDD_SCALE),
- window, dialogProc, (LPARAM)SelectedClump)==IDCANCEL){
- FreeProcInstance(dialogProc);
- return;
- }
- rfRel.vc.x = rfScale.x; rfRel.vc.y = rfScale.y; rfRel.vc.z = rfScale.z;
- combine = rfScale.combine;
- FreeProcInstance(dialogProc);
- break;
- }
-
- RwPushScratchMatrix();
- RwGetClumpOrigin(SelectedClump,&rfRel.pos);
- rfRel.up.x = CREAL(0.0); rfRel.up.y = CREAL(1.0); rfRel.up.z = CREAL(0.0);
- rfRel.at.x = CREAL(0.0); rfRel.at.y = CREAL(0.0); rfRel.at.z = CREAL(1.0);
- rfRel.right.x = CREAL(1.0); rfRel.right.y = CREAL(0.0); rfRel.right.z = CREAL(0.0);
-
- if(combine==rwPRECONCAT) {
- RwGetClumpLTM(SelectedClump,RwScratchMatrix());
- RwTransformVector(&rfRel.up,RwScratchMatrix());
- RwTransformVector(&rfRel.at,RwScratchMatrix());
- RwTransformVector(&rfRel.right,RwScratchMatrix());
- RwNormalize(&rfRel.up);
- RwNormalize(&rfRel.right);
- RwNormalize(&rfRel.at);
- }
-
- RwTranslateMatrix(RwScratchMatrix(),-rfRel.pos.x,-rfRel.pos.y,-rfRel.pos.z,rwREPLACE);
- RwScaleMatrix(RwScratchMatrix(),
- (rfRel.vc.x * rfRel.right.x) + (rfRel.vc.y * rfRel.up.x) + (rfRel.vc.z * rfRel.at.x),
- (rfRel.vc.x * rfRel.right.y) + (rfRel.vc.y * rfRel.up.y) + (rfRel.vc.z * rfRel.at.y),
- (rfRel.vc.x * rfRel.right.z) + (rfRel.vc.y * rfRel.up.z) + (rfRel.vc.z * rfRel.at.z),rwPOSTCONCAT);
- RwTranslateMatrix(RwScratchMatrix(),rfRel.pos.x,rfRel.pos.y,rfRel.pos.z,rwPOSTCONCAT);
-
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
- RenderScene(window);
-
- RwPopScratchMatrix();
- break;
-
- // ******************************************* rotate ***************************************
- // rotate the selected object about the X, Y, Z or User (local or global) defined axis
- case ID_ROTX: case ID_ROTY: case ID_ROTZ: case ID_ROTU:
- switch(item) {
- case ID_ROTX:
- rfRel.vc.x = CREAL(1.0); rfRel.vc.y = CREAL(0.0); rfRel.vc.z = CREAL(0.0); angle = (RwReal)rfRot.val; combine = rfRot.combine;
- break;
- case ID_ROTY:
- rfRel.vc.x = CREAL(0.0); rfRel.vc.y = CREAL(1.0); rfRel.vc.z = CREAL(0.0); angle = (RwReal)rfRot.val; combine = rfRot.combine;
- break;
- case ID_ROTZ:
- rfRel.vc.x = CREAL(0.0); rfRel.vc.y = CREAL(0.0); rfRel.vc.z = CREAL(1.0); angle = (RwReal)rfRot.val; combine = rfRot.combine;
- break;
- case ID_ROTU:
- dialogProc = MakeProcInstance(RotateDlgProc, AppInstance);
- if (DialogBoxParam(AppInstance, MAKEINTRESOURCE(RDD_ROTATE),
- window, dialogProc, (LPARAM)SelectedClump)==IDCANCEL) {
- FreeProcInstance(dialogProc);
- return;
- }
- rfRel.vc.x = rfRot.x; rfRel.vc.y = rfRot.y; rfRel.vc.z = rfRot.z;
- angle = (RwReal) rfRot.val; combine = (RwReal)rfRot.combine;
- FreeProcInstance(dialogProc);
- break;
- }
-
- RwPushScratchMatrix();
- RwGetClumpOrigin(SelectedClump,&rfRel.pos);
- rfRel.up.x = CREAL(0.0); rfRel.up.y = CREAL(1.0); rfRel.up.z = CREAL(0.0);
- rfRel.at.x = CREAL(0.0); rfRel.at.y = CREAL(0.0); rfRel.at.z = CREAL(1.0);
- rfRel.right.x = CREAL(1.0); rfRel.right.y = CREAL(0.0); rfRel.right.z = CREAL(0.0);
-
- if(combine==rwPRECONCAT) {
- RwGetClumpLTM(SelectedClump,RwScratchMatrix());
- RwTransformVector(&rfRel.up,RwScratchMatrix());
- RwTransformVector(&rfRel.at,RwScratchMatrix());
- RwTransformVector(&rfRel.right,RwScratchMatrix());
-
- RwTranslateMatrix(RwScratchMatrix(),-rfRel.pos.x,-rfRel.pos.y,-rfRel.pos.z,rwREPLACE);
- RwRotateMatrix(RwScratchMatrix(),
- (rfRel.vc.x * rfRel.right.x) + (rfRel.vc.y * rfRel.up.x) + (rfRel.vc.z * rfRel.at.x),
- (rfRel.vc.x * rfRel.right.y) + (rfRel.vc.y * rfRel.up.y) + (rfRel.vc.z * rfRel.at.y),
- (rfRel.vc.x * rfRel.right.z) + (rfRel.vc.y * rfRel.up.z) + (rfRel.vc.z * rfRel.at.z),angle,rwPOSTCONCAT);
- RwTranslateMatrix(RwScratchMatrix(),rfRel.pos.x,rfRel.pos.y,rfRel.pos.z,rwPOSTCONCAT);
- }
- else {
- RwRotateMatrix(RwScratchMatrix(),rfRel.vc.x, rfRel.vc.y, rfRel.vc.z, angle, rwREPLACE);
- }
-
- if(rfRot.repeat!=1) rfRepeatMode = TRUE;
- for (i=0; i<rfRot.repeat; i++) {
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
- if(i == rfRot.repeat-1) rfRepeatMode = FALSE;
- RenderScene(window);
- }
- RwPopScratchMatrix();
- break;
-
- // ********************************************** Joint Rotate ******************************************
- // rotate joing the selected object about the X, Y, Z or User (local or global) defined axis
- case ID_JROTX: case ID_JROTY: case ID_JROTZ: case ID_JROTU:
- switch(item) {
- case ID_JROTX:
- rfRel.vc.x = CREAL(1.0); rfRel.vc.y = CREAL(0.0); rfRel.vc.z = CREAL(0.0); angle = (RwReal)rfRot.val;
- break;
- case ID_JROTY:
- rfRel.vc.x = CREAL(0.0); rfRel.vc.y = CREAL(1.0); rfRel.vc.z = CREAL(0.0); angle = (RwReal)rfRot.val;
- break;
- case ID_JROTZ:
- rfRel.vc.x = CREAL(0.0); rfRel.vc.y = CREAL(0.0); rfRel.vc.z = CREAL(1.0); angle = (RwReal)rfRot.val;
- break;
- case ID_JROTU:
- dialogProc = MakeProcInstance(RotateDlgProc, AppInstance);
- if (DialogBoxParam(AppInstance, MAKEINTRESOURCE(RDD_ROTATE),
- window, dialogProc, (LPARAM)SelectedClump)==IDCANCEL) {
- FreeProcInstance(dialogProc);
- return;
- }
- rfRel.vc.x = rfRot.x; rfRel.vc.y = rfRot.y; rfRel.vc.z = rfRot.z;
- angle = (RwReal) rfRot.val;
- FreeProcInstance(dialogProc);
- break;
- }
-
- RwPushScratchMatrix();
- RwRotateMatrix(RwScratchMatrix(),rfRel.vc.x, rfRel.vc.y, rfRel.vc.z, angle, rwREPLACE);
-
- if(rfRot.repeat!=1) rfRepeatMode = TRUE;
- for (i=0; i<rfRot.repeat; i++) {
- RwTransformClumpJoint(SelectedClump, RwScratchMatrix(), rwPOSTCONCAT);
- if(i == rfRot.repeat-1) rfRepeatMode = FALSE;
- RenderScene(window);
- }
- RwPopScratchMatrix();
- break;
-
-
- // ********************************************** materials ******************************************
- // turn on/off material animation
- case ID_MANIMATE:
- if (rfSurf.MatAnimate) { // turn it off
- rfSurf.MatAnimate = FALSE;
- CheckMenuItem(GetMenu(window), ID_MANIMATE, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else { // turn it on
- rfSurf.MatAnimate = TRUE;
- CheckMenuItem(GetMenu(window), ID_MANIMATE, MF_BYCOMMAND | MF_CHECKED);
- }
- break;
-
- // turn on/off ambient component of material animation
- case MRF_AMBIENT:
- if (rfSurf.Ambient) { // turn it off
- rfSurf.Ambient = FALSE;
- CheckMenuItem(GetMenu(window), MRF_AMBIENT, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else { // turn it on
- rfSurf.Ambient = TRUE;
- CheckMenuItem(GetMenu(window), MRF_AMBIENT, MF_BYCOMMAND | MF_CHECKED);
- }
- break;
-
- // turn on/off diffuse component of material animation
- case MRF_DIFFUSE:
- if (rfSurf.Diffuse) { // turn it off
- rfSurf.Diffuse = FALSE;
- CheckMenuItem(GetMenu(window), MRF_DIFFUSE, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else { // turn it on
- rfSurf.Diffuse = TRUE;
- CheckMenuItem(GetMenu(window), MRF_DIFFUSE, MF_BYCOMMAND | MF_CHECKED);
- }
- break;
-
- // turn on/off specular component of material animation
- case MRF_SPECULAR:
- if (rfSurf.Specular) { // turn it off
- rfSurf.Specular = FALSE;
- CheckMenuItem(GetMenu(window), MRF_SPECULAR, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else { // turn it on
- rfSurf.Specular = TRUE;
- CheckMenuItem(GetMenu(window), MRF_SPECULAR, MF_BYCOMMAND | MF_CHECKED);
- }
- break;
-
- // ********************************************** select Chapters for path ******************************************
- case IDM_CHAP5:
- strcpy(fileName,"\\l3d\\chap5\\box"); RwSetShapePath(fileName, rwREPLACE);
- strcpy(fileName,"\\l3d\\chap5\\poly"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap5\\robot"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap5\\tex1"); RwSetShapePath(fileName, rwPOSTCONCAT);
- break;
- case IDM_CHAP6:
- strcpy(fileName,"\\l3d\\chap6\\kitchen"); RwSetShapePath(fileName, rwREPLACE);
- strcpy(fileName,"\\l3d\\chap6\\ship"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap6\\robot"); RwSetShapePath(fileName, rwPOSTCONCAT);
- break;
- case IDM_CHAP7:
- strcpy(fileName,"\\l3d\\chap7\\ball"); RwSetShapePath(fileName, rwREPLACE);
- strcpy(fileName,"\\l3d\\chap7\\color"); RwSetShapePath(fileName, rwPOSTCONCAT);
- break;
- case IDM_CHAP8:
- strcpy(fileName,"\\l3d\\chap8\\box"); RwSetShapePath(fileName, rwREPLACE);
- strcpy(fileName,"\\l3d\\chap8\\fore"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap8\\turn"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap8\\wall"); RwSetShapePath(fileName, rwPOSTCONCAT);
- break;
- case IDM_CHAP9:
- strcpy(fileName,"\\l3d\\chap9\\ani"); RwSetShapePath(fileName, rwREPLACE);
- strcpy(fileName,"\\l3d\\chap9\\box"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap9\\mask"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap9\\poly"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap9\\ship"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap9\\tex1"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap9\\tex2"); RwSetShapePath(fileName, rwPOSTCONCAT);
- break;
- case IDM_CHAP10:
- strcpy(fileName,"\\l3d\\chap10"); RwSetShapePath(fileName, rwREPLACE);
- break;
- case IDM_CHAP11:
- strcpy(fileName,"\\l3d\\chap11"); RwSetShapePath(fileName, rwREPLACE);
- break;
- case IDM_CHAP12:
- strcpy(fileName,"\\l3d\\chap12\\car"); RwSetShapePath(fileName, rwREPLACE);
- strcpy(fileName,"\\l3d\\chap12\\f16"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap12\\tracks"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap12\\triad"); RwSetShapePath(fileName, rwPOSTCONCAT);
- break;
- case IDM_CHAP13:
- strcpy(fileName,"\\l3d\\chap13\\compos"); RwSetShapePath(fileName, rwREPLACE);
- strcpy(fileName,"\\l3d\\chap13\\coral"); RwSetShapePath(fileName, rwPOSTCONCAT);
- break;
- case IDM_CHAP15:
- strcpy(fileName,"\\l3d\\chap15"); RwSetShapePath(fileName, rwREPLACE);
- break;
- case IDM_CHAP19:
- strcpy(fileName,"\\l3d\\chap19\\dolphin"); RwSetShapePath(fileName, rwREPLACE);
- strcpy(fileName,"\\l3d\\chap19\\face"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap19\\include"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap19\\misc"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap19\\reflect"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap19\\robot"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap19\\share"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap19\\triad"); RwSetShapePath(fileName, rwPOSTCONCAT);
- strcpy(fileName,"\\l3d\\chap19\\tv"); RwSetShapePath(fileName, rwPOSTCONCAT);
- break;
- // ********************************************** amimate textures ******************************************
- /* each animate cycle, a certain number of frames are skipped. The more frames that are skipped,
- the faster the animation plays */
- // increment the number of frames to skip per frame to speed the animation
- case IDM_FASTER:
- rfChangeAnimateSpeed(SelectedClump,1);
- break;
-
- // decrement the number of frames to skip per frame to slow the animation
- case IDM_SLOWER:
- rfChangeAnimateSpeed(SelectedClump,-1);
- break;
-
- /* Each timer cycle, the textureRate amount is added to an accumulator. Every overflow of the accumulator
- causes the texture animation to go to its next frame */
- // accelerate the texture frame rate by making the textureRate larger
- case IDM_ACCELERATE:
- textureRate += (float)0.1;
- if(textureRate>=1.0) textureRate=(float)1.0;
- break;
-
- // decelerate the texture frame rate by making the textureRate smaller
- case IDM_DECELERATE:
- textureRate -= (float)0.1;
- if(textureRate<=0.1) textureRate=(float)0.1;
- break;
-
- // ********************************************** modify raster ******************************************
- // change a texture raster for either 8-bit or 16-bit display modes
- case IDM_MODTEXRASTER:
- if(DisplayDepth==16)
- badret = rfModifyTextureRaster16(SelectedClump);
- else
- badret = rfModifyTextureRaster8(SelectedClump);
- if(badret)
- {
- RenderScene(window);
- }
- break;
-
- // change a backdrop raster for either 8-bit or 16-bit display modes
- case IDM_MODBACKRASTER:
- CurrentWindow = window;
- if(DisplayDepth==16)
- badret = rfModifyBackdropRaster16(Camera);
- else
- badret = rfModifyBackdropRaster8(Camera);
- if(badret)
- {
- RwInvalidateCameraViewport(Camera);
- RenderScene(window);
- }
- break;
-
- // ********************************************** sprites ******************************************
- //when set, a (.bmp) file is read onto a newly created sprite as opposed to the background raster
- case MRF_READSPRITES:
- if (rfReadSprite) { // turn it off
- rfReadSprite = FALSE;
- CheckMenuItem(GetMenu(window), MRF_READSPRITES, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else { // turn it on
- rfReadSprite = TRUE;
- CheckMenuItem(GetMenu(window), MRF_READSPRITES, MF_BYCOMMAND | MF_CHECKED);
- }
- break;
-
- // ********************************************** bird's eye view ******************************************
- // when set, a sprite is created with all 256 colors present as 16 by 16 color boxes thereby showing the entire palette
- case MRF_PALETTEVIEW:
- if (!rfPaletteView) { // turn it on
- rfPaletteView = TRUE;
- RwSetClumpState(PaletteSprite, rwON);
- CheckMenuItem(GetMenu(window), MRF_PALETTEVIEW, MF_BYCOMMAND | MF_CHECKED);
- }
- else { // turn it off
- rfPaletteView = FALSE;
- RwSetClumpState(PaletteSprite, rwOFF);
- CheckMenuItem(GetMenu(window), MRF_PALETTEVIEW, MF_BYCOMMAND | MF_UNCHECKED);
-
-
- }
- RenderScene(window);
- break;
-
-
- // ********************************************** bird's eye view ******************************************
- /* when on, a bird's eye sprite is created and onto the raster of this sprite is placed a second camera viewport */
- case MRF_BIRDSEYE:
- if (rfBirdsEye) { // turn it off
- rfBirdsEye = FALSE;
- CheckMenuItem(GetMenu(window), MRF_BIRDSEYE, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else { // turn it on
- rfBirdsEye = TRUE;
- CheckMenuItem(GetMenu(window), MRF_BIRDSEYE, MF_BYCOMMAND | MF_CHECKED);
- }
- RenderScene(window);
- break;
-
-
- // ********************************************** regular rwView ******************************************
- case IDM_FILE_OPEN:
- /*
- * Use a common dialog to get the name of the file to load.
- * We intialize things with the directory and name of the last
- * filename loaded.
- */
- _splitpath(LastFileName, directory, dir, fileName, ext);
- strcat(fileName, ext);
- strcat(directory, dir);
- len = strlen(directory);
- if ((len > 0) && (directory[len - 1] == '\\'))
- directory[len - 1] = '\0';
-
- memset(&ofn, 0, sizeof(OPENFILENAME));
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = window;
- ofn.lpstrFilter = "RW Object (*.rwx)\0*.rwx\0Backdrop (*.bmp)\0*.bmp\0Spline (*.rrc)\0*.rrc\0Palette (*.pal)\0*.pal\0";
- ofn.nFilterIndex = 1;
- ofn.lpstrFile= fileName;
- ofn.nMaxFile = sizeof(fileName);
- ofn.lpstrInitialDir = directory;
- ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
- if (GetOpenFileName(&ofn))
- {
- /*
- * Save the file name for next time.
- */
- strcpy(LastFileName, fileName);
-
- /*
- * Use LoadObject() to load an object of the appropriate type from
- * the given file. LoadObject() determines the object type to load
- * from the extension of the file.
- */
- if (LoadObject(window, fileName))
- {
- /*
- * Update the MRU file list and menus.
- */
- DeleteMRUFileMenuItems(window);
- AddFileToMRUFileList(fileName);
- AppendMRUFileMenuItems(window);
- RenderScene(window);
- }
- }
- break;
-
- case IDM_FILE_SAVE:
- /*
- * Ensure there is a clump and its not the representation
- * of a light (we don't save those).
- */
- if ((SelectedClump != NULL) && (!ISCLUMPLIGHT(SelectedClump)))
- {
- /*
- * Write out under the filename stored with the clump.
- */
- oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
- status = RwWriteShape(GETCLUMPFILENAME(SelectedClump), SelectedClump);
- SetCursor(oldCursor);
-
- if (!status)
- {
- sprintf(buffer, "Could not write the file %s",
- GETCLUMPFILENAME(SelectedClump));
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- }
- }
- break;
-
- case IDM_FILE_SAVEAS:
- /*
- * Ensure there is a clump and its not the representation
- * of a light (we don't save those).
- */
- if ((SelectedClump != NULL) && (!ISCLUMPLIGHT(SelectedClump)))
- {
- /*
- * Use a common dialog to get the name of the file to save.
- * We intialize things with the current filename of the clump
- * to be saved.
- */
- _splitpath(GETCLUMPFILENAME(SelectedClump), directory, dir, fileName, ext);
- strcat(fileName, ext);
- strcat(directory, dir);
- len = strlen(directory);
- if ((len > 0) && (directory[len - 1] == '\\'))
- directory[len - 1] = '\0';
-
- memset(&ofn, 0, sizeof(OPENFILENAME));
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = window;
- ofn.lpstrFilter = "RW Object (*.rwx)\0*.rwx\0";
- ofn.nFilterIndex = 1;
- ofn.lpstrFile= fileName;
- ofn.nMaxFile = sizeof(fileName);
- ofn.lpstrInitialDir = directory;
- ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
- if (GetSaveFileName(&ofn))
- {
- /*
- * Write out under the new filename.
- */
- oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
- status = RwWriteShape(fileName, SelectedClump);
- SetCursor(oldCursor);
-
- if (!status)
- {
- sprintf(buffer, "Could not write the file %s",
- fileName);
- MessageBox(window, buffer, WINDOWTITLE,
- MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION);
- }
- }
-
- /*
- * Update the clump's stored filename to reflect the new file it
- * is stored int.
- */
- strcpy(GETCLUMPFILENAME(SelectedClump), fileName);
- }
- break;
-
- case IDM_FILE_EXIT:
- /*
- * Close the viewer.
- */
- SendMessage(window, WM_CLOSE, 0, 0L);
- break;
-
- case IDM_FILE_MRUFILE:
- case IDM_FILE_MRUFILE + 1:
- case IDM_FILE_MRUFILE + 2:
- case IDM_FILE_MRUFILE + 3:
- if (LoadObject(window, MRUFiles[item - IDM_FILE_MRUFILE]))
- RenderScene(window);
- break;
-
- case IDM_EDIT_DELETE:
- /*
- * Delete the picked clump (if there is one) but don't delete a sprite or spline.
- */
- if( (GETOBJECTTYPE(SelectedClump)==rfIsClump) || (GETOBJECTTYPE(SelectedClump)==rfIsLight)
- || (GETOBJECTTYPE(SelectedClump)==rfNoMoveClump) || (GETOBJECTTYPE(SelectedClump)==rfIsSprite))
- {
- if (SelectedClump != NULL)
- {
- DestroyClumpObj(SelectedClump);
- DeselectClump(window);
- RenderScene(window);
- }
- }
- break;
-
- case IDM_SCENE_NEW:
- /*
- * Ensure the user really wishes to discard this scene and its
- * contents.
- */
- if (MessageBox(window, "Discard this 3D Scene?", WINDOWTITLE,
- MB_YESNO | MB_APPLMODAL | MB_ICONQUESTION) == IDYES)
- {
- CreateNewScene(window);
- }
- break;
-
- case IDM_SCENE_BACKGROUNDCOLOR:
- case IDM_BACKGROUNDPOPUP_COLOR:
- /*
- * Change the background color of the world.
- */
- dialogProc = MakeProcInstance(ColorDlgProc, AppInstance);
- RwGetCameraBackColor(Camera, &color);
- if (DialogBoxParam(AppInstance, MAKEINTRESOURCE(IDD_COLORPICKER),
- window, dialogProc, (LPARAM)&color) == IDOK)
- {
- /*
- * Change the background camera's background color and re-render.
- */
- SettingsChanged = TRUE;
- BackgroundColor = RGBToColorRef(&color);
- RwSetCameraBackColorStruct(Camera, &color);
- RwInvalidateCameraViewport(Camera);
- RenderScene(window);
- }
- FreeProcInstance(dialogProc);
- break;
-
- case IDM_CAMERA_ELEVATIONVIEW:
- case IDM_CAMERA_RESET:
- /*
- * Reset the camera's viewing position.
- */
- ResetCamera(Camera);
- RenderScene(window);
- break;
-
- case IDM_CAMERA_PLANVIEW:
- /*
- * Put the camera in plan view, i.e., looking down.
- */
- RwSetCameraPosition(Camera, CREAL(0.0), DEFAULTCAMERADISTANCE, CREAL(0.0));
- RwPointCamera(Camera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
- RwSetCameraLookUp(Camera, CREAL(0.0), CREAL(0.0), CREAL(-1.0));
- RenderScene(window);
- break;
-
- case IDM_CAMERA_SIDEVIEW:
- /*
- * Put the camera in side view.
- */
- RwSetCameraPosition(Camera, DEFAULTCAMERADISTANCE, CREAL(0.0), CREAL(0.0));
- RwPointCamera(Camera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
- RwSetCameraLookUp(Camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
- RenderScene(window);
- break;
-
- case IDM_LIGHT_NEWDIRECTIONAL:
- light = CreateLightObj(rwDIRECTIONAL);
- if (light != NULL)
- {
- SetLightObjVisibleState(light, (ShowLights ? rwON : rwOFF));
- AddLightObjToScene(Scene, light);
- RenderScene(window);
- }
- else
- {
- MessageBox(window,
- "Could not create the RenderWare light",
- WINDOWTITLE, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
- }
- break;
-
- case IDM_LIGHT_NEWPOINT:
- light = CreateLightObj(rwPOINT);
- if (light != NULL)
- {
- SetLightObjVisibleState(light, (ShowLights ? rwON : rwOFF));
- AddLightObjToScene(Scene, light);
- RenderScene(window);
- }
- else
- {
- MessageBox(window,
- "Could not create the RenderWare light",
- WINDOWTITLE, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
- }
- break;
-
- case IDM_LIGHT_NEWCONICAL:
- light = CreateLightObj(rwCONICAL);
- if (light != NULL)
- {
- SetLightObjVisibleState(light, (ShowLights ? rwON : rwOFF));
- AddLightObjToScene(Scene, light);
- RenderScene(window);
- }
- else
- {
- MessageBox(window,
- "Could not create the RenderWare light",
- WINDOWTITLE, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
- }
- break;
-
- case IDM_OPTIONS_SHOWLIGHTS:
- if (ShowLights)
- {
- /*
- * If the menu item is currently checked then lights are shown so turn them off and
- * uncheck the menu.
- */
- ShowLights = FALSE;
- RwForAllLightsInSceneInt(Scene, (RwLightFuncInt)SetLightObjVisibleState, rwOFF);
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else
- {
- /*
- * If the menu item is currently unchecked then lights are not shown so turn them on and
- * check the menu.
- */
- ShowLights = TRUE;
- RwForAllLightsInSceneInt(Scene, (RwLightFuncInt)SetLightObjVisibleState, rwON);
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_SHOWLIGHTS, MF_BYCOMMAND | MF_CHECKED);
- }
- SettingsChanged = TRUE;
- RenderScene(window);
- break;
-
- case IDM_OPTIONS_SHOWHIGHLIGHT:
- if (ShowHighlight)
- {
- /*
- * We are currently showing highlights. So turn the highlight off and
- * uncheck the menu item.
- */
- ShowHighlight = FALSE;
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_SHOWHIGHLIGHT, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else
- {
- /*
- * We are currently not showing highlights. So turn the highlight on and
- * check the menu item.
- */
- ShowHighlight = TRUE;
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_SHOWHIGHLIGHT, MF_BYCOMMAND | MF_CHECKED);
- }
- SettingsChanged = TRUE;
- RenderScene(window);
- break;
-
- case IDM_OPTIONS_PLAYMOVIES:
- if (PlayMovies)
- {
- /*
- * We are currently playing movies (multi-frame textures). So turn
- * the playing off and uncheck the menu item.
- */
- PlayMovies = FALSE;
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_PLAYMOVIES, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else
- {
- /*
- * We currently are not playing movies (multi-frame textures). So turn
- * the playing on and check the menu item.
- */
- PlayMovies = TRUE;
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_PLAYMOVIES, MF_BYCOMMAND | MF_CHECKED);
- }
- SettingsChanged = TRUE;
- break;
-
-
- case IDM_OPTIONS_MOMENTUM:
- if (Momentum)
- {
- /*
- * We are currently have object momentum. So turn it off and uncheck
- * the menu item.
- */
- Momentum = FALSE;
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_MOMENTUM, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else
- {
- /*
- * We are currently don't have object momentum. So turn it on and check
- * the menu item.
- */
- Momentum = TRUE;
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_MOMENTUM, MF_BYCOMMAND | MF_CHECKED);
- }
- SettingsChanged = TRUE;
- break;
-
- case IDM_OPTIONS_CENTERBACKDROP:
- if (CenterBackdrop)
- {
- /*
- * We are currently a centered backdrop. So turn it off and uncheck
- * the menu item.
- */
- CenterBackdrop = FALSE;
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_CENTERBACKDROP, MF_BYCOMMAND | MF_UNCHECKED);
- }
- else
- {
- /*
- * We are currently don't have a centered backdrop. So turn it on and check
- * the menu item.
- */
- CenterBackdrop = TRUE;
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_CENTERBACKDROP, MF_BYCOMMAND | MF_CHECKED);
- }
- UpdateCameraBackdropPosition(Camera);
- RenderScene(window);
- SettingsChanged = TRUE;
- break;
-
- case IDM_OPTIONS_SEARCHPATH:
- /* Display the search path box */
- dialogProc = MakeProcInstance(SearchPathDlgProc, AppInstance);
- DialogBox(AppInstance, MAKEINTRESOURCE(IDD_SEARCHPATH), window, dialogProc);
- FreeProcInstance(dialogProc);
- break;
-
- case IDM_CLUMP_RESET:
- case IDM_CLUMPPOPUP_RESET:
- /*
- * Reset the clump to its default position, orientation and scaling.
- */
- RwPushScratchMatrix();
- RwIdentityMatrix(RwScratchMatrix());
- RwTransformClump(SelectedClump, RwScratchMatrix(), rwREPLACE);
- RwTransformClumpJoint(SelectedClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- RenderScene(window);
- break;
-
- case IDM_CAMERA_MOVETO:
- case IDM_LIGHTPOPUP_MOVETO:
- case IDM_CLUMPPOPUP_MOVETO:
- /*
- * Alight the camera with the position and orientation of the given object.
- */
- RwPushScratchMatrix();
- RwGetClumpLTM(SelectedClump, RwScratchMatrix());
- RwTransformCamera(Camera, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- RenderScene(window);
- break;
-
- case IDM_CAMERA_LOOKAT:
- case IDM_LIGHTPOPUP_LOOKAT:
- case IDM_CLUMPPOPUP_LOOKAT:
- /*
- * Make the camera look at the picked object.
- */
- RwGetClumpOrigin(SelectedClump, &point);
- RwPointCamera(Camera, point.x, point.y, point.z);
- RenderScene(window);
- break;
-
- case IDM_EDIT_DUPLICATE:
- case IDM_LIGHTPOPUP_DUPLICATE:
- case IDM_CLUMPPOPUP_DUPLICATE:
- /*
- * Duplicate the selected object (which may be a clump
- * or a light and the clump which represents it).
- */
- oldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
- newClump = DuplicateClumpObj(SelectedClump);
- SetCursor(oldCursor);
- if (newClump != NULL)
- {
- /*
- * Move the new clump slightly (an arbitrary amount) to
- * the right and down (in camera space) so the new and
- * old objects don't occupy the same space.
- */
- RwGetCameraLookRight(Camera, &right);
- right.x = RMul(CREAL(0.2), right.x);
- right.y = RMul(CREAL(0.2), right.y);
- right.z = RMul(CREAL(0.2), right.z);
- RwGetCameraLookUp(Camera, &up);
- up.x = RMul(CREAL(-0.2), up.x);
- up.y = RMul(CREAL(-0.2), up.y);
- up.z = RMul(CREAL(-0.2), up.z);
- RwPushScratchMatrix();
- RwTranslateMatrix(RwScratchMatrix(), right.x, right.y, right.z, rwREPLACE);
- RwTranslateMatrix(RwScratchMatrix(), up.x, up.y, up.z, rwPOSTCONCAT);
- RwTransformClump(newClump, RwScratchMatrix(), rwPOSTCONCAT);
-
- if (ISCLUMPLIGHT(newClump))
- {
- light = GETCLUMPLIGHT(newClump);
- SetLightObjVisibleState(light, (ShowLights ? rwON : rwOFF));
-
- /*
- * If the clump is the representation of a light reposition
- * the light to match the new position of the clump.
- */
- RwGetClumpLTM(newClump, RwScratchMatrix());
- RwTransformLight(light, RwScratchMatrix(), rwREPLACE);
- }
- RwPopScratchMatrix();
- RenderScene(window);
- }
- else
- {
- MessageBox(window,
- "Could not duplicate the RenderWare object",
- WINDOWTITLE, MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
- }
- break;
-
- case IDM_LIGHTPOPUP_DELETE:
- case IDM_CLUMPPOPUP_DELETE:
- /*
- * Delete the picked clump. If the picked clump is the
- * representation of a light, delete the associated
- * light.
- */
- DestroyClumpObj(SelectedClump);
- DeselectClump(window);
- RenderScene(window);
- break;
-
-
- case IDM_LIGHTPOPUP_PROPERTIES:
- case IDM_LIGHT_PROPERTIES:
- /*
- * Display the light properties dialog.
- */
- dialogProc = MakeProcInstance(LightPropsDlgProc, AppInstance);
- if (DialogBoxParam(AppInstance, MAKEINTRESOURCE(IDD_LIGHTPROPS),
- window, dialogProc, (LPARAM)GETCLUMPLIGHT(SelectedClump)) == IDOK)
- RenderScene(window);
- FreeProcInstance(dialogProc);
- break;
-
- case IDM_CLUMPPOPUP_PROPERTIES:
- case IDM_CLUMP_PROPERTIES:
- /*
- * Display the clump properties dialog.
- */
- dialogProc = MakeProcInstance(ClumpPropsDlgProc, AppInstance);
- DialogBoxParam(AppInstance, MAKEINTRESOURCE(IDD_CLUMPPROPS),
- window, dialogProc, (LPARAM)SelectedClump);
- FreeProcInstance(dialogProc);
- break;
-
- case IDM_SCENE_BACKDROPDELETE:
- case IDM_BACKGROUNDPOPUP_DELETE:
- /*
- * Delete the camera's backdrop (if there is one).
- */
- if (RwGetCameraBackdrop(Camera) != NULL)
- {
- RwDestroyRaster(RwGetCameraBackdrop(Camera));
- RwSetCameraBackdrop(Camera, NULL);
- EnableMenuItem(GetMenu(window), IDM_SCENE_BACKDROPDELETE, MF_BYCOMMAND | MF_GRAYED);
- BackdropFileName[0] = '\0';
- SettingsChanged = TRUE;
- RenderScene(window);
- }
- break;
-
- case IDM_HELP_ABOUT:
- /*
- * Display the about box.
- */
- dialogProc = MakeProcInstance(AboutBoxDlgProc, AppInstance);
- DialogBox(AppInstance, MAKEINTRESOURCE(IDD_ABOUTBOX), window, dialogProc);
- FreeProcInstance(dialogProc);
- break;
-
- }
- }
-
- /**********************************************************************/
-
- /*
- * Handle MS Window's timer expiry. This function will perform any
- * animation actions necessary, including spinning clumps and animating
- * textures.
- */
- static void
- OnTimer(HWND window)
- {
- BOOL render = FALSE;
- RwPolygon3d *myPoly;
- RwMaterial *myMaterial=RwCreateMaterial();
- RwInt32 rate;
-
- /* ********************************************** surface animation ************************************* */
- // If surface is on, then change the surface of the selected clump
- if(rfSurf.Ambient) { // update the ambient reflection coefficient
- RwForAllPolygonsInClumpReal(SelectedClump, RwSetPolygonAmbient, rfSurf.vAmbient);
- rfSurf.vAmbient += rfSurf.AmbientInc; if(rfSurf.vAmbient>=CREAL(1.0)) rfSurf.vAmbient=CREAL(0.0);
- render = TRUE;
- }
- if(rfSurf.Diffuse) { // update the diffuse reflection coefficient
- RwForAllPolygonsInClumpReal(SelectedClump, RwSetPolygonDiffuse, rfSurf.vDiffuse);
- rfSurf.vDiffuse += rfSurf.DiffuseInc; if(rfSurf.vDiffuse>=CREAL(1.0)) rfSurf.vDiffuse=CREAL(0.0);
- render = TRUE;
- }
- if(rfSurf.Specular) { // update the specular reflection coefficient
- RwForAllPolygonsInClumpReal(SelectedClump, RwSetPolygonSpecular, rfSurf.vSpecular);
- rfSurf.vSpecular += rfSurf.SpecularInc; if(rfSurf.vSpecular>=CREAL(1.0)) rfSurf.vSpecular=CREAL(0.0);
- render = TRUE;
- }
- if(rfSurf.MatAnimate) { // update the ambient reflection coefficient of the tagged polygon of the selected clump
- myPoly = RwFindTaggedPolygon(SelectedClump,WINDOWTAG);
- myMaterial = RwGetPolygonMaterial(myPoly);
- if(myPoly!=NULL) {
- RwSetMaterialAmbient(myMaterial,rfSurf.vAmbient);
- rfSurf.vAmbient += rfSurf.AmbientInc; if(rfSurf.vAmbient>=CREAL(1.0)) rfSurf.vAmbient=CREAL(0.0);
- render = TRUE;
- }
- }
-
- // if an object is traveling the spline then update its location
- if(TravelSpline) {
- coaster->t = RAdd(coaster->t,coaster->tDelta); // advance to next spline locatin
- PositionObjectOnSpline(coaster,SelectedClump);
- render = TRUE;
- }
-
-
- /*
- * Determine if there is a clump to spin (we also disable the spin
- * if the mouse is being dragged).
- */
- if (Momentum && SpinClump && (MouseMoveMode == mmNoAction))
- {
- /*
- * Spin the last clump picked by the last computed spin matrix.
- */
- RwTransformClumpJoint(SelectedClump, SpinMatrix, rwPOSTCONCAT);
- render = TRUE;
-
- if ((FrameNumber++ & 0x7f) == 0)
- {
- /*
- * Every 128 frames (a somewhat arbitrary frequency) we call
- * RwOrthoNormalizeMatrix() on the clump's joint matrix to
- * correct any errors which may have crept into it during
- * successive matrix concatenations. This is necessary due
- * to the inevitable accuracy limitations of fixed-point
- * numbers. It is unlikely that this action will be necessary
- * in your own applications unless you perform a very large
- * number of incremental rotation matrix concatenations (as
- * is done here). If this is the case with your application,
- * periodic use of RwOrthoNormalizeMatrix() will ensure
- * that these rounding errors will be eliminated.
- *
- * We call RwOrthoNormalizeMatrix() in the floating-point
- * version of RwView as well, as it is not a particularly
- * expensive operation and the same problems of rounding
- * errors in matrices can occur when using floating-point.
- * Although they are more uncommon.
- */
- RwPushScratchMatrix();
- RwGetClumpJointMatrix(SelectedClump, RwScratchMatrix());
- RwOrthoNormalizeMatrix(RwScratchMatrix(), RwScratchMatrix());
- RwTransformClumpJoint(SelectedClump, RwScratchMatrix(), rwREPLACE);
- RwPopScratchMatrix();
- }
- }
-
-
- // if texture animation is enabled then
- if (PlayMovies)
- {
- rate = (int) accumulatedRate; // new rate is the integer porition of the accumulated rate
- accumulatedRate += textureRate; // add the texture rate increment to the accumulated rate
- if((int) accumulatedRate > rate) // only upgrade when integer overflow occurs
- {
- RwForAllNamedTextures(RwTextureNextFrame); // do for all named textures
- render = TRUE;
- }
- }
-
- if (render)
- {
- /*
- * Re-render the scene if necessary.
- */
- RenderScene(window);
- }
- }
-
-
-
-
-
- /**********************************************************************/
-
- /*
- * The window procedure for this application's window.
- */
- LRESULT CALLBACK
- MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
- {
- POINT point;
- #if defined(WIN32)
- POINTS points;
- #endif
-
- switch (message)
- {
- case WM_CREATE:
- /*
- * Create the pop-up menus.
- */
- if (!CreatePopupMenus())
- return -1L;
-
- /*
- * Ensure the menu items are in the correct state.
- */
- EnableMenuItem(GetMenu(window), IDM_SCENE_BACKDROPDELETE,
- MF_BYCOMMAND | (RwGetCameraBackdrop(Camera) != NULL ? MF_ENABLED : MF_GRAYED));
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_SHOWHIGHLIGHT,
- MF_BYCOMMAND | (ShowHighlight ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_SHOWLIGHTS,
- MF_BYCOMMAND | (ShowLights ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_PLAYMOVIES,
- MF_BYCOMMAND | (PlayMovies ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_MOMENTUM,
- MF_BYCOMMAND | (Momentum ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(GetMenu(window), IDM_OPTIONS_CENTERBACKDROP,
- MF_BYCOMMAND | (CenterBackdrop ? MF_CHECKED : MF_UNCHECKED));
-
- AppendMRUFileMenuItems(window);
-
- /*
- * There is not initially selected clump.
- */
- DeselectClump(window);
-
- /*
- * Clumps are loaded into the scene by drag and drop.
- * So make this window a drop site.
- */
- DragAcceptFiles(window, TRUE);
-
- /*
- * In this application, 3D animation is driven by window's
- * timer messages, so turn a timer on.
- */
- SetTimer(window, 1, 20, NULL);
-
- // *********************************** initialize the animating materials variables ************************
- rfSurf.vAmbient = CREAL(0.0); rfSurf.vDiffuse=CREAL(0.0); rfSurf.vSpecular=CREAL(0.0);
- rfSurf.AmbientInc = CREAL(0.01); rfSurf.DiffuseInc=CREAL(0.01); rfSurf.SpecularInc=CREAL(0.01);
- rfReadSprite=FALSE; // use BMP as backdrop not sprites
- rfBirdsEye=FALSE; // don't display bird's eye sprite
- rfPaletteView=FALSE; // don't display palette sprite
- RwSetClumpState(PaletteSprite, rwOFF); // start with off
- rfSurf.Ambient=FALSE; // don't animate ambient
- rfSurf.Diffuse=FALSE; // don't diffuse ambient
- rfSurf.Specular=FALSE; // don't specular ambient
- rfSurf.MatAnimate=FALSE; // don't animate ambient of tagged polygon
-
- // *********************************************** initialize debugging ***************************************
- rfDebug.Severity=rwWARNING;
- rfDebug.Message=rwDISABLE;
- rfDebug.Assertion=rwENABLE;
- rfDebug.Script=rwDISABLE;
- rfDebug.Output=rwENABLE;
- rfDebug.Trace=rwENABLE;
-
- // *********************************************** initialize the transformations *******************************
- // rotation about the Y axis in 15 degrees repreating 10 times according to the world coordiante system
- rfScale.x=CREAL(1.0); rfScale.y=CREAL(1.0); rfScale.z=CREAL(1.0); rfScale.combine=rwPOSTCONCAT;
-
- // rotation about the Y axis in 15 degrees repreating 10 times according to the world coordiante system
- rfTran.x=CREAL(0.0); rfTran.y=CREAL(0.0); rfTran.z=CREAL(0.0); rfTran.combine=rwPOSTCONCAT;
-
- // rotation about the Y axis in 15 degrees repreating 10 times according to the world coordiante system
- rfRot.x=CREAL(0.0); rfRot.y=CREAL(1.0); rfRot.z=CREAL(0.0); rfRot.val=15; rfRot.repeat=10; rfRot.combine=rwPOSTCONCAT;
-
- // pan, revolve and tilt is set to move in 15 degree increments repeating 10 times
- rfLoc.val=15; rfLoc.repeat=10;
-
- // camera is set to move in 0.2 increments repeating 10 times
- rfCam.val=CREAL(0.2); rfCam.repeat=10;
-
- // figure out the display depth
- DisplayDepth = Is8or16bpp(window);
-
- //************************************************ Spline **********************************************************
- HideSpline = FALSE;
- CheckMenuItem(GetMenu(window), IDM_HIDESPLINETRACK, MF_BYCOMMAND | MF_UNCHECKED);
- HideControlPoints = FALSE;
- CheckMenuItem(GetMenu(window), IDM_HIDESPLINECONTROLPOINTS, MF_BYCOMMAND | MF_UNCHECKED);
- UseSmoothEnd = FALSE;
- CheckMenuItem(GetMenu(window), IDM_SMOOTHEND, MF_BYCOMMAND | MF_UNCHECKED);
- TravelSpline = FALSE;
- CheckMenuItem(GetMenu(window), IDM_MOVEOBJECTONSPLINE, MF_BYCOMMAND | MF_UNCHECKED);
- return 0L;
-
- #if defined(CONSTRAIN_SIZE)
- case WM_GETMINMAXINFO:
- #if defined(__WINDOWS_386__)
- /*
- * The MK_FP32() is necessary under Watcom to convert
- * an Windows 16 bit far pointer to a 32 bit far pointer.
- */
- OnGetMinMaxInfo((MINMAXINFO FAR *)MK_FP32((void*)lParam));
- #else
- OnGetMinMaxInfo((MINMAXINFO FAR *)lParam);
- #endif
- return 0L;
- #endif
-
- case WM_SIZE:
- if (RwIsOpen)
- OnSize(window, LOWORD(lParam), HIWORD(lParam));
- return 0L;
-
- case WM_MEASUREITEM:
- #if defined(__WINDOWS_386__)
- /*
- * The MK_FP32() is necessary under Watcom to convert
- * an Windows 16 bit far pointer to a 32 bit far pointer.
- */
- OnMeasureItem(window, (MEASUREITEMSTRUCT FAR *)MK_FP32((void*)lParam));
- #else
- OnMeasureItem(window, (MEASUREITEMSTRUCT FAR *)lParam);
- #endif
- return 0L;
-
- case WM_DRAWITEM:
- #if defined(__WINDOWS_386__)
- /*
- * The MK_FP32() is necessary under Watcom to convert
- * an Windows 16 bit far pointer to a 32 bit far pointer.
- */
- OnDrawItem(window, (DRAWITEMSTRUCT FAR *)MK_FP32((void*)lParam));
- #else
- OnDrawItem(window, (DRAWITEMSTRUCT FAR *)lParam);
- #endif
- return 0L;
-
- case WM_DROPFILES:
- if (RwIsOpen)
- {
- /*
- * Turn the timer off for the duration of the drop
- */
- KillTimer(window, 1);
-
- OnDrop(window, (HDROP)wParam);
- /*
- * Turn the timer back on to start the animations back
- * up.
- */
- SetTimer(window, 1, 20, NULL);
- }
- return 0L;
-
- case WM_LBUTTONDOWN:
- if (RwIsOpen)
- {
- #if defined(WIN32)
- points = MAKEPOINTS(lParam);
- POINTSTOPOINT(point, points);
- #else
- point = MAKEPOINT(lParam);
- #endif
- OnLButtonDown(window, &point, wParam);
- }
- return 0L;
-
- case WM_RBUTTONDOWN:
- if (RwIsOpen)
- {
- #if defined(WIN32)
- points = MAKEPOINTS(lParam);
- POINTSTOPOINT(point, points);
- #else
- point = MAKEPOINT(lParam);
- #endif
- OnRButtonDown(window, &point, wParam);
- }
- return 0L;
-
- case WM_MOUSEMOVE:
- if (RwIsOpen)
- {
- if (MouseMoveMode != mmNoAction)
- {
- #if defined(WIN32)
- points = MAKEPOINTS(lParam);
- POINTSTOPOINT(point, points);
- #else
- point = MAKEPOINT(lParam);
- #endif
- OnMouseMove(window, &point);
- }
- }
- return 0L;
-
- case WM_LBUTTONUP:
- if (RwIsOpen)
- OnLButtonUp();
- return 0L;
-
- case WM_RBUTTONUP:
- if (RwIsOpen)
- OnRButtonUp();
- return 0L;
-
- case WM_PAINT:
- if (RwIsOpen)
- OnPaint(window);
- return 0L;
-
- case WM_COMMAND:
- if (RwIsOpen)
- {
- #ifdef WIN32
- HWND hwndCtl = (HWND) lParam;
- WORD wID = LOWORD(wParam);
- WORD wNotifyCode = HIWORD(wParam);
- #else
- HWND hwndCtl = (HWND) LOWORD(lParam);
- WORD wID = wParam;
- WORD wNotifyCode = HIWORD(lParam);
- #endif
- /*
- * Turn the timer off for the duration of the command
- * action.
- */
- KillTimer(window, 1);
-
- if (hwndCtl == (HWND)0)
- OnMenu(window, wID);
-
- /*
- * Turn the timer back on to start the animations back
- * up.
- */
- SetTimer(window, 1, 20, NULL);
- }
- return 0L;
-
- case WM_TIMER:
- if (RwIsOpen)
- OnTimer(window);
- return 0L;
-
- case WM_CLOSE:
- /*
- * If the settings have changed then ask the user if she or he
- * wishes to save them.
- */
- if (SettingsChanged)
- {
- if (MessageBox(window, "Save the new 3D Object Viewer settings?",
- WINDOWTITLE, MB_YESNO | MB_APPLMODAL | MB_ICONQUESTION) == IDYES)
- WriteSettings(TRUE);
- else
- WriteSettings(FALSE);
- }
- else
- {
- WriteSettings(FALSE);
- }
- DestroyWindow(window);
- return 0L;
-
- case WM_DESTROY:
- /*
- * The window is going away so it is no longer a drop site.
- */
- DragAcceptFiles(window, FALSE);
-
- /*
- * Turn the timer off.
- */
- KillTimer(window, 1);
-
- /*
- * Destroy the pop-up menus.
- */
- DestroyPopupMenus();
-
- /*
- * Quit message handling.
- */
- PostQuitMessage(0);
- return 0L;
- }
-
- /*
- * Let Windows handle all other messages.
- */
- return DefWindowProc(window, message, wParam, lParam);
- }
-
- /**********************************************************************/
-
- /*
- * Windows application entry point.
- */
- int PASCAL
- WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine, int cmdShow)
- {
- MSG msg;
- HWND window;
- HACCEL accel;
-
- /*
- * Cache the instance handle in a global variable for later use.
- */
- AppInstance = instance;
-
- if (prevInstance)
- {
- /*
- * Only allow one viewer application to run at any one time.
- */
- MessageBox(NULL,
- "The RenderWare 3D Object Viewer is already running."
- "Only a single 3D Object Viewer can run at any one time",
- WINDOWTITLE, MB_OK | MB_APPLMODAL | MB_ICONSTOP);
- return FALSE;
- }
-
- /*
- * Register the window class.
- */
- if (!InitApplication(instance))
- return FALSE;
-
- /*
- * Read the initial settings from the initialization file.
- */
- ReadSettings();
-
- /*
- * Create the window.
- */
- window = InitInstance(instance);
- if (window == NULL)
- return FALSE;
-
- /*
- * Initialize the 3D (RenderWare) components of the app.
- */
- if (!Init3D(window))
- {
- DestroyWindow(window);
- return FALSE;
- }
-
- /*
- * Parse any command line parameters.
- */
- if (!ReadFromCommandLine(window, cmdLine))
- {
- TidyUp3D();
- DestroyWindow(window);
- return FALSE;
- }
-
- /*
- * Show the window, and refresh it.
- */
- ShowWindow(window, cmdShow);
- UpdateWindow(window);
-
- /*
- * Load the accelerators.
- */
- accel = LoadAccelerators(AppInstance, MAKEINTRESOURCE(IDR_ACCELERATOR));
-
- /*
- * Enter the message processing loop.
- */
- while (GetMessage(&msg, NULL, 0U, 0U))
- {
- if (!TranslateAccelerator(window, accel, &msg))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- /*
- * Tidy up the 3D (RenderWare) components of the application.
- */
- TidyUp3D();
-
- return msg.wParam;
- }
-
-
-