home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Learn 3D Graphics Programming on the PC
/
Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso
/
rwwin
/
rwwalk.c_
/
rwwalk.bin
Wrap
Text File
|
1995-11-14
|
24KB
|
836 lines
/**********************************************************************
*
* File : rwwalk.c
*
* Abstract : RenderWare Walkthrough demo. Main module
*
**********************************************************************
*
* 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) 1995 Criterion Software Ltd.
* All Rights Reserved.
*
* RenderWare is a trademark of Canon Inc.
*
************************************************************************/
/**********************************************************************
*
* Header files.
*
**********************************************************************/
#define INCLUDE_SHELLAPI_H
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "rwlib.h"
#include "status.h"
#include "common.h"
#include "resource.h"
/**********************************************************************
*
* Application constants.
*
**********************************************************************/
#if !defined(__WINDOWS_386__)
#define MK_FP32(x) (x)
#endif
/*
* Uncomment the following line to give the object's in the scene
* momentum, i.e., after they have been spun by mouse move, they will
* continue to spin by an animation facility driven by the MS Windows
* timer message.
*/
/* #define DO_MOMENTUM */
#define DEFAULT_WINDOW_WIDTH 300
#define DEFAULT_WINDOW_HEIGHT 300
#define MAXIMUM_WINDOW_WIDTH 512
#define MAXIMUM_WINDOW_HEIGHT 512
#define DEFAULT_CAMERA_TILT CREAL(0.0)
#define DEFAULT_CAMERA_HEIGHT CREAL(0.0)
#define MAX_ANIM_TEXTURE 10
#define ERROR_DIALOG_TITLE "RenderWare Walkthrough Error"
/*--- Ansi Declarations */
/**********************************************************************
*
* Forward functions.
*
**********************************************************************/
extern long far PASCAL MainWndProc(HWND, WORD, WORD, LONG);
/**********************************************************************
*
* Type definitions.
*
**********************************************************************/
typedef enum
{
MMNoAction,
MMMoveCamera,
MMPanCamera,
MMTiltCamera,
MMDragClump
}
MMMode;
typedef enum
{
ANNoAction,
ANMoveCamera,
ANPanCamera
}
ANMode;
/**********************************************************************
*
* Application global variables.
*
**********************************************************************/
static HANDLE AppInstance;
static RwScene *Scene = NULL;
static RwCamera *Camera = NULL;
static RwLight *Light = NULL;
static MMMode MouseMoveMode = MMNoAction;
static ANMode AnimMode = ANNoAction;
static RwInt32 FirstX;
static RwInt32 FirstY;
static RwInt32 LastX;
static RwInt32 LastY;
static RwInt32 Width;
static RwInt32 Height;
static RwReal CamZDelta;
static RwReal CamPanDelta;
static RwReal CamTilt = DEFAULT_CAMERA_TILT;
static RwTexture *TextureArray[MAX_ANIM_TEXTURE];
static RwInt32 TextureCount = 0;
static RwClump *DragClump = NULL;
static BOOL ThreeDInitialized = FALSE;
/**********************************************************************
*
* Functions.
*
**********************************************************************/
/**************************************************************************
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 FAR PASCAL
AboutDlgProc(HWND hDlg, WORD message, WORD wParam, LONG 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:
DlgDrawItem((DRAWITEMSTRUCT FAR *) MK_FP32((void *) lParam));
return (TRUE);
}
return (FALSE);
}
/**********************************************************************/
/* Handle the given menu item. */
/**********************************************************************/
static void
HandleMenu(HWND window, WORD menuItem)
{
switch (menuItem)
{
case CM_FILEEXIT:
SendMessage(window, WM_CLOSE, 0, 0L);
break;
case CM_HELPABOUT:
KillTimer(window, 1);
DialogBox(AppInstance, "ABOUT", window, MakeProcInstance(AboutDlgProc, AppInstance));
SetTimer(window, 1, 10, NULL);
break;
}
}
/**********************************************************************/
/*
* Perform any necessary MS Windows application initialization. Basically,
* this means registering the window class for this application.
*/
static BOOL
InitApplication(HANDLE Instance)
{
WNDCLASS wc;
wc.style = CS_BYTEALIGNWINDOW;
wc.lpfnWndProc = (WNDPROC) MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = Instance;
wc.hIcon = LoadIcon(Instance, "RW_ICON");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = "FILE_MENU";
wc.lpszClassName = "RwWalkWndClass";
return RegisterClass(&wc);
}
/**********************************************************************/
static HWND
InitInstance(HANDLE Instance)
{
HWND Window;
/*
* Create the MS Windows window instance for this application. The initial
* window size is given by DEFAULT_WINDOW_WIDTH and DEFAULT_WINDOW_HEIGHT.
* However, when we create the RenderWare camera in Init3D() we specify
* a maximum camera viewport which is the same size as the screen. Thus
* the window can be maximed.
*/
Window = CreateWindow("RwWalkWndClass", "RenderWare WalkThrough",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT,
NULL, NULL, Instance, NULL);
if (!Window)
{
return NULL;
}
CheckDisplayDepth(Window);
return Window;
}
/**********************************************************************/
static RwTexture *
AddAnimTextures(RwTexture * Texture)
{
if (RwGetTextureNumFrames(Texture) > 1)
TextureArray[(int) (TextureCount++)] = Texture;
return Texture;
}
/**********************************************************************/
static BOOL
Init3D(HANDLE Instance, HWND Window)
{
RwClump *Clump;
char buffer[64];
int i;
if (!RwOpen("MSWindows", NULL))
{
if (RwGetError() == E_RW_NOMEM)
{
MessageBox(Window,
"Insufficient memory to open the RenderWare library",
ERROR_DIALOG_TITLE,
MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
else
{
MessageBox(Window, "Error opening the RenderWare library",
ERROR_DIALOG_TITLE,
MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
return FALSE;
}
/*--- Set the shape path to enable texture loading ---*/
GetModuleFileName(Instance, 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);
buffer[i + 1] = 0;
strcat(buffer, ".");
RwSetShapePath(buffer, rwPOSTCONCAT);
Camera = RwCreateCamera(MAXIMUM_WINDOW_WIDTH,
MAXIMUM_WINDOW_HEIGHT, NULL);
if (!Camera)
{
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 RenderWare camera",
ERROR_DIALOG_TITLE,
MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
return FALSE;
}
RwSetCameraBackColor(Camera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
RwSetCameraNearClipping(Camera, CREAL(0.05));
RwPanCamera(Camera, CREAL(180.0));
RwTiltCamera(Camera, CamTilt);
RwSetCameraBackColor(Camera, CREAL(0.5), CREAL(0.5), CREAL(1.0));
RwSetCameraViewwindow(Camera, CREAL(0.6), CREAL(0.6));
Scene = RwCreateScene();
if (!Scene)
{
MessageBox(Window, "Error creating the RenderWare scene",
ERROR_DIALOG_TITLE,
MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return FALSE;
}
Light = RwCreateLight(rwDIRECTIONAL, CREAL(0.1), CREAL(-1.0), CREAL(-0.5),
CREAL(1.0));
if (!Light)
{
MessageBox(Window, "Error creating the RenderWare light",
ERROR_DIALOG_TITLE,
MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return FALSE;
}
RwAddLightToScene(Scene, Light);
Clump = RwReadShape("kitchen.rwx");
if (!Clump)
{
if (RwGetError() == E_RW_NOMEM)
{
MessageBox(Window,
"Insufficient memory to read script file kitchen.rwx",
ERROR_DIALOG_TITLE,
MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
else
{
MessageBox(Window, "Could not read script file kitchen.rwx",
ERROR_DIALOG_TITLE,
MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
return FALSE;
}
RwAddClumpToScene(Scene, Clump);
RwForAllNamedTextures(AddAnimTextures);
ThreeDInitialized = TRUE;
return TRUE;
}
/**********************************************************************/
static void
TidyUp3D()
{
RwDestroyScene(Scene);
RwDestroyCamera(Camera);
RwClose();
}
/**********************************************************************/
static void
HandleGetMinMaxInfo(HWND Window, MINMAXINFO FAR * minmaxinfo)
{
minmaxinfo->ptMaxSize.x = MAXIMUM_WINDOW_WIDTH;
minmaxinfo->ptMaxSize.y = MAXIMUM_WINDOW_HEIGHT;
minmaxinfo->ptMaxTrackSize.x = MAXIMUM_WINDOW_WIDTH;
minmaxinfo->ptMaxTrackSize.y = MAXIMUM_WINDOW_HEIGHT;
}
/**********************************************************************/
static void
HandleSize(HWND Window, RwInt32 Width, RwInt32 Height)
{
Height = StatusAdjustHeight(Window, (int) Height);
RwSetCameraViewport(Camera, 0, 0, Width, Height);
InvalidateRect(Window, NULL, FALSE);
}
/**********************************************************************/
static void
HandleLeftButtonDown(HWND Window, RwInt32 x, RwInt32 y, WORD VKeys)
{
RwInt32 vx, vy, vw, vh;
POINT point;
RwReal XDelta;
RwReal YDelta;
if (VKeys & MK_SHIFT)
{
MouseMoveMode = MMPanCamera;
AnimMode = ANPanCamera;
ShowAppLeftStatus(Window, Camera, "Pan Camera");
}
else if (VKeys & MK_CONTROL)
{
MouseMoveMode = MMTiltCamera;
ShowAppLeftStatus(Window, Camera, "Tilt Camera");
}
else
{
MouseMoveMode = MMMoveCamera;
AnimMode = ANMoveCamera;
ShowAppLeftStatus(Window, Camera, "Pan and Zoom Camera");
}
if (MouseMoveMode != MMNoAction)
{
RwGetCameraViewport(Camera, &vx, &vy, &vw, &vh);
FirstX = vx + (vw >> 1);
FirstY = vy + (vh >> 1);
point.x = (int) FirstX;
point.y = (int) FirstY;
ClientToScreen(Window, &point);
FirstX = point.x;
FirstY = point.y;
Width = vw;
Height = vh;
point.x = (int) x;
point.y = (int) y;
ClientToScreen(Window, &point);
LastX = point.x;
LastY = point.y;
XDelta = RDiv(INT2REAL(FirstX - point.x), INT2REAL(Width));
YDelta = RDiv(INT2REAL(FirstY - point.y), INT2REAL(Height));
CamZDelta = RDiv(YDelta, CREAL(2));
CamPanDelta = RMul(XDelta, CREAL(4));
SetCapture(Window);
}
}
/**********************************************************************/
static void
HandleRightButtonDown(HWND Window, RwInt32 x, RwInt32 y, WORD VKeys)
{
RwInt32 vx, vy, vw, vh;
POINT point;
RwPickRecord Pick;
RwReal XDelta;
RwReal YDelta;
ShowAppLeftStatus(Window, Camera, "Move Object");
RwPickScene(Scene, x, y, Camera, &Pick);
if (Pick.type == rwPICKCLUMP)
{
/* The objects in the scene which are manipulatable are tagged
* with 2. */
if (RwGetClumpTag(Pick.object.clump.clump) == 2)
{
DragClump = Pick.object.clump.clump;
MouseMoveMode = MMDragClump;
}
else
{
MouseMoveMode = MMNoAction;
}
}
else
{
MouseMoveMode = MMNoAction;
}
if (MouseMoveMode != MMNoAction)
{
RwGetCameraViewport(Camera, &vx, &vy, &vw, &vh);
FirstX = vx + (vw >> 1);
FirstY = vy + (vh >> 1);
point.x = (int) FirstX;
point.y = (int) FirstY;
ClientToScreen(Window, &point);
FirstX = point.x;
FirstY = point.y;
Width = vw;
Height = vh;
point.x = (int) x;
point.y = (int) y;
ClientToScreen(Window, &point);
LastX = point.x;
LastY = point.y;
XDelta = RDiv(INT2REAL(FirstX - point.x), INT2REAL(Width));
YDelta = RDiv(INT2REAL(FirstY - point.y), INT2REAL(Height));
CamZDelta = RDiv(YDelta, CREAL(2));
CamPanDelta = RMul(XDelta, CREAL(6));
SetCapture(Window);
}
}
/**********************************************************************/
static void
HandleMouseMove(HWND Window, int x, int y)
{
POINT point;
RwReal XDelta;
RwReal YDelta;
switch (MouseMoveMode)
{
case MMNoAction:
break;
case MMMoveCamera:
point.x = x;
point.y = y;
ClientToScreen(Window, &point);
XDelta = RDiv(INT2REAL(FirstX - point.x), INT2REAL(Width));
YDelta = RDiv(INT2REAL(FirstY - point.y), INT2REAL(Height));
CamZDelta = RDiv(YDelta, CREAL(2));
CamPanDelta = RMul(XDelta, CREAL(6));
break;
case MMPanCamera:
point.x = x;
point.y = y;
ClientToScreen(Window, &point);
XDelta = RDiv(INT2REAL(FirstX - point.x), INT2REAL(Width));
CamPanDelta = RMul(XDelta, CREAL(6));
break;
case MMDragClump:
point.x = x;
point.y = y;
ClientToScreen(Window, &point);
XDelta = RDiv(INT2REAL(point.x - LastX), INT2REAL(Width));
YDelta = RDiv(INT2REAL(point.y - LastY), INT2REAL(Height));
RwPushScratchMatrix();
RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0), RMul(XDelta, CREAL(180.0)),
rwREPLACE);
RwTransformClumpJoint(DragClump, RwScratchMatrix(),
rwPOSTCONCAT);
RwPopScratchMatrix();
LastX = point.x;
LastY = point.y;
break;
case MMTiltCamera:
point.x = x;
point.y = y;
ClientToScreen(Window, &point);
YDelta = RDiv(INT2REAL(point.y - LastY), INT2REAL(Height));
RwTiltCamera(Camera, -CamTilt);
CamTilt = RAdd(CamTilt, RMul(YDelta, CREAL(30)));
if (CamTilt < CREAL(-45.0))
CamTilt = CREAL(-45.0);
else if (CamTilt > CREAL(45.0))
CamTilt = CREAL(45.0);
RwTiltCamera(Camera, CamTilt);
LastX = point.x;
LastY = point.y;
break;
}
}
/**********************************************************************/
static void
HandleLeftButtonUp(HWND Window)
{
if (MouseMoveMode != MMNoAction)
{
MouseMoveMode = MMNoAction;
AnimMode = ANNoAction;
ReleaseCapture();
ShowAppLeftStatus(Window, Camera, "");
}
}
/**********************************************************************/
static void
HandleRightButtonUp(HWND Window)
{
if (MouseMoveMode != MMNoAction)
{
MouseMoveMode = MMNoAction;
AnimMode = ANNoAction;
ReleaseCapture();
ShowAppLeftStatus(Window, Camera, "");
}
}
/**********************************************************************/
static void
HandlePaint(HWND Window)
{
HDC DC;
PAINTSTRUCT PS;
DC = BeginPaint(Window, &PS);
RwInvalidateCameraViewport(Camera);
RwBeginCameraUpdate(Camera, (void *) (DWORD) Window);
RwClearCameraViewport(Camera);
RwRenderScene(Scene);
RwEndCameraUpdate(Camera);
RwShowCameraImage(Camera, (void *) (DWORD) DC);
EndPaint(Window, &PS);
ShowAppLeftStatus(Window, Camera, "");
ShowAppRightStatus(Window, Camera, "");
}
/**********************************************************************/
static void
HandleTimer(HWND Window)
{
HDC DC;
int i;
RwV3d pos;
if (AnimMode != ANNoAction)
{
switch (AnimMode)
{
case ANMoveCamera:
RwTiltCamera(Camera, -CamTilt);
RwVCMoveCamera(Camera, CREAL(0.0), CREAL(0.0), CamZDelta);
RwPanCamera(Camera, CamPanDelta);
RwGetCameraPosition(Camera, &pos);
if (pos.x < CREAL(-0.75))
pos.x = CREAL(-0.75);
else if (pos.x > CREAL(0.75))
pos.x = CREAL(0.75);
if (pos.z < CREAL(-0.75))
pos.z = CREAL(-0.75);
else if (pos.z > CREAL(0.75))
pos.z = CREAL(0.75);
RwSetCameraPosition(Camera, pos.x, DEFAULT_CAMERA_HEIGHT, pos.z);
RwTiltCamera(Camera, CamTilt);
RwSetCameraLookUp(Camera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
break;
case ANPanCamera:
RwTiltCamera(Camera, -CamTilt);
RwPanCamera(Camera, CamPanDelta);
RwTiltCamera(Camera, CamTilt);
break;
}
}
for (i = 0; i < TextureCount; i++)
RwTextureNextFrame(TextureArray[i]);
RwInvalidateCameraViewport(Camera);
RwBeginCameraUpdate(Camera, (void *) (DWORD) Window);
RwClearCameraViewport(Camera);
RwRenderScene(Scene);
RwEndCameraUpdate(Camera);
DC = GetDC(Window);
RwShowCameraImage(Camera, (void *) (DWORD) DC);
ReleaseDC(Window, DC);
}
/**********************************************************************/
long far PASCAL
MainWndProc(HWND Window, WORD Message, WORD WParam, LONG LParam)
{
switch (Message)
{
case WM_COMMAND:
if (LOWORD(LParam) == 0)
HandleMenu(Window, WParam);
return 0L;
case WM_CREATE:
SetTimer(Window, 1, 20, NULL);
break;
case WM_GETMINMAXINFO:
HandleGetMinMaxInfo(Window, (MINMAXINFO FAR *) MK_FP32((void *) LParam));
break;
case WM_SIZE:
if (ThreeDInitialized)
HandleSize(Window, (RwInt32) LOWORD(LParam), (RwInt32) HIWORD(LParam));
break;
case WM_LBUTTONDOWN:
if (ThreeDInitialized)
HandleLeftButtonDown(Window, LOWORD(LParam), HIWORD(LParam), WParam);
break;
case WM_RBUTTONDOWN:
if (ThreeDInitialized)
HandleRightButtonDown(Window, (RwInt32) LOWORD(LParam), (RwInt32) HIWORD(LParam), WParam);
break;
case WM_MOUSEMOVE:
if (ThreeDInitialized)
{
if (MouseMoveMode != MMNoAction)
HandleMouseMove(Window, LOWORD(LParam), HIWORD(LParam));
}
break;
case WM_LBUTTONUP:
if (ThreeDInitialized)
HandleLeftButtonUp(Window);
break;
case WM_RBUTTONUP:
if (ThreeDInitialized)
HandleRightButtonUp(Window);
break;
case WM_PAINT:
if (ThreeDInitialized)
HandlePaint(Window);
break;
case WM_TIMER:
if (ThreeDInitialized)
HandleTimer(Window);
break;
case WM_DESTROY:
KillTimer(Window, 1);
PostQuitMessage(0);
break;
default:
return DefWindowProc(Window, Message, WParam, LParam);
}
return FALSE;
}
/**********************************************************************/
int PASCAL
WinMain(HANDLE Instance, HANDLE PrevInstance, LPSTR CmdLine, int CmdShow)
{
MSG Message;
HWND Window;
AppInstance = Instance;
if (PrevInstance)
{
MessageBox(NULL, "RenderWare WalkThrough is already running...",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return FALSE;
}
if (!InitApplication(Instance))
{
return FALSE;
}
if (!(Window = InitInstance(Instance)))
{
return FALSE;
}
if (!Init3D(Instance, Window))
{
DestroyWindow(Window);
return FALSE;
}
ShowWindow(Window, CmdShow);
UpdateWindow(Window);
while (GetMessage(&Message, (HWND) NULL, (UINT) NULL, (UINT) NULL))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
TidyUp3D();
UnregisterClass("RwWalkWndClass", Instance);
return Message.wParam;
}
/**********************************************************************/