TMcube: C++Builder Version
/****************************************************************************\
* *
* TMcube.cpp *
* TMcubeU.cpp *
* *
* This program draws a texture-mapped cube in 3D world space and allows the *
* user to move and rotate the cube through keyboard controls. A different *
* texture is applied to each cube face. Supports linear or perspective *
* texture mapping, z-buffering, and 3D clipping through the RENDER_STATE *
* symbol defined in TMcubeU.h. *
* *
\****************************************************************************/
#include
#pragma hdrstop
#include "TMcubeU.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnIdle(TObject *Sender, bool &Done)
{
CheckForMovement();
Done = False;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormActivate(TObject *Sender)
{
fg_realize(hPal);
Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
register int i;
hDC = GetDC(Form1->Handle);
fg_setdc(hDC);
hPal = fg_defpal();
fg_realize(hPal);
fg_vbinit();
fg_vbdepth(vbDepth);
hVB = fg_vballoc(vbWidth,vbHeight);
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);
}
fg_setcolor(-1);
fg_fillpage();
Application->OnActivate = OnActivate;
Application->OnIdle = OnIdle;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
fg_vbscale(0,vbWidth-1,0,vbHeight-1,0,cxClient-1,0,cyClient-1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
cxClient = ClientWidth;
cyClient = ClientHeight;
Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
fg_vbclose();
fg_tmfree(-1);
fg_zbfree(hZB);
fg_vbfree(hVB);
fg_vbfin();
DeleteObject(hPal);
ReleaseDC(Form1->Handle,hDC);
}
/****************************************************************************\
* *
* 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 application's OnIdle event handler. *
* *
\****************************************************************************/
void __fastcall TForm1::CheckForMovement()
{
static double xWorld = 0.0, yWorld = 0.0, zWorld = 100.0;
static int xAngle = 0, yAngle = 0, zAngle = 0;
static bool Redraw = True;
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)
{
// 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();
// display what we just drew
fg_vbscale(0,vbWidth-1,0,vbHeight-1,0,cxClient-1,0,cyClient-1);
Redraw = False;
}
}
/****************************************************************************\
* *
* DrawCube() *
* *
* Draws each of the six cube faces in 3D world space. *
* *
\****************************************************************************/
void __fastcall TForm1::DrawCube()
{
register int i;
for (i = 0; i < 6; i++)
{
fg_tmselect(hTM[i]);
fg_3Dtexturemapobject((double *)Faces[i],(int *)tmSource,4);
}
}
|