home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Learn 3D Graphics Programming on the PC
/
Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso
/
rwwin
/
rwsim.c_
/
rwsim.bin
Wrap
Text File
|
1995-11-14
|
34KB
|
1,008 lines
/**********************************************************************
*
* File : rwsim.c
*
* Abstract : RenderWare N body simulation 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.
*
************************************************************************/
#define INCLUDE_SHELLAPI_H
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <rwlib.h>
#include "common.h"
#include "status.h"
#include "resource.h"
#ifndef __WINDOWS_386__
#define MK_FP32(x) (x)
#endif
#define DAMPING CREAL(0.95)
#define MAXTHINGS 25
#define ERROR_DIALOG_TITLE "RenderWare n-Body Simulation Error"
#define MAXIMUM_WINDOW_WIDTH 512
#define MAXIMUM_WINDOW_HEIGHT 512
/*--- Ansi Declarations */
extern long far PASCAL MainWndProc(HWND, WORD, WPARAM, LPARAM);
typedef struct
{
RwClump *geometry;
int canmove;
RwReal size;
RwV3d pos, vel;
RwMatrix4d *tumble, *rot, *antirot;
RwReal rotangle, antiangle;
RwV3d axis;
int damprot;
}
Thing;
Thing things[MAXTHINGS];
int follow, numthings;
HANDLE hInstance;
RwScene *scene;
RwCamera *pCamera;
RwLight *pLight;
static ThreeDInitialized = FALSE;
static long frames = 0;
/**************************************************************************
About Dialogue Box Stuff
**************************************************************************/
void
DlgDrawItem(DRAWITEMSTRUCT FAR * dis)
{
HDC hdcMemory;
HBITMAP hbmplogo, hbmpOld;
BITMAP bm;
hbmplogo = LoadBitmap(hInstance, "RW_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, 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:
DlgDrawItem((DRAWITEMSTRUCT FAR *) MK_FP32((void *) lParam));
return (TRUE);
}
return (FALSE);
}
/**********************************************************************/
/* Handle the given menu item. */
/**********************************************************************/
static void
HandleMenu(HWND window, WPARAM menuItem)
{
switch (menuItem)
{
case CM_FILEEXIT:
SendMessage(window, WM_CLOSE, 0, 0L);
break;
case CM_TRACK0:
follow = 0;
break;
case CM_TRACK1:
follow = 1;
break;
case CM_TRACK2:
follow = 2;
break;
case CM_TRACK3:
follow = 3;
break;
case CM_TRACK4:
follow = 4;
break;
case CM_TRACK5:
follow = 5;
break;
case CM_TRACK6:
follow = 6;
break;
case CM_TRACK7:
follow = 7;
break;
case CM_TRACK8:
follow = 8;
break;
case CM_TRACK9:
follow = 9;
break;
case CM_HELPABOUT:
KillTimer(window, 1);
DialogBox(hInstance, "ABOUT", window, MakeProcInstance(AboutDlgProc, hInstance));
SetTimer(window, 1, 10, NULL);
break;
}
}
/*********************************************************************/
static void
randomvec(RwV3d * vec)
{
vec->x = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
vec->y = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
vec->z = RANDOM_REAL(CREAL(-1.0), CREAL(1.0));
}
/*********************************************************************/
static void
assignvec(RwV3d * vec, RwReal x, RwReal y, RwReal z)
{
vec->x = x;
vec->y = y;
vec->z = z;
}
/*********************************************************************/
static RwPolygon3d *
makezippy(RwPolygon3d * p)
{
static int zippy = 0;
switch (zippy % 7)
{
case 0:
RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.0));
break;
case 1:
RwSetPolygonColor(p, CREAL(0.0), CREAL(0.7), CREAL(0.0));
break;
case 2:
RwSetPolygonColor(p, CREAL(0.0), CREAL(0.0), CREAL(0.7));
break;
case 3:
RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.0));
break;
case 4:
RwSetPolygonColor(p, CREAL(0.7), CREAL(0.0), CREAL(0.7));
break;
case 5:
RwSetPolygonColor(p, CREAL(0.0), CREAL(0.7), CREAL(0.7));
break;
case 6:
RwSetPolygonColor(p, CREAL(0.7), CREAL(0.7), CREAL(0.7));
break;
}
zippy++;
return (p);
}
/*********************************************************************/
static void
makethings(RwScene * scene, Thing * things, int num)
{
RwClump *clump, *prototypes[4];
RwV3d p;
int i;
RwInt32 which;
RwSRandom((RwInt32) clock());
for (i = 0; i < 4; i++)
{
RwClumpBegin();
RwSetSurface(CREAL(0.4), CREAL(0.7), CREAL(0.0));
RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))));
switch (i)
{
case 0:
RwTranslateCTM(CREAL(0.0), CREAL(-0.15 / 2), CREAL(0.0));
RwCone(CREAL(0.15), CREAL(0.1), 12);
RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.0));
RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))));
RwDisc(CREAL(0.0), CREAL(0.1), 12);
break;
case 1:
RwSphere(CREAL(0.1), 3);
break;
case 2:
RwTranslateCTM(CREAL(0.0), CREAL(-0.15 / 2), CREAL(0.0));
RwCylinder(CREAL(0.15), CREAL(0.1), CREAL(0.1), 12);
RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))));
RwDisc(CREAL(0.15), CREAL(0.1), 12);
RwRotateCTM(CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(180.0));
RwSetSurfaceColor(RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))),
RDiv(CREAL(1.0), INT2REAL(1 + (RwRandom() % 4))));
RwDisc(CREAL(0.0), CREAL(0.1), 12);
break;
default:
RwBlock(CREAL(0.1), CREAL(0.2), CREAL(0.15));
break;
}
RwClumpEnd(&prototypes[i]);
}
for (i = 0; i < num; i++)
{
which = RwRandom() % 4L;
clump = RwDuplicateClump(prototypes[(int) which]);
if ((RwRandom() & 7) < 2)
RwForAllPolygonsInClump(clump, makezippy);
RwAddClumpToScene(scene, clump);
things[i].geometry = clump;
things[i].size = CREAL(0.1);
RwIdentityMatrix(things[i].tumble = RwCreateMatrix());
RwIdentityMatrix(things[i].rot = RwCreateMatrix());
/*
RwIdentityMatrix(things[i].antirot = RwCreateMatrix());
*/
things[i].damprot = 0;
randomvec(&p);
things[i].pos.x = RMul(p.x, RSub(CREAL(1.0), things[i].size));
things[i].pos.y = RMul(p.y, RSub(CREAL(1.0), things[i].size));
things[i].pos.z = RMul(p.z, RSub(CREAL(1.0), things[i].size));
things[i].canmove = 7;
assignvec(&things[i].vel, CREAL(0.0), CREAL(0.0), CREAL(0.0));
}
for (i = 0; i < 4; i++)
RwDestroyClump(prototypes[i]);
}
/*********************************************************************/
static
twobody(Thing * things, int i, int j)
{
RwReal length, adjust, doti, dotj, speedi, speedj;
RwV3d hit, axis, xferi, xferj;
RwV3d veli, velj;
hit.x = RSub(things[j].pos.x, things[i].pos.x);
hit.y = RSub(things[j].pos.y, things[i].pos.y);
hit.z = RSub(things[j].pos.z, things[i].pos.z);
length = RAdd(RAdd(RMul(hit.x, hit.x), RMul(hit.y, hit.y)),
RMul(hit.z, hit.z));
if (length > CREAL(0.0) && length < CREAL(0.2 * 0.2))
{
if (1)
{
length = RSqrt(length);
hit.x = RDiv(hit.x, length);
hit.y = RDiv(hit.y, length);
hit.z = RDiv(hit.z, length);
adjust = RDiv(RSub(CREAL(0.2), length), CREAL(2));
veli = things[i].vel;
speedi = RAdd(RAdd(RMul(veli.x, veli.x), RMul(veli.y, veli.y)),
RMul(veli.z, veli.z));
if (speedi != CREAL(0.0))
{
speedi = RSqrt(speedi);
veli.x = RDiv(veli.x, speedi);
veli.y = RDiv(veli.y, speedi);
veli.z = RDiv(veli.z, speedi);
doti = RwDotProduct(&hit, &veli);
if (doti > CREAL(0))
{
speedi = RMul(speedi, RMul(doti, DAMPING));
xferi.x = RMul(hit.x, speedi);
xferi.y = RMul(hit.y, speedi);
xferi.z = RMul(hit.z, speedi);
RwCrossProduct(&veli, &hit, &axis);
/*
RwRotateMatrix(things[i].rot, axis.x,axis.y,axis.z,
RMul(speedi, RMul(RSub(CREAL(1),doti), CREAL(720.0))),
rwREPLACE);
*/
things[i].rotangle = RMul(speedi, RMul(RSub(CREAL(1), doti), CREAL(720.0)));
things[i].axis.x = axis.x;
things[i].axis.y = axis.y;
things[i].axis.z = axis.z;
/*
RwRotateMatrix(things[i].antirot, axis.x,axis.y,axis.z,
RMul(speedi, RMul(RSub(CREAL(1),doti), CREAL(-4.0))),
rwREPLACE);
*/
things[i].antiangle = RMul(speedi, RMul(RSub(CREAL(1), doti), CREAL(-4.0)));
things[i].damprot = (int) (720.0 / 4.0);
}
else
xferi.x = xferi.y = xferi.z = CREAL(0.0);
}
else
xferi.x = xferi.y = xferi.z = CREAL(0.0);
/* I happen to know that -= works :-) */
if (things[i].canmove & 1)
things[i].pos.x -= RMul(hit.x, adjust);
if (!things[j].canmove & 1)
things[i].pos.x -= RMul(hit.x, adjust);
if (things[i].canmove & 2)
things[i].pos.y -= RMul(hit.y, adjust);
if (!things[j].canmove & 2)
things[i].pos.y -= RMul(hit.y, adjust);
if (things[i].canmove & 4)
things[i].pos.z -= RMul(hit.z, adjust);
if (!things[j].canmove & 4)
things[i].pos.z -= RMul(hit.z, adjust);
hit.x = -hit.x;
hit.y = -hit.y;
hit.z = -hit.z;
velj = things[j].vel;
speedj = RAdd(RAdd(RMul(velj.x, velj.x), RMul(velj.y, velj.y)),
RMul(velj.z, velj.z));
if (speedj != CREAL(0.0))
{
speedj = RSqrt(speedj);
velj.x = RDiv(velj.x, speedj);
velj.y = RDiv(velj.y, speedj);
velj.z = RDiv(velj.z, speedj);
dotj = RwDotProduct(&hit, &velj);
if (dotj > CREAL(0))
{
speedj = RMul(speedj, RMul(dotj, DAMPING));
xferj.x = RMul(hit.x, speedj);
xferj.y = RMul(hit.y, speedj);
xferj.z = RMul(hit.z, speedj);
RwCrossProduct(&velj, &hit, &axis);
/*
RwRotateMatrix(things[j].rot, axis.x,axis.y,axis.z,
RMul(speedj, RMul(RSub(CREAL(1),dotj), CREAL(720.0))),
rwREPLACE);
*/
things[j].rotangle = RMul(speedj, RMul(RSub(CREAL(1), dotj), CREAL(720.0)));
things[j].axis.x = axis.x;
things[j].axis.y = axis.y;
things[j].axis.z = axis.z;
/*
RwRotateMatrix(things[j].antirot, axis.x,axis.y,axis.z,
RMul(speedj, RMul(RSub(CREAL(1),dotj), CREAL(-4.0))),
rwREPLACE);
*/
things[j].antiangle = RMul(speedj, RMul(RSub(CREAL(1), dotj), CREAL(-4.0)));
things[j].damprot = (int) (720.0 / 4.0);
}
else
xferj.x = xferj.y = xferj.z = CREAL(0.0);
}
else
xferj.x = xferj.y = xferj.z = CREAL(0.0);
if (things[j].canmove & 1)
things[j].pos.x -= RMul(hit.x, adjust);
if (!things[i].canmove & 1)
things[j].pos.x -= RMul(hit.x, adjust);
if (things[j].canmove & 2)
things[j].pos.y -= RMul(hit.y, adjust);
if (!things[i].canmove & 2)
things[j].pos.y -= RMul(hit.y, adjust);
if (things[j].canmove & 4)
things[j].pos.z -= RMul(hit.z, adjust);
if (!things[i].canmove & 4)
things[j].pos.z -= RMul(hit.z, adjust);
/* A little bird told me that += always works :-) */
things[i].vel.x += RSub(xferj.x, xferi.x);
things[i].vel.y += RSub(xferj.y, xferi.y);
things[i].vel.z += RSub(xferj.z, xferi.z);
things[j].vel.x += RSub(xferi.x, xferj.x);
things[j].vel.y += RSub(xferi.y, xferj.y);
things[j].vel.z += RSub(xferi.z, xferj.z);
}
return (1);
}
return (0);
}
/*********************************************************************/
void
collisions(Thing * things, int num)
{
int i, j;
for (i = 0; i < num; i++)
{
for (j = i + 1; j < num; j++)
{
if (twobody(things, i, j))
break;
}
}
}
/*********************************************************************/
static void
gravitatethings(Thing * things, int num, RwV3d * acc)
{
int i;
RwV3d p;
RwReal val;
RwReal limit;
RwPushScratchMatrix();
limit = CREAL(1.0 - 0.1);
for (i = 0; i < num; i++)
{
if (things[i].damprot > 0)
{
/* Below is the original version of the damping code. This accumulates
a new .rot matrix by repeated multiplication with .antirot. This
causes the .rot matrix to drift causing shearing of the object.
RwMultiplyMatrix(things[i].rot, things[i].antirot, RwScratchMatrix());
RwCopyMatrix(RwScratchMatrix(), things[i].rot);
*/
RwRotateMatrix(things[i].rot, things[i].axis.x, things[i].axis.y,
things[i].axis.z,
RSub(things[i].rotangle, things[i].antiangle), rwREPLACE);
things[i].damprot--;
}
RwMultiplyMatrix(things[i].tumble, things[i].rot, RwScratchMatrix());
if ((frames) % (num << 3) == (i << 3))
RwOrthoNormalizeMatrix(RwScratchMatrix(), RwScratchMatrix());
RwCopyMatrix(RwScratchMatrix(), things[i].tumble);
p = things[i].pos;
RwTranslateMatrix(RwScratchMatrix(), p.x, p.y, p.z, rwPOSTCONCAT);
RwTransformClump(things[i].geometry, RwScratchMatrix(), rwREPLACE);
things[i].canmove = 0;
/* += */
things[i].vel.x += acc->x;
val = things[i].pos.x += things[i].vel.x;
if (val < -limit || val > limit)
{
things[i].vel.x -= acc->x;
things[i].vel.x = RMul(-things[i].vel.x, DAMPING);
things[i].pos.x = val < CREAL(0.0) ? -limit : limit;
}
else
things[i].canmove |= 1;
things[i].vel.y += acc->y;
val = things[i].pos.y += things[i].vel.y;
if (val < -limit || val > limit)
{
things[i].vel.y -= acc->y;
things[i].vel.y = RMul(-things[i].vel.y, DAMPING);
things[i].pos.y = val < CREAL(0.0) ? -limit : limit;
}
else
things[i].canmove |= 2;
things[i].vel.z += acc->z;
val = things[i].pos.z += things[i].vel.z;
if (val < -limit || val > limit)
{
things[i].vel.z -= acc->z;
things[i].vel.z = RMul(-things[i].vel.z, DAMPING);
things[i].pos.z = val < CREAL(0.0) ? -limit : limit;
}
else
things[i].canmove |= 4;
}
RwPopScratchMatrix();
frames++;
}
/*********************************************************************/
/*********************************************************************/
BOOL
InitApplication(HANDLE hInst)
{
WNDCLASS wc;
wc.style = CS_BYTEALIGNWINDOW | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, "RW_ICON");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = "FILE_MENU";
wc.lpszClassName = "RwNBodyWndClass";
return (RegisterClass(&wc));
}
BOOL
InitInstance(HANDLE hInst, int nCmdShow)
{
HWND hWnd;
int i, j;
RwClump *temp;
hInstance = hInst;
hWnd = CreateWindow("RwNBodyWndClass", "RenderWare n-Body Simulation",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 350, 350,
NULL, NULL, hInstance, NULL);
if (hWnd == NULL)
{
MessageBox(NULL, "Internal Operating System Error",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return (FALSE);
}
CheckDisplayDepth(hWnd);
if (!RwOpen("MSWindows", NULL))
{
if (RwGetError() == E_RW_NOMEM)
{
MessageBox(hWnd,
"Insufficient memory to open the RenderWare library",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
else
{
MessageBox(hWnd, "Error opening the RenderWare library",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
return (FALSE);
}
scene = RwCreateScene();
if (scene == NULL)
{
RwClose();
MessageBox(hWnd, "Error creating the RenderWare scene",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return (FALSE);
}
pCamera = RwCreateCamera(MAXIMUM_WINDOW_WIDTH,
MAXIMUM_WINDOW_HEIGHT, NULL);
if (pCamera == NULL)
{
if (RwGetError() == E_RW_NOMEM)
{
MessageBox(hWnd,
"Insufficient memory to create the RenderWare camera",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
else
{
MessageBox(hWnd, "Error creating the RenderWare camera",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
}
RwDestroyScene(scene);
RwClose();
return (FALSE);
}
RwClearCameraViewport(pCamera);
RwSetCameraBackColor(pCamera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
RwVCMoveCamera(pCamera, CREAL(0.0), CREAL(0.0), CREAL(-7.0));
pLight = RwCreateLight(rwDIRECTIONAL, CREAL(-0.5), CREAL(-1.0), CREAL(-1.0),
CREAL(1.2));
if (pLight == NULL)
{
RwDestroyCamera(pCamera);
RwDestroyScene(scene);
RwClose();
MessageBox(hWnd, "Error creating the RenderWare light",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return (FALSE);
}
RwAddLightToScene(scene, pLight);
RwClumpBegin();
RwVertex(CREAL(-1.0), CREAL(-1.005), CREAL(1.0));
RwVertex(CREAL(1.0), CREAL(-1.005), CREAL(1.0));
RwVertex(CREAL(1.0), CREAL(1.0), CREAL(1.0));
RwVertex(CREAL(-1.0), CREAL(1.0), CREAL(1.0));
RwVertex(CREAL(-1.0), CREAL(-1.005), CREAL(-1.0));
RwVertex(CREAL(1.0), CREAL(-1.005), CREAL(-1.0));
RwVertex(CREAL(1.0), CREAL(1.0), CREAL(-1.0));
RwVertex(CREAL(-1.0), CREAL(1.0), CREAL(-1.0));
RwSetSurface(CREAL(0.4), CREAL(0.6), CREAL(0.0));
RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.5));
RwQuad(2, 1, 4, 3);
RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(0.7));
RwQuad(6, 2, 3, 7);
RwSetSurfaceColor(CREAL(0.0), CREAL(0.7), CREAL(0.0));
RwQuad(5, 6, 7, 8);
RwSetSurfaceColor(CREAL(0.7), CREAL(0.0), CREAL(0.0));
RwQuad(1, 5, 8, 4);
RwSetSurfaceColor(CREAL(0.0), CREAL(0.7), CREAL(0.0));
RwQuad(8, 7, 3, 4);
RwTransformBegin();
RwTranslateCTM(CREAL(0.0), CREAL(-1.0), CREAL(0.0));
RwScaleCTM(CREAL(0.25), CREAL(0.0), CREAL(0.25));
for (i = -4; i <= 4; i++)
for (j = -4; j <= 4; j++)
RwVertex(INT2REAL(i), CREAL(0.0), INT2REAL(j));
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++)
{
if ((i ^ j) & 1)
{
RwSetSurface(CREAL(0.5), CREAL(0.2), CREAL(0.0));
RwSetSurfaceColor(CREAL(1.0), CREAL(0.0), CREAL(0.0));
}
else
{
RwSetSurface(CREAL(0.5), CREAL(0.5), CREAL(0.0));
RwSetSurfaceColor(CREAL(0.5), CREAL(0.5), CREAL(0.0));
}
RwQuad(9 + (i * 9) + j, 9 + (i * 9) + j + 1, 9 + ((i + 1) * 9) + j + 1, 9 + ((i + 1) * 9) + j);
}
RwTransformEnd();
RwClumpEnd(&temp);
RwAddHintToClump(temp, rwCONTAINER);
RwAddClumpToScene(scene, temp);
numthings = 10; /* number of objects */
makethings(scene, things, numthings);
follow = 0;
/* thunderbirds are go! */
SetTimer(hWnd, 1, 50, NULL);
ThreeDInitialized = TRUE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return (TRUE);
}
/**************************************************************************/
void
OnSize(HWND hwnd, LPARAM lparam)
{
RwInt32 width;
RwInt32 height;
width = (RwInt32) LOWORD(lparam);
height = (RwInt32) HIWORD(lparam);
height = StatusAdjustHeight(hwnd, (int) height);
/* Set the camera viewport to match the window's client area. */
RwSetCameraViewport(pCamera, 0, 0, width, height);
RwGetCameraViewport(pCamera, NULL, NULL, &width, &height);
/* Maintain the view window at a 1:1 aspect ratio. */
if ((width != 0) && (height != 0))
{
if (width >= height)
RwSetCameraViewwindow(pCamera,
CREAL(0.2),
RMul(CREAL(0.2), RDiv(INT2REAL(height), INT2REAL(width))));
else
RwSetCameraViewwindow(pCamera,
RMul(CREAL(0.2), RDiv(INT2REAL(width), INT2REAL(height))),
CREAL(0.2));
}
ShowAppLeftStatus(hwnd, pCamera, "");
ShowAppRightStatus(hwnd, pCamera, "");
}
long far PASCAL
MainWndProc(HWND hWnd, WORD message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
static int x;
static int y;
static int bButtonDown = 0;
MINMAXINFO FAR *minmaxinfo;
switch (message)
{
case WM_COMMAND:
if (LOWORD(lParam) == 0)
HandleMenu(hWnd, wParam);
return 0L;
case (WM_SIZE):
if (!ThreeDInitialized)
break;
OnSize(hWnd, lParam);
break;
case (WM_GETMINMAXINFO):
minmaxinfo = (MINMAXINFO FAR *) MK_FP32((void *) lParam);
minmaxinfo->ptMaxSize.x = MAXIMUM_WINDOW_WIDTH;
minmaxinfo->ptMaxSize.y = MAXIMUM_WINDOW_HEIGHT;
minmaxinfo->ptMaxTrackSize.x = MAXIMUM_WINDOW_WIDTH;
minmaxinfo->ptMaxTrackSize.y = MAXIMUM_WINDOW_HEIGHT;
break;
case (WM_LBUTTONDOWN):
if (!bButtonDown)
{
SetCapture(hWnd);
ShowAppLeftStatus(hWnd, pCamera, "Pan and Tilt Camera");
}
else
/* both must be down */
{
ShowAppLeftStatus(hWnd, pCamera, "Zoom Camera");
}
bButtonDown |= 1;
x = LOWORD(lParam);
y = HIWORD(lParam);
break;
case (WM_RBUTTONDOWN):
if (!bButtonDown)
{
SetCapture(hWnd);
ShowAppLeftStatus(hWnd, pCamera, "Pan and Zoom Camera");
}
else
{
ShowAppLeftStatus(hWnd, pCamera, "Zoom Camera");
}
bButtonDown |= 2;
x = LOWORD(lParam);
y = HIWORD(lParam);
break;
case (WM_MOUSEMOVE):
if (bButtonDown)
{
int dx, dy;
dx = ((short) LOWORD(lParam)) - x;
dy = ((short) HIWORD(lParam)) - y;
switch (bButtonDown)
{
case 1:
{
RwV3d at, up;
RwPushScratchMatrix();
RwGetCameraLookUp(pCamera, &up);
RwRotateMatrix(RwScratchMatrix(), up.x, up.y, up.z, INT2REAL(-dx),
rwREPLACE);
RwGetCameraLookRight(pCamera, &at);
RwRotateMatrix(RwScratchMatrix(), at.x, at.y, at.z, INT2REAL(-dy),
rwPOSTCONCAT);
RwTransformCamera(pCamera, RwScratchMatrix(), rwPOSTCONCAT);
RwPopScratchMatrix();
}
break;
case 2:
RwVCMoveCamera(pCamera, CREAL(0.0), CREAL(0.0), RDiv(INT2REAL(-dy),
CREAL(50.0)));
RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
INT2REAL(-dx), rwREPLACE);
RwTransformCamera(pCamera, RwScratchMatrix(), rwPOSTCONCAT);
break;
case 3:
RwVCMoveCamera(pCamera, CREAL(0.0), CREAL(0.0), RDiv(INT2REAL(-dy),
CREAL(50.0)));
break;
}
// InvalidateRect( hWnd, NULL, FALSE );
x = (short) LOWORD(lParam);
y = (short) HIWORD(lParam);
}
break;
case (WM_LBUTTONUP):
if (!ThreeDInitialized)
break;
bButtonDown &= ~1;
if (!bButtonDown)
{
ReleaseCapture();
ShowAppLeftStatus(hWnd, pCamera, "");
}
else
ShowAppLeftStatus(hWnd, pCamera, "Pan and Zoom Camera");
break;
case (WM_RBUTTONUP):
if (!ThreeDInitialized)
break;
bButtonDown &= ~2;
if (!bButtonDown)
{
ShowAppLeftStatus(hWnd, pCamera, "");
ReleaseCapture();
}
else
{
ShowAppLeftStatus(hWnd, pCamera, "Pan and Tilt Camera");
}
break;
case (WM_PAINT):
if (!ThreeDInitialized)
break;
hDC = BeginPaint(hWnd, &ps);
RwBeginCameraUpdate(pCamera, (void *) (DWORD) hWnd);
RwInvalidateCameraViewport(pCamera);
RwClearCameraViewport(pCamera);
RwRenderScene(scene);
RwEndCameraUpdate(pCamera);
RwShowCameraImage(pCamera, (void *) (DWORD) hDC);
EndPaint(hWnd, &ps);
ShowAppLeftStatus(hWnd, pCamera, "");
ShowAppRightStatus(hWnd, pCamera, "");
break;
case (WM_CHAR):
if (!ThreeDInitialized)
break;
if (wParam >= '0' && wParam <= '9' && wParam < numthings + '0')
{
follow = wParam - '0';
}
else if ((wParam == 't') || (wParam == 'T'))
{
DWORD t, u;
int i;
char szBuf[255];
u = GetTickCount();
while (u == (t = GetTickCount()));
for (i = 0; i < 150; i++)
{
RwV3d vec;
collisions(things, numthings);
RwGetCameraLookUp(pCamera, &vec);
vec.x = RDiv(vec.x, CREAL(-200));
vec.y = RDiv(vec.y, CREAL(-200));
vec.z = RDiv(vec.z, CREAL(-200));
gravitatethings(things, numthings, &vec);
if (1)
{
RwGetClumpOrigin(things[follow].geometry, &vec);
RwPointCamera(pCamera, vec.x, vec.y, vec.z);
RwSetCameraLookUp(pCamera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
}
RwBeginCameraUpdate(pCamera, (void *) (DWORD) hWnd);
RwClearCameraViewport(pCamera);
RwRenderScene(scene);
hDC = GetDC(hWnd);
RwEndCameraUpdate(pCamera);
RwShowCameraImage(pCamera, (void *) (DWORD) hDC);
ReleaseDC(hWnd, hDC);
}
u = GetTickCount();
sprintf(szBuf, "Winsim took %lu ms for %d frames\n", u - t, i);
MessageBox(hWnd, szBuf, "", MB_OK);
}
break;
case (WM_TIMER):
if (!ThreeDInitialized)
break;
if (1)
{
RwV3d vec;
collisions(things, numthings);
RwGetCameraLookUp(pCamera, &vec);
vec.x = RDiv(vec.x, CREAL(-200));
vec.y = RDiv(vec.y, CREAL(-200));
vec.z = RDiv(vec.z, CREAL(-200));
gravitatethings(things, numthings, &vec);
if (!bButtonDown)
{
RwGetClumpOrigin(things[follow].geometry, &vec);
RwPointCamera(pCamera, vec.x, vec.y, vec.z);
RwSetCameraLookUp(pCamera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
}
RwBeginCameraUpdate(pCamera, (void *) (DWORD) hWnd);
RwClearCameraViewport(pCamera);
RwRenderScene(scene);
hDC = GetDC(hWnd);
RwEndCameraUpdate(pCamera);
RwShowCameraImage(pCamera, (void *) (DWORD) hDC);
ReleaseDC(hWnd, hDC);
}
break;
case (WM_DESTROY):
KillTimer(hWnd, 1);
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0L);
}
int PASCAL
WinMain(HANDLE hInst, HANDLE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
if (!InitApplication(hInst))
{
MessageBox(NULL, "n-Body simulation is already running...",
ERROR_DIALOG_TITLE, MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return (FALSE);
}
if (!InitInstance(hInst, nCmdShow))
{
return (FALSE);
}
while (GetMessage(&msg, (HWND) NULL, (UINT) NULL, (UINT) NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
RwDestroyCamera(pCamera);
RwDestroyLight(pLight);
while (numthings--)
RwDestroyClump(things[numthings].geometry);
RwDestroyScene(scene);
RwClose();
UnregisterClass("RwNBodyWndClass", hInst);
return (msg.wParam);
}