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
}

<< Prev

Next >>

Contents
Fastgraph Home Page

 

copyright 2001 Ted Gruber Software, Inc.