home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Learn 3D Graphics Programming on the PC
/
Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso
/
rwwin
/
rwvis.c_
/
rwvis.bin
Wrap
Text File
|
1995-11-14
|
42KB
|
1,445 lines
/**********************************************************************
*
* File : rwvis.c
*
* Abstract : RenderWare visualisation demo
*
**********************************************************************
*
* 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.
*
************************************************************************/
/*---- Include files ---*/
#define INCLUDE_SHELLAPI_H
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include "rwlib.h"
#include "status.h"
#include "common.h"
/*--- Macro Definitions ---*/
#ifndef __WINDOWS_386__
#define MK_FP32(x) (x) /* not using Watcom */
#endif
#define RWAPPNAME "Renderware Visualisation Demo"
#define MAX_WIN_WIDTH 512
#define MAX_WIN_HEIGHT 512
#define DEFAULT_X SIN
#define DEFAULT_Y COS
#define DEFAULT_Z XADDY
#define DEFAULT_R R_8
#define DEFAULT_S S_SMOOTH
#define DEFAULT_T T_MANDEL
#define X_MBASE 1
#define Y_MBASE (X_MBASE + 10)
#define Z_MBASE (Y_MBASE + 10)
#define M_MBASE (Z_MBASE + 10)
#define R_MBASE (M_MBASE + 10)
#define S_MBASE (R_MBASE + 10)
#define T_MBASE (S_MBASE + 10)
#define H_MBASE (T_MBASE + 10)
#define MAX_RESOLUTION 16
#define MAX_CLUMP_VERTICES (MAX_RESOLUTION * MAX_RESOLUTION + 10 * MAX_RESOLUTION + 13)
#define MAX_POLY_VERTICES (MAX_RESOLUTION + 3)
#define CUBE_DIMENSION 4.0
/*--- Type Definitions ---*/
typedef enum
{
S_FLAT,
S_SMOOTH
}
EnShading;
typedef enum
{
H_ABOUT
}
EnHelp;
typedef enum
{
T_NONE,
T_WOOD,
T_BRICK,
T_MARBLE,
T_MANDEL,
T_MANDRILL,
}
EnTexture;
typedef enum
{
R_4,
R_8,
R_16
}
EnResolution;
typedef enum
{
ZERO,
RAMP,
SIN,
COS,
SQUARED,
CUBED,
MAX_FUNC
}
EnFunc;
typedef enum
{
XMULY,
XSUBY,
XADDY,
MAX_ZFUNC
}
EnZFunc;
typedef struct
{
BOOL flag;
RwMatrix4d *m;
RwInt32 dx;
RwInt32 dy;
}
TyRot;
/*--- Global Variable Definitions ---*/
RwLight *Light;
char *TextureNames[] =
{
NULL,
"wood008.bmp",
"stone002.bmp",
"stone004.bmp",
"mandel.bmp",
"mandrill.bmp"
}; /* must match order of EnTexture */
TyRot Rot;
EnFunc Xfunc = DEFAULT_X;
EnFunc Yfunc = DEFAULT_Y;
EnZFunc Zfunc = DEFAULT_Z;
EnShading Shading = DEFAULT_S;
EnTexture Texture = DEFAULT_T;
HMENU Mainmenu;
HINSTANCE Hinstance;
RwCamera *Camera;
BOOL lb = FALSE;
BOOL rb = FALSE;
RwInt32 Xprev;
RwInt32 Yprev;
RwClump *Clump = NULL;
RwInt32 Resolution;
RwInt32 Vertices;
RwReal Costab[MAX_RESOLUTION + 1];
RwReal Sintab[MAX_RESOLUTION + 1];
RwV3d Vval[MAX_CLUMP_VERTICES];
RwInt32 Vindex[MAX_CLUMP_VERTICES];
int Fnoffset;
RwReal Fn[512];
BOOL Membrane = FALSE;
/**************************************************************************
About Dialogue Box Stuff
**************************************************************************/
void
DlgDrawItem(DRAWITEMSTRUCT FAR * dis)
{
HDC hdcMemory;
HBITMAP hbmplogo, hbmpOld;
BITMAP bm;
hbmplogo = LoadBitmap(Hinstance, "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);
}
/***************************************************************************
Build Internal Sin & Cos tables
***************************************************************************/
void
BuildSinCosTab(void)
{
int i;
for (i = 0; i <= MAX_RESOLUTION; i++)
{
Sintab[i] = FL2REAL(sin(i * 6.283 / (float) MAX_RESOLUTION));
Costab[i] = FL2REAL(cos(i * 6.283 / (float) MAX_RESOLUTION));
}
}
/***************************************************************************
Display Informational Text
***************************************************************************/
void
ShowInfo(HWND hwnd)
{
char str[32];
if (Membrane)
{
sprintf(str, "Membrane");
}
else
{
sprintf(str, "z = ");
switch (Xfunc)
{
case ZERO:
strcat(str, "0 ");
break;
case RAMP:
strcat(str, "x ");
break;
case SIN:
strcat(str, "sin(x) ");
break;
case COS:
strcat(str, "cos(x) ");
break;
case SQUARED:
strcat(str, "(x^2) ");
break;
case CUBED:
strcat(str, "(x^3) ");
break;
}
switch (Zfunc)
{
case XMULY:
strcat(str, "* ");
break;
case XADDY:
strcat(str, "+ ");
break;
case XSUBY:
strcat(str, "- ");
break;
}
switch (Yfunc)
{
case ZERO:
strcat(str, "0");
break;
case RAMP:
strcat(str, "y");
break;
case SIN:
strcat(str, "sin(y)");
break;
case COS:
strcat(str, "cos(y)");
break;
case SQUARED:
strcat(str, "(y^2)");
break;
case CUBED:
strcat(str, "(y^3)");
break;
}
}
ShowAppRightStatus(hwnd, Camera, str);
}
/***************************************************************************
Set polygon data field to indicate if it forms the box or the surface
***************************************************************************/
RwPolygon3d *
SetPolygonData(RwPolygon3d * p)
{
RwInt32 varray[MAX_POLY_VERTICES];
RwGetPolygonVertices(p, varray);
if (Membrane)
{
if (varray[0] <= Vertices)
RwSetPolygonData(p, varray);
else
RwSetPolygonData(p, NULL);
}
else
{
if (varray[0] <= (Resolution + 1) * (Resolution + 1))
RwSetPolygonData(p, varray);
else
RwSetPolygonData(p, NULL);
}
return (p);
}
/***************************************************************************
GeneratePoints
***************************************************************************/
void
GeneratePoints(void)
{
RwReal temp, *xval, yval;
int x, y, v;
RwReal xyscale, xyoffset, zscale;
xyscale = RDiv(CREAL(CUBE_DIMENSION), INT2REAL(Resolution));
xyoffset = -RMul(CREAL(CUBE_DIMENSION), CREAL(0.5));
zscale = RMul(CREAL(CUBE_DIMENSION), CREAL(0.25));
xval = (RwReal *)malloc(sizeof (RwReal) * (Resolution + 1L));
/*--- Build Grid of Z values ---*/
v = 0;
for (x = 0; x <= Resolution; x++)
{
switch (Xfunc)
{
case ZERO:
xval[x] = CREAL(0.0);
break;
case RAMP:
xval[x] = RDiv(INT2REAL(x - Resolution / 2), INT2REAL(Resolution / 2));
break;
case SIN:
xval[x] = Sintab[(int)((x % Resolution) * MAX_RESOLUTION / Resolution)];
break;
case COS:
xval[x] = Costab[(int)((x % Resolution) * MAX_RESOLUTION / Resolution)];
break;
case SQUARED:
temp = RDiv(INT2REAL(x - Resolution / 2), INT2REAL(Resolution / 2));
xval[x] = RMul(temp, temp);
break;
case CUBED:
temp = RDiv(INT2REAL(x - Resolution / 2), INT2REAL(Resolution / 2));
xval[x] = RMul(temp, RMul(temp, temp));
break;
}
}
for (y = 0; y <= Resolution; y++)
{
switch (Yfunc)
{
case ZERO:
yval = CREAL(0.0);
break;
case RAMP:
yval = RDiv(INT2REAL(y - Resolution / 2), INT2REAL(Resolution / 2));
break;
case SIN:
yval = Sintab[(int)((y % Resolution) * MAX_RESOLUTION / Resolution)];
break;
case COS:
yval = Costab[(int)((y % Resolution) * MAX_RESOLUTION / Resolution)];
break;
case SQUARED:
temp = RDiv(INT2REAL(y - Resolution / 2), INT2REAL(Resolution / 2));
yval = RMul(temp, temp);
break;
case CUBED:
temp = RDiv(INT2REAL(y - Resolution / 2), INT2REAL(Resolution / 2));
yval = RMul(temp, RMul(temp, temp));
break;
}
for (x = 0; x <= Resolution; x++)
{
Vval[v].x = RAdd(xyoffset, RMul(xyscale, INT2REAL(x)));
Vval[v].y = RAdd(xyoffset, RMul(xyscale, INT2REAL(y)));
switch (Zfunc)
{
case XMULY:
Vval[v++].z = RMul(zscale, RMul(xval[x], yval));
break;
case XADDY:
Vval[v++].z = RMul(zscale, RAdd(xval[x], yval));
break;
case XSUBY:
Vval[v++].z = RMul(zscale, RSub(xval[x], yval));
break;
}
}
}
free(xval);
/*--- Remaining vertices form box ---*/
/* first the base */
y = v;
Vval[v].x = xyoffset;
Vval[v].y = xyoffset;
Vval[v++].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
Vval[v].x = xyoffset;
Vval[v].y = -xyoffset;
Vval[v++].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
Vval[v].x = -xyoffset;
Vval[v].y = -xyoffset;
Vval[v++].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
Vval[v].x = -xyoffset;
Vval[v].y = xyoffset;
Vval[v++].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
/* then the sides */
for (x = 0; x <= Resolution; x++)
{
Vval[v + 1] = Vval[(int)(x * (Resolution + 1))];
Vval[v] = Vval[v + 1];
Vval[v].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
v += 2;
}
for (x = 0; x <= Resolution; x++)
{
Vval[v + 1] = Vval[(int)(((Resolution + 1) * (Resolution)) + x)];
Vval[v] = Vval[v + 1];
Vval[v].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
v += 2;
}
for (x = 0; x <= Resolution; x++)
{
Vval[v + 1] = Vval[(int)((Resolution + 1 - x) * (Resolution + 1) - 1)];
Vval[v] = Vval[v + 1];
Vval[v].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
v += 2;
}
for (x = 0; x <= Resolution; x++)
{
Vval[v + 1] = Vval[(int)(Resolution - x)];
Vval[v] = Vval[v + 1];
Vval[v].z = CREAL(-(CUBE_DIMENSION / 2.0 + 0.1));
v += 2;
}
Vertices = v;
}
/***************************************************************************
Move Sheet
***************************************************************************/
void
MoveSheet()
{
RwInt32 i, j, k;
k = (Resolution + 1) * Resolution;
for (i = Resolution + 1; i < k; i += (Resolution + 1))
for (j = 1; j < Resolution; j++)
{
Vval[(int)(i + j)].z = Fn[(int)(((Fnoffset + (i / Resolution) + j) & 7) << 6)];
}
RwSetClumpVertices(Clump, Vindex, Vval, Vertices);
Fnoffset++;
}
/***************************************************************************
BuildSheet
***************************************************************************/
void
BuildSheet(void)
{
RwUV uv;
RwInt32 i, j, v;
RwInt32 box[20];
RwReal xyscale, xyoffset;
xyscale = RDiv(CREAL(CUBE_DIMENSION), INT2REAL(Resolution));
xyoffset = -RMul(CREAL(CUBE_DIMENSION), CREAL(0.5));
if (Clump)
RwDestroyClump(Clump);
RwModelBegin();
RwClumpBegin();
RwSetHints(rwHS | rwEDITABLE);
switch (Shading)
{
case S_FLAT:
RwSetSurfaceLightSampling(rwFACET);
break;
case S_SMOOTH:
RwSetSurfaceLightSampling(rwVERTEX);
break;
}
RwSetSurfaceTexture(TextureNames[Texture]);
RwSetSurface(CREAL(0.3), CREAL(0.6), CREAL(0.3));
RwSetSurfaceColor(CREAL(1.0), CREAL(0.0), CREAL(0.0));
for (i = 0; i <= Resolution; i++)
{
for (j = 0; j <= Resolution; j++)
{
Vval[(int)(i * (Resolution + 1) + j)].x = RAdd(xyoffset, RMul(xyscale, INT2REAL(i)));
Vval[(int)(i * (Resolution + 1) + j)].y = RAdd(xyoffset, RMul(xyscale, INT2REAL(j)));
Vval[(int)(i * (Resolution + 1) + j)].z = CREAL(0.0);
uv.u = (RDiv(INT2REAL(j), INT2REAL(Resolution)));
uv.v = (RDiv(INT2REAL(i), INT2REAL(Resolution)));
v = RwVertexExt(Vval[(int)(i * (Resolution + 1) + j)].x,
Vval[(int)(i * (Resolution + 1) + j)].y,
Vval[(int)(i * (Resolution + 1) + j)].z, &uv, NULL);
}
}
Vertices = v;
box[0] = RwVertex(xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[1] = RwVertex(-xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[2] = RwVertex(-xyoffset, -xyoffset, CREAL(-0.01));
box[3] = RwVertex(xyoffset, -xyoffset, CREAL(-0.01));
box[4] = RwVertex(-xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[5] = RwVertex(xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[6] = RwVertex(xyoffset, xyoffset, CREAL(-0.01));
box[7] = RwVertex(-xyoffset, xyoffset, CREAL(-0.01));
box[8] = RwVertex(-xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[9] = RwVertex(-xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[10] = RwVertex(-xyoffset, xyoffset, CREAL(-0.01));
box[11] = RwVertex(-xyoffset, -xyoffset, CREAL(-0.01));
box[12] = RwVertex(xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[13] = RwVertex(xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[14] = RwVertex(xyoffset, -xyoffset, CREAL(-0.01));
box[15] = RwVertex(xyoffset, xyoffset, CREAL(-0.01));
box[16] = RwVertex(-xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[17] = RwVertex(-xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[18] = RwVertex(xyoffset, -xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
box[19] = RwVertex(xyoffset, xyoffset, CREAL(-(CUBE_DIMENSION / 2.0 + 0.1)));
for (i = 0; i <= Resolution - 1; i++)
for (j = 0; j <= Resolution - 1; j++)
{
RwQuad(i * (Resolution + 1) + j + 1,
(i + 1) * (Resolution + 1) + j + 1,
(i + 1) * (Resolution + 1) + j + 2,
i * (Resolution + 1) + j + 2);
}
RwSetSurfaceTexture(NULL);
RwSetSurfaceColor(CREAL(0.2), CREAL(0.2), CREAL(0.2));
RwSetSurfaceLightSampling(rwFACET);
RwQuad(box[0], box[3], box[2], box[1]);
RwQuad(box[4], box[7], box[6], box[5]);
RwQuad(box[8], box[11], box[10], box[9]);
RwQuad(box[12], box[15], box[14], box[13]);
RwQuad(box[16], box[19], box[18], box[17]);
RwClumpEnd(&Clump);
RwForAllPolygonsInClump(Clump, SetPolygonData);
MoveSheet();
}
/***************************************************************************
BuildClump
***************************************************************************/
void
BuildClump(void)
{
RwUV uv;
RwInt32 x, y;
RwInt32 v;
if (Clump)
RwDestroyClump(Clump);
GeneratePoints();
RwModelBegin();
RwClumpBegin();
RwSetHints(rwHS | rwEDITABLE);
switch (Shading)
{
case S_FLAT:
RwSetSurfaceLightSampling(rwFACET);
break;
case S_SMOOTH:
RwSetSurfaceLightSampling(rwVERTEX);
break;
}
RwSetSurfaceTexture(TextureNames[Texture]);
RwSetSurface(CREAL(0.3), CREAL(0.6), CREAL(0.3));
RwSetSurfaceColor(CREAL(0.0), CREAL(0.0), CREAL(1.0));
for (y = 0; y <= Resolution; y++)
{
for (x = 0; x <= Resolution; x++)
{
uv.u = (RDiv(INT2REAL(x), INT2REAL(Resolution)));
uv.v = (RDiv(INT2REAL(y), INT2REAL(Resolution)));
v = RwVertexExt(Vval[(int)(y * (Resolution + 1) + x)].x,
Vval[(int)(y * (Resolution + 1) + x)].y,
Vval[(int)(y * (Resolution + 1) + x)].z, &uv, NULL);
}
}
for (; v < Vertices; v++)
{
RwVertex(Vval[(int)v].x, Vval[(int)v].y, Vval[(int)v].z);
}
for (y = 0; y < Resolution; y++)
{
for (x = 0; x < Resolution; x++)
{
RwInt32 tl, bl;
bl = y * (Resolution + 1) + 1 + x;
tl = bl + (Resolution + 1);
RwQuad(tl, bl, bl + 1, tl + 1);
}
}
/* Construct Box */
RwSetSurfaceTexture(NULL);
RwSetSurfaceColor(CREAL(0.2), CREAL(0.2), CREAL(0.2));
RwSetSurfaceLightSampling(rwFACET);
v = (Resolution + 1) * (Resolution + 1) + 1;
RwQuad(v, v + 1, v + 2, v + 3);
v += 4;
/* Construct sides */
for (y = 0; y < 4; y++)
{
for (x = 0; x < Resolution; x++)
{
RwQuad(v, v + 1, v + 3, v + 2);
v += 2;
}
v += 2;
}
RwClumpEnd(&Clump);
RwModelEnd();
RwForAllPolygonsInClump(Clump, SetPolygonData);
}
/**************************************************************************
Change Resolution
**************************************************************************/
void
SetResolution(EnResolution ren)
{
static EnResolution r = -1;
CheckMenuItem(Mainmenu, R_MBASE + r, MF_UNCHECKED);
switch (ren)
{
case R_4:
Resolution = 4;
break;
case R_8:
Resolution = 8;
break;
case R_16:
Resolution = 16;
break;
}
if (r != ren) /* new resolution */
{
if (Membrane)
BuildSheet();
else
BuildClump();
}
r = ren;
CheckMenuItem(Mainmenu, R_MBASE + r, MF_CHECKED);
}
/**************************************************************************
Change Polygon shading if it forms the main surface
**************************************************************************/
RwPolygon3d *
SetPolygonTexture(RwPolygon3d * p, RwTexture * t)
{
if (RwGetPolygonData(p))
{
RwSetMaterialTexture(RwGetPolygonMaterial(p), t);
}
return (p);
}
/**************************************************************************
Change Polygon shading if it forms the main surface
**************************************************************************/
RwPolygon3d *
SetPolygonShading(RwPolygon3d * p)
{
if (RwGetPolygonData(p))
{
switch (Shading)
{
case S_FLAT:
RwSetMaterialLightSampling(RwGetPolygonMaterial(p), rwFACET);
break;
case S_SMOOTH:
RwSetMaterialLightSampling(RwGetPolygonMaterial(p), rwVERTEX);
break;
}
}
return (p);
}
/**************************************************************************
Change Texture
**************************************************************************/
void
SetTexture(EnTexture t)
{
RwTexture *tex;
CheckMenuItem(Mainmenu, T_MBASE + Texture, MF_UNCHECKED);
if (Texture != t)
{
Texture = t;
if (Clump)
{
switch (t)
{
case T_NONE:
tex = NULL;
break;
default:
tex = RwGetNamedTexture(TextureNames[t]);
break;
}
RwForAllPolygonsInClumpPointer(Clump,
(RwPolygon3dFuncPointer)SetPolygonTexture, tex);
}
}
CheckMenuItem(Mainmenu, T_MBASE + Texture, MF_CHECKED);
}
/**************************************************************************
Change Shading
**************************************************************************/
void
SetShading(EnShading s)
{
CheckMenuItem(Mainmenu, S_MBASE + Shading, MF_UNCHECKED);
if (Shading != s)
{
Shading = s;
if (Clump)
{
RwForAllPolygonsInClump(Clump, SetPolygonShading);
}
}
CheckMenuItem(Mainmenu, S_MBASE + Shading, MF_CHECKED);
}
/**************************************************************************
Invoke a help function
**************************************************************************/
void
SetHelp(HWND hwnd, EnHelp h)
{
switch (h)
{
case H_ABOUT:
KillTimer(hwnd, 1);
DialogBox(Hinstance, "ABOUT", hwnd, MakeProcInstance(AboutDlgProc, Hinstance));
SetTimer(hwnd, 1, 50, NULL);
break;
}
}
/**************************************************************************
Turn membrane on/off
**************************************************************************/
void
SetMembrane(void)
{
CheckMenuItem(Mainmenu, M_MBASE, MF_UNCHECKED);
if (Membrane) /* currently on - turn it off */
{
Membrane = FALSE;
BuildClump();
}
else
{
Membrane = TRUE;
BuildSheet();
CheckMenuItem(Mainmenu, M_MBASE, MF_CHECKED);
}
}
/**************************************************************************
Change X function
**************************************************************************/
void
SetX(EnFunc x)
{
CheckMenuItem(Mainmenu, X_MBASE + Xfunc, MF_UNCHECKED);
if (Membrane)
{
SetMembrane();
}
if (Xfunc != x)
{
Xfunc = x;
GeneratePoints();
RwSetClumpVertices(Clump, Vindex, Vval, Vertices);
}
CheckMenuItem(Mainmenu, X_MBASE + Xfunc, MF_CHECKED);
}
/**************************************************************************
Change Y function
**************************************************************************/
void
SetY(EnFunc y)
{
CheckMenuItem(Mainmenu, Y_MBASE + Yfunc, MF_UNCHECKED);
if (Membrane)
{
SetMembrane();
}
if (Yfunc != y)
{
Yfunc = y;
GeneratePoints();
RwSetClumpVertices(Clump, Vindex, Vval, Vertices);
}
CheckMenuItem(Mainmenu, Y_MBASE + Yfunc, MF_CHECKED);
}
/**************************************************************************
Change Z function
**************************************************************************/
void
SetZ(EnZFunc z)
{
CheckMenuItem(Mainmenu, Z_MBASE + Zfunc, MF_UNCHECKED);
if (Membrane)
{
SetMembrane();
}
if (Zfunc != z)
{
Zfunc = z;
GeneratePoints();
RwSetClumpVertices(Clump, Vindex, Vval, Vertices);
}
CheckMenuItem(Mainmenu, Z_MBASE + Zfunc, MF_CHECKED);
}
/**************************************************************************
Display Image
**************************************************************************/
void
ShowView(HWND hwnd)
{
HDC hdc;
RwBeginCameraUpdate(Camera, (void *)(DWORD)hwnd);
RwClearCameraViewport(Camera);
if (Clump)
{
RwTransformClump(Clump, Rot.m, rwREPLACE);
RwRenderClump(Clump);
}
RwEndCameraUpdate(Camera);
hdc = GetDC(hwnd);
RwShowCameraImage(Camera, (void *)(DWORD)hdc);
ReleaseDC(hwnd, hdc);
}
/**************************************************************************
Process WM_GETMINMAXINFO messages
**************************************************************************/
void
OnGetMinMaxInfo(MINMAXINFO FAR * minmaxinfo)
{
minmaxinfo->ptMaxSize.x = MAX_WIN_WIDTH;
minmaxinfo->ptMaxSize.y = MAX_WIN_HEIGHT;
minmaxinfo->ptMaxTrackSize.x = MAX_WIN_WIDTH;
minmaxinfo->ptMaxTrackSize.y = MAX_WIN_HEIGHT;
}
/**************************************************************************
Process WM_COMMAND messages
**************************************************************************/
void
OnCommand(HWND hwnd, WPARAM wparam)
{
HCURSOR save_cursor;
save_cursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
if (wparam < Y_MBASE)
SetX(wparam - X_MBASE);
else if (wparam < Z_MBASE)
SetY(wparam - Y_MBASE);
else if (wparam < M_MBASE)
SetZ(wparam - Z_MBASE);
else if (wparam < R_MBASE)
SetMembrane();
else if (wparam < S_MBASE)
SetResolution(wparam - R_MBASE);
else if (wparam < T_MBASE)
SetShading(wparam - S_MBASE);
else if (wparam < H_MBASE)
SetTexture(wparam - T_MBASE);
else
SetHelp(hwnd, wparam - H_MBASE);
SetCursor(save_cursor);
}
/**************************************************************************
Process WM_CREATE messages
**************************************************************************/
LONG
OnCreate(HWND hwnd)
{
char str[64];
int i;
/*--- Create the light ---*/
if (!(Light = RwCreateLight(rwDIRECTIONAL,
CREAL(0.0), CREAL(-1.0), CREAL(-1.0), CREAL(1.0))))
{
MessageBox(hwnd, "Error creating a RenderWare light",
"Renderware Error", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return (-1);
}
/*--- Create the camera. ---*/
if (!(Camera = RwCreateCamera((RwInt32)MAX_WIN_WIDTH, (RwInt32)MAX_WIN_HEIGHT, NULL)))
{
MessageBox(hwnd, "Error creating a RenderWare camera",
"Renderware Error", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return (-1);
}
RwVCMoveCamera(Camera, CREAL(0.0), CREAL(0.0), CREAL(-25.0));
RwSetCameraBackColor(Camera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
RwClearCameraViewport(Camera);
/*--- Create the matrix used for rotations. ---*/
if (!(Rot.m = RwCreateMatrix()))
{
MessageBox(hwnd, "Error creating a RenderWare matrix",
"Renderware Error", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return (-1);
}
RwRotateMatrix(Rot.m, CREAL(1.0), CREAL(0.0), CREAL(0.0), CREAL(-45.0), rwREPLACE);
RwRotateMatrix(Rot.m, CREAL(0.0), CREAL(1.0), CREAL(0.0), CREAL(-30.0), rwPOSTCONCAT);
/*--- Preload all Textures ---*/
for (i = 1; i < sizeof (TextureNames) / sizeof (char *); i++)
{
if (!RwGetNamedTexture(TextureNames[i]))
{
sprintf(str, "Error loading Renderware texture [%s]", TextureNames[i]);
MessageBox(hwnd, str,
"Renderware Error", MB_OK | MB_ICONSTOP | MB_APPLMODAL);
return (-1);
}
}
/*--- Initialise internal data structures ---*/
BuildSinCosTab();
for (i = 0; i < 512; i++)
Fn[i] = FL2REAL(sin((float) i / 512.0 * 6.2831853) / 2.0);
for (i = 0; i < MAX_CLUMP_VERTICES; i++)
Vindex[i] = i + 1;
/* Start Timer */
SetTimer(hwnd, 1, 50, NULL);
SetTexture(DEFAULT_T);
SetShading(DEFAULT_S);
SetResolution(DEFAULT_R);
SetX(DEFAULT_X); /* set default X function */
SetY(DEFAULT_Y); /* set default Y function */
SetZ(DEFAULT_Z); /* set default Z function */
ShowInfo(hwnd);
return (0);
}
/**************************************************************************
Process WM_LBUTTONDOWN messages
**************************************************************************/
void
OnLeftButtonDown(HWND hwnd, LPARAM lparam)
{
RwPickRecord record;
/* Save the cursor position. */
Xprev = LOWORD(lparam);
Yprev = HIWORD(lparam);
Rot.flag = FALSE;
if (Clump && (RwPickClump(Clump, Xprev, Yprev, Camera, &record)) &&
(record.type == rwPICKCLUMP))
{
ShowAppLeftStatus(hwnd, Camera, "Rotate Object");
SetCursor(LoadCursor(NULL, IDC_SIZE));
SetCapture(hwnd);
lb = TRUE;
}
else
{
ShowAppLeftStatus(hwnd, Camera, "Stop Object Rotation");
}
}
/**************************************************************************
Process WM_LBUTTONUP messages
**************************************************************************/
void
OnLeftButtonUp(HWND hwnd)
{
if (lb)
{
ReleaseCapture();
lb = FALSE;
}
ShowAppLeftStatus(hwnd, Camera, "");
}
/**************************************************************************
Process WM_RBUTTONDOWN messages
**************************************************************************/
void
OnRightButtonDown(HWND hwnd, LPARAM lparam)
{
HCURSOR bulb;
Xprev = LOWORD(lparam);
Yprev = HIWORD(lparam);
SetCapture(hwnd);
bulb = LoadCursor(Hinstance, "C_BULB");
if (bulb)
SetCursor(bulb);
rb = TRUE;
ShowAppLeftStatus(hwnd, Camera, "Rotate Light");
}
/**************************************************************************
Process WM_RBUTTONUP messages
**************************************************************************/
void
OnRightButtonUp(HWND hwnd)
{
if (rb)
{
ReleaseCapture();
rb = FALSE;
}
ShowAppLeftStatus(hwnd, Camera, "");
}
/**************************************************************************
Process WM_MOUSEMOVE messages
**************************************************************************/
void
OnMouseMove(LPARAM lparam)
{
RwInt32 x, y, dx, dy;
x = LOWORD(lparam);
y = HIWORD(lparam);
dx = x - Xprev;
dy = y - Yprev;
if (lb)
{
Rot.flag = TRUE;
Rot.dx = dx;
Rot.dy = dy;
RwRotateMatrix(Rot.m, CREAL(0.0), CREAL(1.0), CREAL(0.0), INT2REAL(dx), rwPOSTCONCAT);
RwRotateMatrix(Rot.m, CREAL(1.0), CREAL(0.0), CREAL(0.0), INT2REAL(dy), rwPOSTCONCAT);
}
else if (rb)
{
RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0),
INT2REAL(dx), rwREPLACE);
RwRotateMatrix(RwScratchMatrix(), CREAL(1.0), CREAL(0.0), CREAL(0.0),
INT2REAL(dy), rwPOSTCONCAT);
RwTransformLight(Light, RwScratchMatrix(), rwPOSTCONCAT);
}
else
{
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
Xprev = x;
Yprev = y;
}
/**************************************************************************
Process WM_PAINT messages
**************************************************************************/
void
OnPaint(HWND hwnd)
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
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 *)(DWORD)hdc);
ShowAppLeftStatus(hwnd, Camera, "");
ShowInfo(hwnd);
EndPaint(hwnd, &ps);
}
/**************************************************************************
Process WM_SIZE messages
**************************************************************************/
void
OnSize(HWND hwnd, LPARAM lparam)
{
RwInt32 width;
RwInt32 height;
width = LOWORD(lparam);
height = HIWORD(lparam);
height = StatusAdjustHeight(hwnd, (int)height);
/* Set the camera viewport to match the window's client area. */
RwSetCameraViewport(Camera, 0, 0, width, height);
RwGetCameraViewport(Camera, (RwInt32) NULL, (RwInt32) NULL, &width, &height);
/* Maintain the view window at a 1:1 aspect ratio. */
if ((width != 0) && (height != 0))
{
if (width >= height)
RwSetCameraViewwindow(Camera,
CREAL(0.2),
RMul(CREAL(0.2), RDiv(INT2REAL(height), INT2REAL(width))));
else
RwSetCameraViewwindow(Camera,
RMul(CREAL(0.2), RDiv(INT2REAL(width), INT2REAL(height))),
CREAL(0.2));
}
/* Redisplay the scene. */
ShowView(hwnd);
ShowAppLeftStatus(hwnd, Camera, "");
ShowInfo(hwnd);
}
/**************************************************************************
Process WM_TIMER messages
**************************************************************************/
void
OnTimer(HWND hwnd)
{
static int rcount = 0;
if (Membrane)
MoveSheet();
if ((Clump) && (!lb) && Rot.flag)
{
RwRotateMatrix(Rot.m, CREAL(0.0), CREAL(1.0), CREAL(0.0), INT2REAL(Rot.dx), rwPOSTCONCAT);
RwRotateMatrix(Rot.m, CREAL(1.0), CREAL(0.0), CREAL(0.0), INT2REAL(Rot.dy), rwPOSTCONCAT);
if (!(++rcount % 127))
RwOrthoNormalizeMatrix(Rot.m, Rot.m);
}
ShowView(hwnd);
}
/**************************************************************************
Process WM_DESTROY messages
**************************************************************************/
void
OnDestroy(HWND hwnd)
{
if (Camera)
RwDestroyCamera(Camera);
if (Rot.m)
RwDestroyMatrix(Rot.m);
KillTimer(hwnd, 1);
PostQuitMessage(0);
}
/**************************************************************************
Main event handler
**************************************************************************/
LONG FAR PASCAL
WinVisProc(HWND hwnd, UINT msg,
WPARAM wparam, LPARAM lparam)
{
LONG ret = 0;
switch (msg)
{
case WM_GETMINMAXINFO:
OnGetMinMaxInfo((MINMAXINFO FAR *) MK_FP32((void *) lparam));
break;
case WM_COMMAND:
OnCommand(hwnd, wparam);
ShowInfo(hwnd);
break;
case WM_CREATE:
ret = OnCreate(hwnd);
break;
case WM_LBUTTONDOWN:
OnLeftButtonDown(hwnd, lparam);
break;
case WM_LBUTTONUP:
OnLeftButtonUp(hwnd);
break;
case WM_RBUTTONDOWN:
OnRightButtonDown(hwnd, lparam);
break;
case WM_RBUTTONUP:
OnRightButtonUp(hwnd);
break;
case WM_MOUSEMOVE:
OnMouseMove(lparam);
break;
case WM_PAINT:
OnPaint(hwnd);
break;
case WM_SIZE:
OnSize(hwnd, lparam);
break;
case WM_TIMER:
OnTimer(hwnd);
break;
case WM_DESTROY:
OnDestroy(hwnd);
break;
default:
ret = DefWindowProc(hwnd, msg, wparam, lparam);
break;
}
return (ret);
}
/**************************************************************************
Windows Program Entry Point
**************************************************************************/
int PASCAL
WinMain(HANDLE hinst, HANDLE hprevinst, LPSTR pcmdline,
int ncmdshow)
{
WNDCLASS wc;
MSG msg;
HWND hwnd;
HMENU tempmenu;
char buffer[64];
int i;
if (hprevinst)
{
MessageBox(NULL, "Application is already running", "Error", MB_OK);
return (FALSE);
}
Hinstance = hinst;
/* Register the window class. NULL hIcon means we get an animated
3D icon for free. */
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WinVisProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = Hinstance;
wc.hIcon = LoadIcon(Hinstance, "RW_ICON");
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "RwWinVisClass";
if (!RegisterClass(&wc))
return (FALSE);
/* Initialize RenderWare. */
if (!RwOpen("MSWindows", NULL))
{
MessageBox(NULL, "RwOpen() failed", "Error", MB_OK);
return (FALSE);
}
/*--- Set the shape path to enable texture loading ---*/
GetModuleFileName(Hinstance, buffer, sizeof (buffer));
i = strlen(buffer);
while (buffer[i] != '\\')
i--;
buffer[i + 1] = 0;
strcat(buffer, "TEXTURES");
RwSetShapePath(buffer, rwREPLACE);
RwSetShapePath(".", rwPOSTCONCAT);
/* Create The menus */
Mainmenu = CreateMenu();
tempmenu = CreateMenu();
AppendMenu(tempmenu, MF_STRING, X_MBASE + ZERO, "f(x) = 0");
AppendMenu(tempmenu, MF_STRING, X_MBASE + RAMP, "f(x) = x");
AppendMenu(tempmenu, MF_STRING, X_MBASE + SIN, "f(x) = sin(x)");
AppendMenu(tempmenu, MF_STRING, X_MBASE + COS, "f(x) = cos(x)");
AppendMenu(tempmenu, MF_STRING, X_MBASE + SQUARED, "f(x) = x^2");
AppendMenu(tempmenu, MF_STRING, X_MBASE + CUBED, "f(x) = x^3");
AppendMenu(tempmenu, MF_SEPARATOR, 0, NULL);
AppendMenu(tempmenu, MF_STRING, Y_MBASE + ZERO, "f(y) = 0");
AppendMenu(tempmenu, MF_STRING, Y_MBASE + RAMP, "f(y) = y");
AppendMenu(tempmenu, MF_STRING, Y_MBASE + SIN, "f(y) = sin(y)");
AppendMenu(tempmenu, MF_STRING, Y_MBASE + COS, "f(y) = cos(y)");
AppendMenu(tempmenu, MF_STRING, Y_MBASE + SQUARED, "f(y) = y^2");
AppendMenu(tempmenu, MF_STRING, Y_MBASE + CUBED, "f(y) = y^3");
AppendMenu(tempmenu, MF_SEPARATOR, 0, NULL);
AppendMenu(tempmenu, MF_STRING, Z_MBASE + XMULY, "f(x) * f(y)");
AppendMenu(tempmenu, MF_STRING, Z_MBASE + XADDY, "f(x) + f(y)");
AppendMenu(tempmenu, MF_STRING, Z_MBASE + XSUBY, "f(x) - f(y)");
AppendMenu(tempmenu, MF_SEPARATOR, 0, NULL);
AppendMenu(tempmenu, MF_STRING, M_MBASE, "Membrane");
AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Plot");
tempmenu = CreateMenu();
AppendMenu(tempmenu, MF_STRING, R_MBASE + R_4, "4");
AppendMenu(tempmenu, MF_STRING, R_MBASE + R_8, "8");
AppendMenu(tempmenu, MF_STRING, R_MBASE + R_16, "16");
AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Resolution");
/* Create and show the window. */
tempmenu = CreateMenu();
AppendMenu(tempmenu, MF_STRING, S_MBASE + S_FLAT, "Flat");
AppendMenu(tempmenu, MF_STRING, S_MBASE + S_SMOOTH, "Smooth");
AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Shading");
tempmenu = CreateMenu();
AppendMenu(tempmenu, MF_STRING, T_MBASE + T_NONE, "None");
AppendMenu(tempmenu, MF_STRING, T_MBASE + T_WOOD, "Wood");
AppendMenu(tempmenu, MF_STRING, T_MBASE + T_BRICK, "Brick");
AppendMenu(tempmenu, MF_STRING, T_MBASE + T_MARBLE, "Marble");
AppendMenu(tempmenu, MF_STRING, T_MBASE + T_MANDEL, "Mandelbrot");
AppendMenu(tempmenu, MF_STRING, T_MBASE + T_MANDRILL, "Mandrill");
AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Texture");
tempmenu = CreateMenu();
AppendMenu(tempmenu, MF_STRING, H_MBASE + H_ABOUT, "About");
AppendMenu(Mainmenu, MF_POPUP, (UINT) tempmenu, "&Help");
/* Create and show the window. */
if (!(hwnd = CreateWindow("RwWinVisClass", RWAPPNAME,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 400,
NULL, Mainmenu, Hinstance, NULL)))
{
RwClose();
return (FALSE);
}
CheckDisplayDepth(hwnd);
ShowWindow(hwnd, ncmdshow);
UpdateWindow(hwnd);
/* Main loop. */
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
/* Terminate RenderWare. */
RwClose();
return (msg.wParam);
}