TMcubeX: C/C++ Version
/****************************************************************************\
* *
* TMcubeX.c *
* *
* This program is similar to the TMcube example, but it shows how to create *
* a native, DirectDraw, or Direct3D program from the same source code. *
* *
\****************************************************************************/
#include
#define RENDER_STATE (FG_PERSPECTIVE_TM | FG_ZBUFFER | FG_ZCLIP)
// define DIRECTX if creating a DirectDraw or Direct3D application
#define DIRECTX
// define the flag bits for fg_ddsetup()
// specify FG_DX_FLIP for a Direct3D application
// specify FG_DX_RENDER_HW or FG_DX_RENDER_SW for a Direct3D application
// specify FG_DX_ZBUFFER only if FG_ZBUFFER is defined in RENDER_STATE
#define DIRECTX_FLAGS (FG_DX_FLIP | FG_DX_RENDER_HW | FG_DX_ZBUFFER)
#define vbWidth 640
#define vbHeight 480
#define vbDepth 16
#define tmWidth 64
typedef struct point3d
{
double x;
double y;
double z;
} POINT3D;
// six faces of a 40x40x40 cube, defined in object coordinates
POINT3D Face1[] = {
{ 20.0,-20.0,-20.0},
{-20.0,-20.0,-20.0},
{-20.0, 20.0,-20.0},
{ 20.0, 20.0,-20.0}
};
POINT3D Face2[] = {
{-20.0,-20.0,-20.0},
{-20.0,-20.0, 20.0},
{-20.0, 20.0, 20.0},
{-20.0, 20.0,-20.0}
};
POINT3D Face3[] = {
{ 20.0, 20.0, 20.0},
{-20.0, 20.0, 20.0},
{-20.0,-20.0, 20.0},
{ 20.0,-20.0, 20.0}
};
POINT3D Face4[] = {
{ 20.0,-20.0, 20.0},
{ 20.0,-20.0,-20.0},
{ 20.0, 20.0,-20.0},
{ 20.0, 20.0, 20.0}
};
POINT3D Face5[] = {
{ 20.0,-20.0, 20.0},
{-20.0,-20.0, 20.0},
{-20.0,-20.0,-20.0},
{ 20.0,-20.0,-20.0}
};
POINT3D Face6[] = {
{ 20.0, 20.0,-20.0},
{-20.0, 20.0,-20.0},
{-20.0, 20.0, 20.0},
{ 20.0, 20.0, 20.0}
};
// for convenience, an array of pointers to each of the six faces
POINT3D *Faces[] = {Face1,Face2,Face3,Face4,Face5,Face6};
// texture map array
BYTE Texture[6][tmWidth*tmWidth*(vbDepth/8)];
// coordinates defining source polygon vertices within the texture map array
int tmSource[] = {tmWidth-1,tmWidth-1, 0,tmWidth-1, 0,0, tmWidth-1,0};
BOOL AppIsActive = FALSE;
BOOL AppIsReady = FALSE;
LRESULT CALLBACK WindowProc(HWND,UINT,WPARAM,LPARAM);
void CheckForMovement(BOOL);
void DrawCube(void);
void ShowCube(void);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdParam, int iCmdShow)
{
static char szAppName[] = "FGtmcubex";
HWND hWnd;
MSG msg;
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
RegisterClassEx(&wndclass);
hWnd = CreateWindowEx(
WS_EX_TOPMOST, // extended window style
szAppName, // window class name
"Texture-Mapped Cube", // window caption
WS_POPUP, // window style
0, // initial x position
0, // initial y position
vbWidth, // initial x size
vbHeight, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hWnd,iCmdShow);
UpdateWindow(hWnd);
// The message loop processes entries placed in the message queue.
// When no message is ready, call CheckForMovement() to check if
// we want to perform movement.
while (TRUE)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else if (AppIsActive)
CheckForMovement(FALSE);
}
return msg.wParam;
}
/****************************************************************************\
* *
* WindowProc() *
* *
\****************************************************************************/
HDC hDC;
HPALETTE hPal;
int hVB;
int hZB;
int hTM[6];
LRESULT CALLBACK WindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
register int i;
switch (iMsg)
{
case WM_ACTIVATEAPP:
AppIsActive = wParam;
if (AppIsActive && AppIsReady)
{
#ifdef DIRECTX
fg_ddrestore();
#endif
CheckForMovement(TRUE);
}
return 0;
case WM_CREATE:
ShowWindow(hWnd,SW_SHOWNORMAL);
#ifdef DIRECTX
fg_ddsetup(vbWidth,vbHeight,vbDepth,DIRECTX_FLAGS);
#else
fg_modeset(vbWidth,vbHeight,fg_colors(),1);
#endif
hDC = GetDC(hWnd);
fg_setdc(hDC);
hPal = fg_defpal();
fg_realize(hPal);
fg_vbinit();
fg_vbdepth(vbDepth);
#ifdef DIRECTX
hVB = 0;
#else
hVB = fg_vballoc(vbWidth,vbHeight);
#endif
fg_vbopen(hVB);
fg_vbcolors();
hZB = fg_zballoc(vbWidth,vbHeight);
fg_zbopen(hZB);
// define 3D viewport, clipping planes, and initial render state
fg_3Dviewport(0,vbWidth-1,0,vbHeight-1,0.5);
fg_3Dsetzclip(40.0,1000.0);
fg_3Drenderstate(RENDER_STATE);
// obtain the six texture maps from the CUBE.PCX file
fg_tminit(6);
fg_showpcx("CUBE.PCX",FG_AT_XY|FG_KEEPCOLORS);
fg_move(0,tmWidth-1);
for (i = 0; i < 6; i++)
{
#if (vbDepth == 8)
fg_getimage(Texture[i],tmWidth,tmWidth);
fg_invert(Texture[i],tmWidth,tmWidth);
#else
fg_getdcb(Texture[i],tmWidth,tmWidth);
fg_invdcb(Texture[i],tmWidth,tmWidth);
#endif
hTM[i] = fg_tmdefine(Texture[i],tmWidth,tmWidth);
fg_moverel(tmWidth,0);
}
CheckForMovement(TRUE);
AppIsReady = TRUE;
return 0;
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
case VK_F12:
DestroyWindow(hWnd);
break;
}
return 0;
case WM_SETFOCUS:
fg_realize(hPal);
return 0;
case WM_DESTROY:
fg_vbclose();
fg_tmfree(-1);
fg_zbfree(hZB);
#ifdef DIRECTX
fg_vbfin();
#else
fg_vbfree(hVB);
fg_vbfin();
fg_modeset(0,0,0,0);
#endif
DeleteObject(hPal);
ReleaseDC(hWnd,hDC);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd,iMsg,wParam,lParam);
}
/****************************************************************************\
* *
* CheckForMovement() *
* *
* The CheckForMovement() function checks for key presses that control the *
* cube's movement, and if required redraws the cube at its new position and *
* orientation. It is called from the WinMain() message loop when there are *
* no messages waiting. *
* *
* The Redraw parameter controls when CheckForMovement() redraws the cube. *
* If FALSE, the cube is redrawn only if its position or orientation has *
* changed since the last call. If TRUE, the cube is redrawn no matter what. *
* *
\****************************************************************************/
void CheckForMovement(BOOL Redraw)
{
static double xWorld = 0.0, yWorld = 0.0, zWorld = 100.0;
static int xAngle = 0, yAngle = 0, zAngle = 0;
BOOL ShiftKey;
// check if either shift key is pressed
ShiftKey = fg_kbtest(42) | fg_kbtest(54);
// + and - move cube along the z axis (+ is toward viewer, - is
// away from viewer)
if (fg_kbtest(74))
{
zWorld += 3.0;
Redraw = TRUE;
}
else if (fg_kbtest(78))
{
zWorld -= 3.0;
Redraw = TRUE;
}
// left and right arrow keys move cube along x axis
else if (fg_kbtest(75))
{
xWorld -= 3.0;
Redraw = TRUE;
}
else if (fg_kbtest(77))
{
xWorld += 3.0;
Redraw = TRUE;
}
// up and down arrow keys move cube along y axis
else if (fg_kbtest(72))
{
yWorld += 3.0;
Redraw = TRUE;
}
else if (fg_kbtest(80))
{
yWorld -= 3.0;
Redraw = TRUE;
}
// x rotates counterclockwise around x axis, X rotates clockwise
else if (fg_kbtest(45))
{
if (ShiftKey)
{
xAngle += 6;
if (xAngle >= 360) xAngle -= 360;
}
else
{
xAngle -= 6;
if (xAngle < 0) xAngle += 360;
}
Redraw = TRUE;
}
// y rotates counterclockwise around y axis, Y rotates clockwise
else if (fg_kbtest(21))
{
if (ShiftKey)
{
yAngle += 6;
if (yAngle >= 360) yAngle -= 360;
}
else
{
yAngle -= 6;
if (yAngle < 0) yAngle += 360;
}
Redraw = TRUE;
}
// z rotates counterclockwise around z axis, Z rotates clockwise
else if (fg_kbtest(44))
{
if (ShiftKey)
{
zAngle += 6;
if (zAngle >= 360) zAngle -= 360;
}
else
{
zAngle -= 6;
if (zAngle < 0) zAngle += 360;
}
Redraw = TRUE;
}
// if the cube's position or rotation changed, redraw the cube
if (Redraw)
{
#ifdef DIRECTX
// tell Direct3D we're about to start a new frame
fg_ddframe(0);
#endif
// prepare the z-buffer for the next frame
fg_zbframe();
// erase the previous frame from the virtual buffer
fg_setcolor(-1);
fg_fillpage();
// define the cube's new position and rotation in 3D world space
fg_3Dsetobject(xWorld,yWorld,zWorld,xAngle*10,yAngle*10,zAngle*10);
// draw the cube
DrawCube();
#ifdef DIRECTX
// tell Direct3D we're finished with this frame
fg_ddframe(1);
#endif
// display what we just drew
ShowCube();
}
}
/****************************************************************************\
* *
* DrawCube() *
* *
* Draws each of the six cube faces in 3D world space. *
* *
\****************************************************************************/
void DrawCube()
{
register int i;
for (i = 0; i < 6; i++)
{
fg_tmselect(hTM[i]);
fg_3Dtexturemapobject((double *)Faces[i],(int *)tmSource,4);
}
}
/****************************************************************************\
* *
* ShowCube() *
* *
* Performs a blit or flip to make the cube visible. *
* *
\****************************************************************************/
void ShowCube()
{
#ifdef DIRECTX
fg_ddflip();
#else
fg_vbpaste(0,vbWidth-1,0,vbHeight-1,0,vbHeight-1);
#endif
}
|