home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Learn 3D Graphics Programming on the PC
/
Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso
/
rwwin
/
rwknight.c_
/
rwknight.bin
Wrap
Text File
|
1995-11-14
|
28KB
|
973 lines
/**********************************************************************
*
* File : rwknight.c
*
* Abstract :
*
* 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. 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.
*
**********************************************************************/
/**********************************************************************
*
* Header files.
*
**********************************************************************/
#include <windows.h>
#include <mmsystem.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "rwlib.h"
#include "rwwin.h"
#include "palette.h"
#include "common.h"
#include "animate.h"
#define DEFINE_GLOBAL
#include "knight.h"
#undef DEFINE_GLOBAL
/**********************************************************************
*
* Application constants.
*
**********************************************************************/
/*
* Class name for the MS Window's window class.
*/
#define RWKNIGHT_CLASS_NAME "RwKnightClass"
/*
* Error dialog box title.
*/
#define ERROR_DIALOG_TITLE "RenderWare Knight Error"
/*
* Maximum size of the viewer's window.
*/
#define MAXIMUM_WINDOW_WIDTH 640
#define MAXIMUM_WINDOW_HEIGHT 480
#define DEFAULT_WINDOW_WIDTH 320
#define DEFAULT_WINDOW_HEIGHT 240
#define MAXIMUM_CAMERA_WIDTH (MAXIMUM_WINDOW_WIDTH/2)
#define MAXIMUM_CAMERA_HEIGHT (MAXIMUM_WINDOW_HEIGHT/2)
/**********************************************************************
*
* Forward functions.
*
**********************************************************************/
extern LRESULT CALLBACK
MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam);
/**********************************************************************
*
* Type definitions.
*
**********************************************************************/
/*
* This enumerated type tells us what kind of action should be taken
* on mouse events.
*/
typedef enum
{
MMNoAction,
MMPanCamera,
MMPanLight
} MMMode;
/**********************************************************************
*
* Application global variables.
*
**********************************************************************/
HANDLE AppInstance;
/*
* This variable tells us what kind of action to take on a mouse move.
* The action depends on the object that was picked when the mouse button
* went down, and on the selection of virtual keys that were depressed at
* that time. By default no action is taken on mouse move.
*/
static MMMode MouseMoveMode = MMNoAction;
/*
* Global variables used to remember the last mouse X and Y coordinates
* when involved in a pan, zoom, drag or spin.
*/
static int LastX;
static int LastY;
static int Stretching = FALSE;
static int MaxWindowWidth = DEFAULT_WINDOW_WIDTH;
static int MaxWindowHeight = DEFAULT_WINDOW_HEIGHT;
/*
* This flag indicates whether the 3D components of the application
* have been successfully initialized as yet. It is used to guard
* the message loop handler functions from being invoked before the
* 3D components of the application are successfully initialized.
*/
static BOOL ThreeDInitialized = FALSE;
/**********************************************************************
*
* Functions.
*
**********************************************************************/
/**********************************************************************/
void SetMaxValues(void)
{
if (Stretching)
{
MaxWindowWidth = MAXIMUM_WINDOW_WIDTH;
MaxWindowHeight = MAXIMUM_WINDOW_HEIGHT;
}
else
{
MaxWindowWidth = MAXIMUM_CAMERA_WIDTH;
MaxWindowHeight = MAXIMUM_CAMERA_HEIGHT;
}
}
/**********************************************************************/
/*
* Perform any necessary MS Windows application initialization. Basically,
* this means registering the window class for this application.
*/
static BOOL
InitApplication(HANDLE instance)
{
WNDCLASS windowClass;
windowClass.style = CS_BYTEALIGNWINDOW;
windowClass.lpfnWndProc = (WNDPROC)MainWndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = instance;
windowClass.hIcon = LoadIcon(instance, "RW_ICON");
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = NULL;
windowClass.lpszMenuName = MAKEINTRESOURCE(KNIGHT_MENU);
windowClass.lpszClassName = RWKNIGHT_CLASS_NAME;
return RegisterClass(&windowClass);
}
/**********************************************************************/
/*
* Perform any necessary initialization for this instance of the
* application. This simply means creating the application's main
* window.
*/
static HWND
InitInstance(HANDLE instance)
{
return CreateWindow(RWKNIGHT_CLASS_NAME, "",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT,
NULL, NULL, instance, NULL);
}
/**********************************************************************/
/*
* 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)
{
#ifndef WIN32
RwOpenArgument args;
#endif
int i;
RwRaster *Raster;
char buffer[64];
if (!CheckDisplayDepth(window))
return(FALSE);
#ifndef WIN32
args.option = rwWINUSEWING;
if (!RwOpenExt("MSWindows", NULL, 1, &args))
#else
if (!RwOpen("MSWindows", NULL))
#endif
{
MessageBox(window, "Error opening the RenderWare library",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return FALSE;
}
GetModuleFileName(AppInstance, buffer, sizeof(buffer));
i = strlen(buffer);
while(buffer[i] != '\\')
i--;
buffer[i+1] = 0;
strcat(buffer, "TEXTURES");
RwSetShapePath(buffer, rwREPLACE);
buffer[i+1] = 0;
strcat(buffer, "SCRIPTS");
RwSetShapePath(buffer, rwPOSTCONCAT);
RwSetShapePath(".", rwPOSTCONCAT);
/*
* Label the window with information about the version of
* RenderWare being used. Its rather unlikely that
* RwGetSystemInfo() or RwGetDeviceInfo() will fail so we ignore its
* return value.
*/
SetWindowText(window, "RenderWare Animated Knight");
MainCamera = RwCreateCamera(MAXIMUM_CAMERA_WIDTH, MAXIMUM_CAMERA_HEIGHT, NULL);
if (!MainCamera)
{
/*
* 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 RenderWare camera",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
else
{
MessageBox(window, "Error creating the Main RenderWare camera",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
RwClose();
return FALSE;
}
FlyCamera = RwCreateCamera(MAXIMUM_CAMERA_WIDTH, MAXIMUM_CAMERA_HEIGHT, NULL);
if (!FlyCamera)
{
MessageBox(window, "Error creating the Flying RenderWare camera",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
RwDestroyCamera(MainCamera);
RwClose();
return FALSE;
}
Camera = MainCamera;
/* load the palette */
CheckAndReadPalette("rwknight.pal");
/* now add the backdrop */
Raster = RwReadRaster("cast256.bmp", 0L);
if (Raster)
{
/* Destroy the existing backdrop raster (if any). */
if (RwGetCameraBackdrop(MainCamera))
RwDestroyRaster(RwGetCameraBackdrop(MainCamera));
/* Set the new backdrop raster. */
RwSetCameraBackdrop(MainCamera, Raster);
RwSetCameraBackdrop(FlyCamera, Raster);
}
/*
* By default, the camera lies on the X-Z plane and points down Z
* into the screen. We shall retain the camera's orientation, but move
* the camera DEFAULT_CAMERA_DISTANCE units down Z away from the screen.
*/
RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), CAMERA_DISTANCE);
RwSetCameraViewwindow(MainCamera, CREAL(0.4), CREAL(0.4));
RwSetCameraViewwindow(FlyCamera, CREAL(0.4), CREAL(0.4));
/*
* Create a scene which will contain the clumps to be rendered and the
* light or lights illuminating those clumps . In this very simple
* application it would be perfectly acceptable to use the default scene
* (as returned by RwDefaultScene()) for rendering. However, it is good
* practice to always create a scene which will be used for your rendering
* and only use the default scene as a bag for currently unused clumps and
* lights.
*/
Scene = RwCreateScene();
if (!Scene)
{
RwDestroyCamera(FlyCamera);
RwDestroyCamera(MainCamera);
RwClose();
MessageBox(window, "Error creating the RenderWare scene",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return FALSE;
}
/*
* Our scene will be illuminated by a directional light. The illumination
* vector of the light is (-1.0, -1.0, -1.0) and its brightness will be 1.0.
*/
Light = RwCreateLight(rwDIRECTIONAL, CREAL(-1.0), CREAL(-1.0), CREAL(-1.0),
CREAL(1.0));
if (!Light)
{
RwDestroyScene(Scene);
RwDestroyCamera(FlyCamera);
RwDestroyCamera(MainCamera);
RwClose();
MessageBox(window, "Error creating the RenderWare light",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return FALSE;
}
/*
* Add the new light to our scene.
*/
RwAddLightToScene(Scene, Light);
/*
* All the 3D components are now successfully initialized, so
* work can begin...
*/
ThreeDInitialized = TRUE;
SetCameraState(window, CAM_MAIN);
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 scene. This will destroy the contents of the scene,
* i.e. any clumps and lights in that scene. In this case destroying
* the scene will destroy the light we created in Init3D, and any
* clumps we have loaded and not already destroyed.
*/
RwDestroyScene(Scene);
/*
* Destroy the camera's backdrop (if any). Backdrops are not
* automatically destroyed by RwDestroyCamera() so we must
* manually destroy the backdrop.
*/
if (RwGetCameraBackdrop(MainCamera))
{
RwDestroyRaster(RwGetCameraBackdrop(MainCamera));
RwSetCameraBackdrop(MainCamera, NULL);
RwSetCameraBackdrop(FlyCamera, NULL);
}
/*
* Destroy the camera.
*/
RwDestroyCamera(FlyCamera);
RwDestroyCamera(MainCamera);
/*
* Close the library. This will free up any internal resources and
* textures loaded.
*/
RwClose();
}
/**********************************************************************/
/*
* Render the scene and copy it to the window and device context
* given. This function encapsulates the very common RenderWare
* for rendering and updating the display.
*/
static void
RenderScene(HWND window)
{
HDC dc;
RwBeginCameraUpdate(Camera, (void *)window);
RwClearCameraViewport(Camera);
RwRenderScene(Scene);
RenderKnight();
RwEndCameraUpdate(Camera);
dc = GetDC(window);
RwShowCameraImage(Camera, (void*)dc);
ReleaseDC(window, dc);
}
RwClump *
LoadClump(HWND window, char *fileName)
{
RwClump *clump;
char buffer[128];
clump = RwReadShape(fileName);
if (!clump)
{
/*
* The load failed. This could be because of errors in the
* script file, insufficient memory, or the file containing
* garbage. We will now examine the error code returned to
* decide whether there was a script file error (in which case
* an error will be issued to the user), whether memory was
* exhausted (a different error is issued to the user), or
* the file contained garbage (in which case we will attempt
* to load the file as a texture instead of a script).
*/
switch (RwGetError())
{
case E_RW_NOMEM:
/*
* Ran out of memory...
*/
sprintf(buffer, "Insufficient memory to load script %s",
fileName);
MessageBox(window, buffer, ERROR_DIALOG_TITLE,
MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
return NULL;
default:
/*
* On any other error we will assume there is an error in
* the script file.
*/
sprintf(buffer,
"Error reading the script file %s",
fileName);
MessageBox(window, buffer, ERROR_DIALOG_TITLE,
MB_OK | MB_ICONEXCLAMATION | MB_APPLMODAL);
return NULL;
}
}
return clump;
}
/**********************************************************************/
static void
HandleSize(HWND window, RwInt32 width, RwInt32 height)
{
RwWinOutputSize winOutputSize;
if (Stretching)
{
/* force stretching to use an exact multiple by dividing and remultiplying */
width = (width/2) * 2;
height = (height/2) * 2;
}
winOutputSize.width = width;
winOutputSize.height = height;
winOutputSize.camera = MainCamera;
RwDeviceControl(rwWINSETOUTPUTSIZE,(RwInt32)0, &winOutputSize, sizeof(winOutputSize));
winOutputSize.camera = FlyCamera;
RwDeviceControl(rwWINSETOUTPUTSIZE,(RwInt32)0, &winOutputSize, sizeof(winOutputSize));
if (Stretching)
{
width/= 2;
height/= 2;
}
/* Set the camera viewport to match the window's client area.*/
RwSetCameraViewport(MainCamera, 0, 0, width, height );
RwSetCameraViewport(FlyCamera, 0, 0, width, height );
RwGetCameraViewport(MainCamera, NULL, NULL, &width, &height );
/* Maintain the view window at a 1:1 aspect ratio. */
if ( width != 0 && height != 0 )
{
if (width >= height)
{
RwSetCameraViewwindow(MainCamera, CREAL(0.4), RMul(CREAL(0.4), RDiv(INT2REAL(height), INT2REAL(width))));
RwSetCameraViewwindow(FlyCamera, CREAL(0.4), RMul(CREAL(0.4), RDiv(INT2REAL(height), INT2REAL(width))));
}
else
{
RwSetCameraViewwindow(MainCamera, RMul(CREAL(0.4), RDiv(INT2REAL(width), INT2REAL(height))), CREAL(0.4));
RwSetCameraViewwindow(FlyCamera, RMul(CREAL(0.4), RDiv(INT2REAL(width), INT2REAL(height))), CREAL(0.4));
}
}
RwSetCameraViewport(MainCamera, 0, 0, width, height);
RwSetCameraViewport(FlyCamera, 0, 0, width, height);
RwSetCameraBackdropViewportRect(MainCamera, 0, 0, width, height);
RwSetCameraBackdropViewportRect(FlyCamera, 0, 0, width, height);
SetBackdrop(MainCamera); /* The camera has changed so reposition the backdrop */
SetBackdrop(FlyCamera);
RenderScene(window);
}
/**********************************************************************/
static void
HandleLeftButtonDown(HWND window, int x, int y)
{
POINT pos;
if (MouseMoveMode != MMNoAction)
{
SetCapture(window);
pos.x = x;
pos.y = y;
ClientToScreen(window, &pos);
LastX = pos.x;
LastY = pos.y;
}
}
/**********************************************************************/
static void
HandleRightButtonDown(HWND window, int x, int y, WPARAM vKeys)
{
POINT pos;
if (vKeys & MK_CONTROL)
{
MouseMoveMode = MMPanLight;
}
else
{
MouseMoveMode = MMPanCamera;
}
if (MouseMoveMode != MMNoAction)
{
SetCapture(window);
pos.x = x;
pos.y = y;
ClientToScreen(window, &pos);
LastX = pos.x;
LastY = pos.y;
}
}
/**********************************************************************/
static void
HandleMouseMove(HWND window, int x, int y)
{
POINT pos;
pos.x = x;
pos.y = y;
ClientToScreen(window, &pos);
/*
* MouseMoveMode tells us what kind of action to perform.
*/
switch (MouseMoveMode)
{
case MMNoAction:
break;
case MMPanCamera:
RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), -CAMERA_DISTANCE);
RwPanCamera(MainCamera, INT2REAL(LastX - pos.x));
RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), CAMERA_DISTANCE);
if (CameraState == CAM_MAIN)
SetBackdrop(MainCamera);
break;
case MMPanLight:
RwPushScratchMatrix();
RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
INT2REAL(LastX - pos.x), rwREPLACE);
RwRotateMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(0.0), CREAL(0.0),
INT2REAL(LastY - pos.y), rwPOSTCONCAT);
RwTransformLight(Light, RwScratchMatrix(), rwPOSTCONCAT);
RwPopScratchMatrix();
break;
}
if (MouseMoveMode != MMNoAction)
{
LastX = pos.x;
LastY = pos.y;
}
}
/**********************************************************************/
static void
HandleLeftButtonUp(void)
{
if (MouseMoveMode != MMNoAction)
{
MouseMoveMode = MMNoAction;
ReleaseCapture();
}
}
/**********************************************************************/
static void
HandleRightButtonUp(void)
{
if (MouseMoveMode != MMNoAction)
{
MouseMoveMode = MMNoAction;
ReleaseCapture();
}
}
/**********************************************************************/
static void
HandlePaint(HWND window)
{
HDC dc;
PAINTSTRUCT ps;
dc = BeginPaint(window, &ps);
if (Stretching)
{
ps.rcPaint.left/=2;
ps.rcPaint.top/=2;
ps.rcPaint.right/=2;
ps.rcPaint.bottom/=2;
}
RwDamageCameraViewport(Camera,
(RwInt32)ps.rcPaint.left,
(RwInt32)ps.rcPaint.top,
(RwInt32)(ps.rcPaint.right - ps.rcPaint.left),
(RwInt32)(ps.rcPaint.bottom - ps.rcPaint.top));
RwShowCameraImage(Camera, (void *)dc);
EndPaint(window, &ps);
}
/**********************************************************************/
static void
HandleTimer(HWND window)
{
AnimateScene();
AnimateCamera(window);
/*
* Re-render the scene and copy the results to the display.
*/
RenderScene(window);
}
/**************************************************************************/
void
HandleGetMinMaxInfo(MINMAXINFO FAR *minmaxinfo)
{
minmaxinfo->ptMaxSize.x = MaxWindowWidth;
minmaxinfo->ptMaxSize.y = MaxWindowHeight;
minmaxinfo->ptMaxTrackSize.x = MaxWindowWidth;
minmaxinfo->ptMaxTrackSize.y = MaxWindowHeight;
}
/**************************************************************************
About Dialogue Box Stuff
**************************************************************************/
void
DlgDrawItem(DRAWITEMSTRUCT FAR *dis)
{
HDC hdcMemory;
HBITMAP hbmplogo, hbmpOld;
BITMAP bm;
hbmplogo = LoadBitmap(AppInstance, "CRITERION_LOGO");
GetObject(hbmplogo, sizeof(BITMAP), &bm);
hdcMemory = CreateCompatibleDC(dis->hDC);
hbmpOld = SelectObject(hdcMemory, hbmplogo);
BitBlt(dis->hDC, dis->rcItem.left, dis->rcItem.top,
dis->rcItem.right - dis->rcItem.left,
dis->rcItem.bottom - dis->rcItem.top,
hdcMemory, 0, 0, SRCCOPY);
SelectObject(hdcMemory, hbmpOld);
DeleteDC(hdcMemory);
DeleteObject(hbmplogo);
}
/**********************************************************************/
BOOL CALLBACK
AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
switch(wParam)
{
case IDOK:
case IDCANCEL:
EndDialog(hDlg, 0);
return(TRUE);
}
break;
case WM_DRAWITEM:
#ifdef __WINDOWS_386__
DlgDrawItem((DRAWITEMSTRUCT FAR *)MK_FP32((void *)lParam));
#else /* __WINDOWS_386__ */
DlgDrawItem((DRAWITEMSTRUCT FAR *)lParam);
#endif /* __WINDOWS_386__ */
return(TRUE);
}
return(FALSE);
}
/**********************************************************************/
static void
HandleMenu(HWND window, WPARAM menuItem)
{
RECT rect;
switch (menuItem)
{
case ID_FILE_EXIT:
SendMessage(window, WM_CLOSE, 0, 0L);
break;
case ID_MODE_STRETCH:
CheckMenuItem(GetMenu(window), ID_MODE_STRETCH, (Stretching) ? (MF_BYCOMMAND|MF_UNCHECKED) : (MF_BYCOMMAND|MF_CHECKED));
Stretching = (Stretching) ? FALSE : TRUE;
SetMaxValues();
GetWindowRect(window, &rect);
if (Stretching)
MoveWindow(window, rect.left, rect.top,
(rect.right - rect.left) * 2,
(rect.bottom - rect.top) * 2, TRUE);
else
MoveWindow(window, rect.left, rect.top,
(rect.right - rect.left) / 2,
(rect.bottom - rect.top) / 2, TRUE);
break;
case ID_MODE_DEMO:
CheckMenuItem(GetMenu(window), ID_MODE_DEMO, (!InterActive) ? (MF_BYCOMMAND|MF_UNCHECKED) : (MF_BYCOMMAND|MF_CHECKED));
InterActive = (InterActive) ? FALSE : TRUE;
break;
case ID_MODE_KNIGHT1:
SetCameraState(window, CAM_FLY1);
break;
case ID_MODE_KNIGHT2:
SetCameraState(window, CAM_FLY2);
break;
case ID_MODE_OBSERVER:
if (CameraState == CAM_KNIGHT1)
SetCameraState(window, CAM_FLY1);
else if (CameraState == CAM_KNIGHT2)
SetCameraState(window, CAM_FLY2);
break;
case ID_HELP_ABOUT:
KillTimer(window, 1);
DialogBox(AppInstance, "ABOUT", window, MakeProcInstance(AboutDlgProc, AppInstance));
SetTimer( window, 1, 20, NULL );
break;
}
}
LRESULT CALLBACK
MainWndProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
#ifdef WIN32
POINTS point;
#else
POINT point;
#endif
switch (message)
{
case WM_COMMAND:
if (LOWORD(lParam) == 0)
HandleMenu(window, wParam);
return 0L;
case WM_CREATE:
SetTimer(window, 1, 20, NULL);
return 0L;
case WM_GETMINMAXINFO:
#ifdef __WINDOWS_386__
HandleGetMinMaxInfo((MINMAXINFO FAR *)MK_FP32((void *)lParam));
#else /* __WINDOWS_386__ */
HandleGetMinMaxInfo((MINMAXINFO FAR *)lParam);
#endif /* __WINDOWS_386__ */
break;
case WM_SIZE:
if (ThreeDInitialized)
HandleSize(window, (RwInt32)LOWORD(lParam), (RwInt32)HIWORD(lParam));
return 0L;
case WM_LBUTTONDOWN:
if (ThreeDInitialized)
{
#ifdef WIN32
point = MAKEPOINTS(lParam);
#else
point = MAKEPOINT(lParam);
#endif
HandleLeftButtonDown(window, point.x, point.y);
}
return 0L;
case WM_RBUTTONDOWN:
if (ThreeDInitialized)
{
#ifdef WIN32
point = MAKEPOINTS(lParam);
#else
point = MAKEPOINT(lParam);
#endif
HandleRightButtonDown(window, point.x, point.y, wParam);
}
return 0L;
case WM_MOUSEMOVE:
if (ThreeDInitialized)
{
if (MouseMoveMode != MMNoAction)
{
#ifdef WIN32
point = MAKEPOINTS(lParam);
#else
point = MAKEPOINT(lParam);
#endif
HandleMouseMove(window, point.x, point.y);
}
}
return 0L;
case WM_LBUTTONUP:
if (ThreeDInitialized)
HandleLeftButtonUp();
return 0L;
case WM_RBUTTONUP:
if (ThreeDInitialized)
HandleRightButtonUp();
return 0L;
case WM_PAINT:
if (ThreeDInitialized)
HandlePaint(window);
return 0L;
case WM_TIMER:
if (ThreeDInitialized)
HandleTimer(window);
return 0L;
case WM_DESTROY:
KillTimer(window, 1);
PostQuitMessage(0);
return 0L;
}
return DefWindowProc(window, message, wParam, lParam);
}
/**********************************************************************/
int PASCAL
WinMain(HANDLE instance, HANDLE prevInstance, LPSTR cmdLine, int cmdShow)
{
MSG message;
HWND window;
if (prevInstance)
{
MessageBox((HWND)0, "The RenderWare Knight Demonstration is already running...",
ERROR_DIALOG_TITLE, MB_OK | MB_APPLMODAL | MB_ICONSTOP);
return FALSE;
}
AppInstance = instance;
if (!InitApplication(instance))
{
return FALSE;
}
if (!(window = InitInstance(instance)))
{
return FALSE;
}
SetMaxValues();
if (!Init3D(window))
{
DestroyWindow(window);
return FALSE;
}
if (AllowStretching(window))
{
EnableMenuItem(GetMenu(window), ID_MODE_STRETCH, MF_ENABLED);
}
if (!LoadKnight(window, instance, Scene))
{
TidyUp3D();
DestroyWindow(window);
return FALSE;
}
AnimateKnight(1, "BOB1"); /* start the animation */
ShowWindow(window, cmdShow);
UpdateWindow(window);
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
TidyUp3D();
UnregisterClass(RWKNIGHT_CLASS_NAME, instance);
return message.wParam;
}