home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / advanced / cube / cubeview.cpp < prev    next >
C/C++ Source or Header  |  1998-03-26  |  11KB  |  482 lines

  1. // cubeview.cpp : implementation of the CCubeView class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "cube.h"
  15.  
  16. #include "cubedoc.h"
  17. #include "cubeview.h"
  18.  
  19. #include "gl\gl.h"
  20. #include "gl\glu.h"
  21.  
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static char BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26.  
  27. unsigned char threeto8[8] =
  28. {
  29.     0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
  30. };
  31.  
  32. unsigned char twoto8[4] =
  33. {
  34.     0, 0x55, 0xaa, 0xff
  35. };
  36.  
  37. unsigned char oneto8[2] =
  38. {
  39.     0, 255
  40. };
  41.  
  42. static int defaultOverride[13] =
  43. {
  44.     0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
  45. };
  46.  
  47. static PALETTEENTRY defaultPalEntry[20] =
  48. {
  49.     { 0,   0,   0,    0 },
  50.     { 0x80,0,   0,    0 },
  51.     { 0,   0x80,0,    0 },
  52.     { 0x80,0x80,0,    0 },
  53.     { 0,   0,   0x80, 0 },
  54.     { 0x80,0,   0x80, 0 },
  55.     { 0,   0x80,0x80, 0 },
  56.     { 0xC0,0xC0,0xC0, 0 },
  57.  
  58.     { 192, 220, 192,  0 },
  59.     { 166, 202, 240,  0 },
  60.     { 255, 251, 240,  0 },
  61.     { 160, 160, 164,  0 },
  62.  
  63.     { 0x80,0x80,0x80, 0 },
  64.     { 0xFF,0,   0,    0 },
  65.     { 0,   0xFF,0,    0 },
  66.     { 0xFF,0xFF,0,    0 },
  67.     { 0,   0,   0xFF, 0 },
  68.     { 0xFF,0,   0xFF, 0 },
  69.     { 0,   0xFF,0xFF, 0 },
  70.     { 0xFF,0xFF,0xFF, 0 }
  71. };
  72.  
  73. /////////////////////////////////////////////////////////////////////////////
  74. // CCubeView
  75.  
  76. IMPLEMENT_DYNCREATE(CCubeView, CView)
  77.  
  78. BEGIN_MESSAGE_MAP(CCubeView, CView)
  79.     //{{AFX_MSG_MAP(CCubeView)
  80.     ON_COMMAND(ID_FILE_PLAY, OnFilePlay)
  81.     ON_UPDATE_COMMAND_UI(ID_FILE_PLAY, OnUpdateFilePlay)
  82.     ON_WM_CREATE()
  83.     ON_WM_DESTROY()
  84.     ON_WM_SIZE()
  85.     ON_WM_TIMER()
  86.     ON_WM_ERASEBKGND()
  87.     //}}AFX_MSG_MAP
  88. END_MESSAGE_MAP()
  89.  
  90. /////////////////////////////////////////////////////////////////////////////
  91. // CCubeView construction/destruction
  92.  
  93. CCubeView::CCubeView()
  94. {
  95.     m_pDC = NULL;
  96.     m_pOldPalette = NULL;
  97.     m_play = FALSE;
  98. }
  99.  
  100. CCubeView::~CCubeView()
  101. {
  102. }
  103.  
  104. /////////////////////////////////////////////////////////////////////////////
  105. // CCubeView drawing
  106.  
  107. void CCubeView::OnDraw(CDC* pDC)
  108. {
  109.     CCubeDoc* pDoc = GetDocument();
  110.     ASSERT_VALID(pDoc);
  111.  
  112.     DrawScene();
  113. }
  114.  
  115. /////////////////////////////////////////////////////////////////////////////
  116. // CCubeView diagnostics
  117.  
  118. #ifdef _DEBUG
  119. void CCubeView::AssertValid() const
  120. {
  121.     CView::AssertValid();
  122. }
  123.  
  124. void CCubeView::Dump(CDumpContext& dc) const
  125. {
  126.     CView::Dump(dc);
  127. }
  128.  
  129. CCubeDoc* CCubeView::GetDocument() // non-debug version is inline
  130. {
  131.     return STATIC_DOWNCAST(CCubeDoc, m_pDocument);
  132. }
  133. #endif //_DEBUG
  134.  
  135. /////////////////////////////////////////////////////////////////////////////
  136. // CCubeView message handlers
  137.  
  138. void CCubeView::OnFilePlay()
  139. {
  140.     m_play = m_play ? FALSE : TRUE;
  141.     if (m_play)
  142.         SetTimer(1, 15, NULL);
  143.     else
  144.         KillTimer(1);
  145. }
  146.  
  147. void CCubeView::OnUpdateFilePlay(CCmdUI* pCmdUI)
  148. {
  149.     pCmdUI->SetCheck(m_play);
  150. }
  151.  
  152. BOOL CCubeView::PreCreateWindow(CREATESTRUCT& cs)
  153. {
  154.     // An OpenGL window must be created with the following flags and must not
  155.     // include CS_PARENTDC for the class style. Refer to SetPixelFormat
  156.     // documentation in the "Comments" section for further information.
  157.     cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
  158.  
  159.     return CView::PreCreateWindow(cs);
  160. }
  161.  
  162. int CCubeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  163. {
  164.     if (CView::OnCreate(lpCreateStruct) == -1)
  165.         return -1;
  166.  
  167.     Init(); // initialize OpenGL
  168.  
  169.     return 0;
  170. }
  171.  
  172. void CCubeView::OnDestroy()
  173. {
  174.     HGLRC   hrc;
  175.  
  176.     KillTimer(1);
  177.  
  178.     hrc = ::wglGetCurrentContext();
  179.  
  180.     ::wglMakeCurrent(NULL,  NULL);
  181.  
  182.     if (hrc)
  183.         ::wglDeleteContext(hrc);
  184.  
  185.     if (m_pOldPalette)
  186.         m_pDC->SelectPalette(m_pOldPalette, FALSE);
  187.  
  188.     if (m_pDC)
  189.         delete m_pDC;
  190.  
  191.     CView::OnDestroy();
  192. }
  193.  
  194. void CCubeView::OnSize(UINT nType, int cx, int cy)
  195. {
  196.     CView::OnSize(nType, cx, cy);
  197.  
  198.     if(cy > 0)
  199.     {
  200.         glViewport(0, 0, cx, cy);
  201.  
  202.         if((m_oldRect.right > cx) || (m_oldRect.bottom > cy))
  203.             RedrawWindow();
  204.  
  205.         m_oldRect.right = cx;
  206.         m_oldRect.bottom = cy;
  207.  
  208.         glMatrixMode(GL_PROJECTION);
  209.         glLoadIdentity();
  210.         gluPerspective(45.0f, (GLdouble)cx/cy, 3.0f, 7.0f);
  211.         glMatrixMode(GL_MODELVIEW);
  212.     }
  213. }
  214.  
  215. void CCubeView::OnTimer(UINT nIDEvent)
  216. {
  217.     DrawScene();
  218.  
  219.     CView::OnTimer(nIDEvent);
  220.  
  221.     // Eat spurious WM_TIMER messages
  222.     MSG msg;
  223.     while(::PeekMessage(&msg, m_hWnd, WM_TIMER, WM_TIMER, PM_REMOVE));
  224. }
  225.  
  226. /////////////////////////////////////////////////////////////////////////////
  227. // GL helper functions
  228.  
  229. void CCubeView::Init()
  230. {
  231.     PIXELFORMATDESCRIPTOR pfd;
  232.     int         n;
  233.     HGLRC       hrc;
  234.     GLfloat     fMaxObjSize, fAspect;
  235.     GLfloat     fNearPlane, fFarPlane;
  236.  
  237.     m_pDC = new CClientDC(this);
  238.  
  239.     ASSERT(m_pDC != NULL);
  240.  
  241.     if (!bSetupPixelFormat())
  242.         return;
  243.  
  244.     n = ::GetPixelFormat(m_pDC->GetSafeHdc());
  245.     ::DescribePixelFormat(m_pDC->GetSafeHdc(), n, sizeof(pfd), &pfd);
  246.  
  247.     CreateRGBPalette();
  248.  
  249.     hrc = wglCreateContext(m_pDC->GetSafeHdc());
  250.     wglMakeCurrent(m_pDC->GetSafeHdc(), hrc);
  251.  
  252.     GetClientRect(&m_oldRect);
  253.     glClearDepth(1.0f);
  254.     glEnable(GL_DEPTH_TEST);
  255.  
  256.     if (m_oldRect.bottom)
  257.         fAspect = (GLfloat)m_oldRect.right/m_oldRect.bottom;
  258.     else    // don't divide by zero, not that we should ever run into that...
  259.         fAspect = 1.0f;
  260.     fNearPlane = 3.0f;
  261.     fFarPlane = 7.0f;
  262.     fMaxObjSize = 3.0f;
  263.     m_fRadius = fNearPlane + fMaxObjSize / 2.0f;
  264.  
  265.     glMatrixMode(GL_PROJECTION);
  266.     glLoadIdentity();
  267.     gluPerspective(45.0f, fAspect, fNearPlane, fFarPlane);
  268.     glMatrixMode(GL_MODELVIEW);
  269. }
  270.  
  271. BOOL CCubeView::bSetupPixelFormat()
  272. {
  273.     static PIXELFORMATDESCRIPTOR pfd =
  274.     {
  275.         sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
  276.         1,                              // version number
  277.         PFD_DRAW_TO_WINDOW |            // support window
  278.           PFD_SUPPORT_OPENGL |          // support OpenGL
  279.           PFD_DOUBLEBUFFER,             // double buffered
  280.         PFD_TYPE_RGBA,                  // RGBA type
  281.         24,                             // 24-bit color depth
  282.         0, 0, 0, 0, 0, 0,               // color bits ignored
  283.         0,                              // no alpha buffer
  284.         0,                              // shift bit ignored
  285.         0,                              // no accumulation buffer
  286.         0, 0, 0, 0,                     // accum bits ignored
  287.         32,                             // 32-bit z-buffer
  288.         0,                              // no stencil buffer
  289.         0,                              // no auxiliary buffer
  290.         PFD_MAIN_PLANE,                 // main layer
  291.         0,                              // reserved
  292.         0, 0, 0                         // layer masks ignored
  293.     };
  294.     int pixelformat;
  295.  
  296.     if ( (pixelformat = ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) == 0 )
  297.     {
  298.         MessageBox("ChoosePixelFormat failed");
  299.         return FALSE;
  300.     }
  301.  
  302.     if (SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE)
  303.     {
  304.         MessageBox("SetPixelFormat failed");
  305.         return FALSE;
  306.     }
  307.  
  308.     return TRUE;
  309. }
  310.  
  311. unsigned char CCubeView::ComponentFromIndex(int i, UINT nbits, UINT shift)
  312. {
  313.     unsigned char val;
  314.  
  315.     val = (unsigned char) (i >> shift);
  316.     switch (nbits)
  317.     {
  318.  
  319.     case 1:
  320.         val &= 0x1;
  321.         return oneto8[val];
  322.     case 2:
  323.         val &= 0x3;
  324.         return twoto8[val];
  325.     case 3:
  326.         val &= 0x7;
  327.         return threeto8[val];
  328.  
  329.     default:
  330.         return 0;
  331.     }
  332. }
  333.  
  334.  
  335. void CCubeView::CreateRGBPalette()
  336. {
  337.     PIXELFORMATDESCRIPTOR pfd;
  338.     LOGPALETTE *pPal;
  339.     int n, i;
  340.  
  341.     n = ::GetPixelFormat(m_pDC->GetSafeHdc());
  342.     ::DescribePixelFormat(m_pDC->GetSafeHdc(), n, sizeof(pfd), &pfd);
  343.  
  344.     if (pfd.dwFlags & PFD_NEED_PALETTE)
  345.     {
  346.         n = 1 << pfd.cColorBits;
  347.         pPal = (PLOGPALETTE) new char[sizeof(LOGPALETTE) + n * sizeof(PALETTEENTRY)];
  348.  
  349.         ASSERT(pPal != NULL);
  350.  
  351.         pPal->palVersion = 0x300;
  352.         pPal->palNumEntries = n;
  353.         for (i=0; i<n; i++)
  354.         {
  355.             pPal->palPalEntry[i].peRed =
  356.                     ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift);
  357.             pPal->palPalEntry[i].peGreen =
  358.                     ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift);
  359.             pPal->palPalEntry[i].peBlue =
  360.                     ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift);
  361.             pPal->palPalEntry[i].peFlags = 0;
  362.         }
  363.  
  364.         /* fix up the palette to include the default GDI palette */
  365.         if ((pfd.cColorBits == 8)                           &&
  366.             (pfd.cRedBits   == 3) && (pfd.cRedShift   == 0) &&
  367.             (pfd.cGreenBits == 3) && (pfd.cGreenShift == 3) &&
  368.             (pfd.cBlueBits  == 2) && (pfd.cBlueShift  == 6)
  369.            )
  370.         {
  371.             for (i = 1 ; i <= 12 ; i++)
  372.                 pPal->palPalEntry[defaultOverride[i]] = defaultPalEntry[i];
  373.         }
  374.  
  375.         m_cPalette.CreatePalette(pPal);
  376.         delete pPal;
  377.  
  378.         m_pOldPalette = m_pDC->SelectPalette(&m_cPalette, FALSE);
  379.         m_pDC->RealizePalette();
  380.     }
  381. }
  382.  
  383. void CCubeView::DrawScene(void)
  384. {
  385.     static BOOL     bBusy = FALSE;
  386.     static GLfloat  wAngleY = 10.0f;
  387.     static GLfloat  wAngleX = 1.0f;
  388.     static GLfloat  wAngleZ = 5.0f;
  389.  
  390.     if(bBusy)
  391.         return;
  392.     bBusy = TRUE;
  393.  
  394.     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  395.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  396.  
  397.     glPushMatrix();
  398.  
  399.         glTranslatef(0.0f, 0.0f, -m_fRadius);
  400.         glRotatef(wAngleX, 1.0f, 0.0f, 0.0f);
  401.         glRotatef(wAngleY, 0.0f, 1.0f, 0.0f);
  402.         glRotatef(wAngleZ, 0.0f, 0.0f, 1.0f);
  403.  
  404.         wAngleX += 1.0f;
  405.         wAngleY += 10.0f;
  406.         wAngleZ += 5.0f;
  407.  
  408.  
  409.         glBegin(GL_QUAD_STRIP);
  410.             glColor3f(1.0f, 0.0f, 1.0f);
  411.             glVertex3f(-0.5f, 0.5f, 0.5f);
  412.  
  413.             glColor3f(1.0f, 0.0f, 0.0f);
  414.             glVertex3f(-0.5f, -0.5f, 0.5f);
  415.  
  416.             glColor3f(1.0f, 1.0f, 1.0f);
  417.             glVertex3f(0.5f, 0.5f, 0.5f);
  418.  
  419.             glColor3f(1.0f, 1.0f, 0.0f);
  420.             glVertex3f(0.5f, -0.5f, 0.5f);
  421.  
  422.             glColor3f(0.0f, 1.0f, 1.0f);
  423.             glVertex3f(0.5f, 0.5f, -0.5f);
  424.  
  425.             glColor3f(0.0f, 1.0f, 0.0f);
  426.             glVertex3f(0.5f, -0.5f, -0.5f);
  427.  
  428.             glColor3f(0.0f, 0.0f, 1.0f);
  429.             glVertex3f(-0.5f, 0.5f, -0.5f);
  430.  
  431.             glColor3f(0.0f, 0.0f, 0.0f);
  432.             glVertex3f(-0.5f, -0.5f,  -0.5f);
  433.  
  434.             glColor3f(1.0f, 0.0f, 1.0f);
  435.             glVertex3f(-0.5f, 0.5f, 0.5f);
  436.  
  437.             glColor3f(1.0f, 0.0f, 0.0f);
  438.             glVertex3f(-0.5f, -0.5f, 0.5f);
  439.  
  440.         glEnd();
  441.  
  442.         glBegin(GL_QUADS);
  443.             glColor3f(1.0f, 0.0f, 1.0f);
  444.             glVertex3f(-0.5f, 0.5f, 0.5f);
  445.  
  446.             glColor3f(1.0f, 1.0f, 1.0f);
  447.             glVertex3f(0.5f, 0.5f, 0.5f);
  448.  
  449.             glColor3f(0.0f, 1.0f, 1.0f);
  450.             glVertex3f(0.5f, 0.5f, -0.5f);
  451.  
  452.             glColor3f(0.0f, 0.0f, 1.0f);
  453.             glVertex3f(-0.5f, 0.5f, -0.5f);
  454.         glEnd();
  455.  
  456.         glBegin(GL_QUADS);
  457.             glColor3f(1.0f, 0.0f, 0.0f);
  458.             glVertex3f(-0.5f, -0.5f, 0.5f);
  459.  
  460.             glColor3f(1.0f, 1.0f, 0.0f);
  461.             glVertex3f(0.5f, -0.5f, 0.5f);
  462.  
  463.             glColor3f(0.0f, 1.0f, 0.0f);
  464.             glVertex3f(0.5f, -0.5f, -0.5f);
  465.  
  466.             glColor3f(0.0f, 0.0f, 0.0f);
  467.             glVertex3f(-0.5f, -0.5f,  -0.5f);
  468.         glEnd();
  469.  
  470.     glPopMatrix();
  471.  
  472.     glFinish();
  473.     SwapBuffers(wglGetCurrentDC());
  474.  
  475.     bBusy = FALSE;
  476. }
  477.  
  478. BOOL CCubeView::OnEraseBkgnd(CDC* pDC)
  479. {
  480.     return TRUE;
  481. }
  482.