COpenGLView.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:17k
源码类别:

游戏

开发平台:

Visual C++

  1. // Copyright 1996, Microsoft Systems Journal.
  2. /////////////////////////////////////////////////////////////////////////////
  3. //
  4. // COpenGLView.cpp : implementation of the COpenGLView class
  5. //
  6. /////////////////////////////////////////////////////////////////////////////
  7. #include "stdafx.h"
  8. //#include "resource.h"       // main symbols
  9. #include "COpenGLView.h"
  10. #include <mmsystem.h> // for MM timers (you'll need WINMM.LIB)
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. // add support for OpenGL 1.1 if we're using an old header
  17. // These are new PIXELFORMATDESCRIPTOR flags for OpenGL 1.1
  18. #ifndef PFD_GENERIC_ACCELERATED
  19. #define PFD_GENERIC_ACCELERATED 0x00001000
  20. #endif
  21. #ifndef PFD_DEPTH_DONTCARE
  22. #define PFD_DEPTH_DONTCARE 0x20000000
  23. #endif
  24. #define INSTALLABLE_DRIVER_TYPE_MASK  (PFD_GENERIC_ACCELERATED|PFD_GENERIC_FORMAT)
  25. /////////////////////////////////////////////////////////////////////////////
  26. const char* const COpenGLView::_ErrorStrings[]= {
  27. {"No Error"}, // 0
  28. {"Unable to get a DC"}, // 1
  29. {"ChoosePixelFormat failed"}, // 2
  30. {"SelectPixelFormat failed"}, // 3
  31. {"wglCreateContext failed"}, // 4
  32. {"wglMakeCurrent failed"}, // 5
  33. {"wglDeleteContext failed"}, // 6
  34. {"SwapBuffers failed"}, // 7
  35. };
  36. /////////////////////////////////////////////////////////////////////////////
  37. // COpenGLView
  38. IMPLEMENT_DYNCREATE(COpenGLView, CView)
  39. BEGIN_MESSAGE_MAP(COpenGLView, CView)
  40. //{{AFX_MSG_MAP(COpenGLView)
  41. ON_WM_CREATE()
  42. ON_WM_DESTROY()
  43. ON_WM_ERASEBKGND()
  44. ON_WM_SIZE()
  45. // If you don't have an ID_ANIMATE, you can either add one
  46. // to your menu (Add an Animate command) or comment out the
  47. // references
  48. //#if defined ID_ANIMATE
  49. // ON_COMMAND(ID_ANIMATE, OnAnimate)
  50. // ON_UPDATE_COMMAND_UI(ID_ANIMATE, OnUpdateAnimate)
  51. //#else
  52. // #pragma message( "No Animation Accelerator Interface Defined in COpenGLView" )
  53. //#endif
  54. ON_WM_KEYDOWN()
  55. //}}AFX_MSG_MAP
  56. END_MESSAGE_MAP()
  57. /////////////////////////////////////////////////////////////////////////////
  58. // COpenGLView construction/destruction
  59. COpenGLView::COpenGLView() :
  60. m_PixelFormat(0),m_hRC(0), m_pDC(0),
  61. m_ErrorString(_ErrorStrings[0])
  62. {
  63. // TODO: add construction code here
  64. }
  65. /////////////////////////////////////////////////////////////////////////////
  66. COpenGLView::~COpenGLView()
  67. {
  68. }
  69. /////////////////////////////////////////////////////////////////////////////
  70. BOOL COpenGLView::PreCreateWindow(CREATESTRUCT& cs) 
  71. {
  72. // TODO: Add your specialized code here and/or call the base class
  73. // An OpenGL window must be created with the following flags and must not
  74.     // include CS_PARENTDC for the class style. Refer to SetPixelFormat
  75.     // documentation in the "Comments" section for further information.
  76.     cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
  77. return CView::PreCreateWindow(cs);
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. // COpenGLView drawing
  81. void COpenGLView::OnDraw(CDC* pDC)
  82. {
  83. CDocument* pDoc = GetDocument();
  84. ASSERT_VALID(pDoc);
  85. // Clear out the color & depth buffers
  86. ::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  87. PreRenderScene();
  88. ::glPushMatrix();
  89. RenderStockScene();
  90.   ::glPopMatrix();
  91. ::glPushMatrix();
  92. RenderScene();
  93. ::glPopMatrix();
  94. // Tell OpenGL to flush its pipeline
  95. ::glFinish();
  96. // Now Swap the buffers
  97. if ( FALSE == ::SwapBuffers( m_pDC->GetSafeHdc() ) )
  98. {
  99. SetError(7);
  100. }
  101. PostRenderScene();
  102. }
  103. //////////////////////////////////////////////////////////////////////////////
  104. // PostRenderScene
  105. // perform post display processing
  106. //
  107. // The default PostRenderScene places the framerate in the
  108. // view's title. Replace this with your own title if you like.
  109. void COpenGLView::PostRenderScene( void )
  110. {
  111. }
  112. /////////////////////////////////////////////////////////////////////////////
  113. // COpenGLView diagnostics
  114. #ifdef _DEBUG
  115. /////////////////////////////////////////////////////////////////////////////
  116. void COpenGLView::AssertValid() const
  117. {
  118. CView::AssertValid();
  119. }
  120. /////////////////////////////////////////////////////////////////////////////
  121. void COpenGLView::Dump(CDumpContext& dc) const
  122. {
  123. CView::Dump(dc);
  124. }
  125. /////////////////////////////////////////////////////////////////////////////
  126. CDocument* COpenGLView::GetDocument() // non-debug version is inline
  127. {
  128. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDocument)));
  129. return (CDocument*)m_pDocument;
  130. }
  131. #endif //_DEBUG
  132. /////////////////////////////////////////////////////////////////////////////
  133. int COpenGLView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  134. {
  135. if (CView::OnCreate(lpCreateStruct) == -1)
  136. return -1;
  137. InitializeOpenGL();
  138. return 0;
  139. }
  140. /////////////////////////////////////////////////////////////////////////////
  141. void COpenGLView::OnDestroy() 
  142. {
  143. CView::OnDestroy();
  144. // TODO: Add your message handler code here
  145. // NOTE:wglDeleteContext makes the RC non-current, so this step is unnecessary
  146. // (but you can do it if it makes you feel secure)
  147. //    if ( FALSE ==  ::wglMakeCurrent( 0, 0 ) )
  148. // {
  149. // SetError(2);
  150. //        return FALSE;
  151. // }
  152.     if ( FALSE == ::wglDeleteContext( m_hRC ) )
  153. {
  154. SetError(6);
  155.   }
  156. // For Color-Index mode, you should reset the palette to the original here
  157.     if ( m_pDC )
  158. {
  159.         delete m_pDC;
  160. }
  161. }
  162. /////////////////////////////////////////////////////////////////////////////
  163. // OnEraseBkgnd
  164. // OpenGL has its own routine to erase the background. Here we tell MFC
  165. // not to do it, that we'll take care of it. If we didn't the scene might
  166. // flash.
  167. BOOL COpenGLView::OnEraseBkgnd(CDC* pDC) 
  168. {
  169. // TODO: Add your message handler code here and/or call default
  170. // return CView::OnEraseBkgnd(pDC);
  171. return TRUE; // tell Windows not to erase the background
  172. }
  173. /////////////////////////////////////////////////////////////////////////////
  174. // OnSize
  175. // We need to set up the viewport when the size changes, and this is the best
  176. // place for it, as long as you don't need to render more than one scene, in which
  177. // case you'd have to do it just before each scene gets rendered.
  178. // We also set up the viewing volumn here since we're using perspective mode. For
  179. // Orthographic you could do it anywhere since you don't need the aspect ratio.
  180. // Finally we also set up the default veiwing transform. For an animated scene you'd
  181. // have to do it just before the scene was rendered.
  182. void COpenGLView::OnSize(UINT nType, int cx, int cy) 
  183. {
  184. CView::OnSize(nType, cx, cy);
  185. // TODO: Add your message handler code here
  186. GLdouble aspect_ratio; // width/height ratio
  187. if ( 0 >= cx || 0 >= cy )
  188. {
  189. return;
  190. }
  191. SetupViewport( cx, cy );
  192. // compute the aspect ratio
  193. // this will keep all dimension scales equal
  194. aspect_ratio = (GLdouble)cx/(GLdouble)cy;
  195. // select the projection matrix and clear it
  196.     ::glMatrixMode(GL_PROJECTION);
  197.     ::glLoadIdentity();
  198. // select the viewing volumn
  199. SetupViewingFrustum( aspect_ratio );
  200. // switch back to the modelview matrix and clear it
  201.     ::glMatrixMode(GL_MODELVIEW);
  202.     ::glLoadIdentity();
  203.   
  204. // now perform any viewing transformations
  205. SetupViewingTransform();
  206. }
  207. //////////////////////////////////////////////////////////////////////////////
  208. // SetError-error string manipulation
  209. /////////////////////////////////////////////////////////////////////////////
  210. void COpenGLView::SetError( int e )
  211. {
  212. // if there was no previous error,
  213. // then save this one
  214. if ( _ErrorStrings[0] == m_ErrorString ) 
  215. {
  216. m_ErrorString = _ErrorStrings[e];
  217. }
  218. }
  219. //////////////////////////////////////////////////////////////////////////////
  220. // InitializeOpenGL
  221. // - just that. This is set up for RGB mode, though I've indicated
  222. // where you would add code for color-index mode.
  223. BOOL COpenGLView::InitializeOpenGL()
  224. {
  225. // Can we put this in the constructor?
  226.     m_pDC = new CClientDC(this);
  227.     if ( NULL == m_pDC ) // failure to get DC
  228. {
  229. SetError(1);
  230. return FALSE;
  231. }
  232. if (!SetupPixelFormat())
  233. {
  234.         return FALSE;
  235. }
  236. // For Color-Index mode, you'd probably create your palette here, right
  237. // after you select the pixel format
  238.     if ( 0 == (m_hRC = ::wglCreateContext( m_pDC->GetSafeHdc() ) ) )
  239. {
  240. SetError(4);
  241. return FALSE;
  242. }
  243.     if ( FALSE == ::wglMakeCurrent( m_pDC->GetSafeHdc(), m_hRC ) )
  244. {
  245. SetError(5);
  246. return FALSE;
  247. }
  248. // specify black as clear color
  249.     ::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  250. // specify the back of the buffer as clear depth
  251.     ::glClearDepth(1.0f);
  252. // enable depth testing
  253.     ::glEnable(GL_DEPTH_TEST);
  254. return TRUE;
  255. }
  256. /////////////////////////////////////////////////////////////////////////////
  257. BOOL COpenGLView::SetupPixelFormat()
  258. {
  259.   static PIXELFORMATDESCRIPTOR pfd = 
  260. {
  261.         sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
  262.         1,                              // version number
  263.         PFD_DRAW_TO_WINDOW |            // support window
  264.           PFD_SUPPORT_OPENGL |          // support OpenGL
  265.           PFD_DOUBLEBUFFER,             // double buffered
  266.         PFD_TYPE_RGBA,                  // RGBA type
  267.         24,                             // 24-bit color depth
  268.         0, 0, 0, 0, 0, 0,               // color bits ignored
  269.         0,                              // no alpha buffer
  270.         0,                              // shift bit ignored
  271.         0,                              // no accumulation buffer
  272.         0, 0, 0, 0,                     // accum bits ignored
  273.         16,                             // 16-bit z-buffer
  274.         0,                              // no stencil buffer
  275.         0,                              // no auxiliary buffer
  276.         PFD_MAIN_PLANE,                 // main layer
  277.         0,                              // reserved
  278.         0, 0, 0                         // layer masks ignored
  279.     };
  280.     
  281.     if ( 0 == (m_PixelFormat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd)) )
  282.     {
  283. SetError(2);
  284.         return FALSE;
  285. }
  286.     if ( FALSE == ::SetPixelFormat(m_pDC->GetSafeHdc(), m_PixelFormat, &pfd) )
  287.     {
  288.         SetError(3);
  289.         return FALSE;
  290. }
  291.     return TRUE;
  292. }
  293. /////////////////////////////////////////////////////////////////////////////
  294. // SetupViewport
  295. BOOL COpenGLView::SetupViewport( int cx, int cy )
  296. {
  297. // select the full client area
  298.     ::glViewport(0, 0, cx, cy);
  299. return TRUE;
  300. }
  301. /////////////////////////////////////////////////////////////////////////////
  302. // SetupViewingFrustum
  303. BOOL COpenGLView::SetupViewingFrustum( GLdouble aspect_ratio )
  304. {
  305. // select a default viewing volumn
  306.     ::gluPerspective(40.0f, aspect_ratio, .1f, 20.0f);
  307. // here's an ortho view
  308. // glOrtho( -2.0f, 2.0f, -2.0f, 2.0f, -.10f, 20.0f );
  309. return TRUE;
  310. }
  311. /////////////////////////////////////////////////////////////////////////////
  312. // SetupViewingTransform
  313. // This is a static, default viewing transform
  314. BOOL COpenGLView::SetupViewingTransform()
  315. {
  316. // select a default viewing transformation
  317. // of a 20 degree rotation about the X axis
  318. // then a -5 unit transformation along Z
  319. // (It's as good as any I guess...)
  320. ::glTranslatef( 0.0f, 0.0f, -5.0f );
  321. ::glRotatef( 20.0f, 1.0f, 0.0f, 0.0f );
  322.     return TRUE;
  323. }
  324. /////////////////////////////////////////////////////////////////////////////
  325. // RenderScene
  326. // This is the default scene for the COpenGLView class.
  327. // draw a red wire sphere inside a light blue cube
  328. BOOL COpenGLView::RenderScene()
  329. {
  330. // rotate the wire sphere so it's vertically
  331. // oriented
  332. ::glRotatef( 90.0f, 1.0f, 0.0f, 0.0f );
  333. ::glColor3f( 1.0f, 0.0f, 0.0f );
  334. //::auxWireSphere( .5 );
  335. ::glColor3f( 0.5f, 0.5f, 1.0f );
  336. //::auxWireCube( 1.0 );
  337.     return TRUE;
  338. }
  339.  
  340. /////////////////////////////////////////////////////////////////////////////
  341. // RenderStockScene
  342. void COpenGLView::RenderStockScene()
  343. {
  344. // define all vertices   X     Y     Z
  345. GLfloat v0[3], v1[3], v2[3], v3[3], delta;
  346. int color = 0;
  347. delta = 0.5f;
  348. // define the two colors
  349. GLfloat color1[3] = { 0.9f, 0.9f, 0.9f };
  350.   GLfloat color2[3] = { 0.05f, 0.05f, 0.05f };
  351. v0[1] = v1[1] = v2[1] = v3[1] = 0.0f;
  352. ::glBegin( GL_QUADS );
  353. for ( int x = -5 ; x <= 5 ; x++ )
  354. {
  355. for ( int z = -5 ; z <= 5 ; z++ )
  356. {
  357. ::glColor3fv( (color++)%2 ? color1 : color2 );
  358. v0[0] = 0.0f+delta*z;
  359. v0[2] = 0.0f+delta*x;
  360. v1[0] = v0[0]+delta;
  361. v1[2] = v0[2];
  362. v2[0] = v0[0]+delta;
  363. v2[2] = v0[2]+delta;
  364. v3[0] = v0[0];
  365. v3[2] = v0[2]+delta;
  366. ::glVertex3fv( v0 );
  367. ::glVertex3fv( v1 );
  368. ::glVertex3fv( v2 );
  369. ::glVertex3fv( v3 );
  370. }
  371. }
  372. ::glEnd();
  373. }
  374. /////////////////////////////////////////////////////////////////////////////
  375. // Draw3DAxes
  376. // Draws lines along the current 3 axes from "start" units to "finish", with 
  377. // "ticks" tickmarks spaced out along it.
  378. void COpenGLView::Draw3DAxes( float start, float finish, int ticks )
  379. {
  380. // make sure that start < finish
  381. if ( start > finish )
  382. {
  383. float temp = start;
  384. start = finish;
  385. finish = start;
  386. }
  387. // if ticks < 0 and delta is larger than 1, place the ticks
  388. // on each scales unit length
  389. if ( 0 > ticks )
  390. {
  391. float delta = finish-start;
  392. ticks = delta > 1.0 ? (int)delta : 0;
  393. }
  394. // draw the tickmarked axes
  395. Draw3DAxesLine( start, finish, 0, ticks );
  396. Draw3DAxesLine( start, finish, 1, ticks );
  397. Draw3DAxesLine( start, finish, 2, ticks );
  398. }
  399. /////////////////////////////////////////////////////////////////////////////
  400. // Draw3DAxesLine
  401. // This routine draws a colored line along a specified axis.
  402. // axis_id = 0 for the x, 1 for the y, and anything else for the z
  403. // start and finish are the starting and ending location, start < finish.
  404. // ticks is the number of ticks to place along the axis.
  405. // If you are using lighting/materials, you might want to wrapper this routine
  406. // so that it's called with lighting disabled, or else the axis lines will be effected
  407. // by lighting claculations - which generally means hard to see.
  408. void COpenGLView::Draw3DAxesLine( float start, float finish, int axis_id, int ticks )
  409. {
  410. float *px, *py, *pz, zero = 0.0f;
  411. float tickx, ticky, tickz;
  412. float *pdx, *pdy, *pdz, tinytick, delta = (finish-start)/(ticks<1?1:ticks);
  413. GLfloat negativeColor[3] = { 1.0f, 0.0f, 0.0f };
  414. GLfloat positiveColor[3] = { 0.0f, 1.0f, 0.0f };
  415. pdx = pdy = pdz = px = py = pz = &zero;
  416. tickx = ticky = tickz = 0.0f;
  417. tinytick = 0.05f;
  418. // select which of the 3 axes is going to vary
  419. if ( 0 == axis_id ) // X axis
  420. {
  421. pdx = &delta;   
  422. ticky = tinytick;   
  423. px = &start;   
  424. }
  425. else if ( 1 == axis_id ) // Y axis
  426. {
  427. pdy = &delta;   
  428. tickx = tinytick;   
  429. py = &start;   
  430. }
  431. else  // default Z axis
  432. {
  433. pdz = &delta;   
  434. ticky = tinytick;   
  435. pz = &start;   
  436. }
  437. // turn off the lighting effects
  438. // since we don't want the axes lines effected by the
  439. // lighting. You might need to call ::glDisable(GL_LIGHTING)
  440. // before this routine
  441. ::glBegin(GL_LINES);
  442. // now draw the two lines that make up the axis
  443. ::glColor3fv( negativeColor ); // negative color
  444. ::glVertex3f( *px, *py, *pz );
  445. ::glVertex3f( 0.0f, 0.0f, 0.0f );
  446. ::glColor3fv( positiveColor ); // positive color
  447. ::glVertex3f( 0.0f, 0.0f, 0.0f );
  448. ::glVertex3f( *px+*pdx*ticks, *py+*pdy*ticks, *pz+*pdz*ticks );
  449. // now draw the tick marks
  450. for (int i = 0; i < ticks  ; i++ )
  451. {
  452. if ( i < ticks/2 )
  453. {
  454. ::glColor3fv( negativeColor );
  455. }
  456. else
  457. {
  458. ::glColor3fv( positiveColor );
  459. }
  460. ::glVertex3f( *px-tickx, *py-ticky, *pz-tickz );
  461. ::glVertex3f( *px+tickx, *py+ticky, *pz+tickz );
  462. *px += *pdx;
  463. *py += *pdy;
  464. *pz += *pdz;
  465. }
  466. ::glEnd();
  467. // don't forget to turn lighting effects back on
  468. // via glEnable(GL_LIGHTING)
  469. }
  470. /////////////////////////////////////////////////////////////////////////////
  471. // OnKeyDown
  472. // This routine runs the keyboard interface.
  473. // Most of the keys accepted are from the numeric keypad
  474. // HOME: Resets viewpoint to initial values (animation keeps going)
  475. // SHIFT-HOME: reset viewpoint & clear movement vectors
  476. // 5: Clear movement vectors
  477. // Up/Down Arrows: change velocity in Z (if shifted, change rotation)
  478. // Left/Right Arrows: change velocity in X (if shifted, change rotation)
  479. // Plus/Minus: change velocity in Y (if shifted, change rotation)
  480. // ESC: Exit animation
  481. void COpenGLView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  482. {
  483. switch ( nChar )
  484.    {
  485.    case VK_ESCAPE: // close down the app
  486. GetParent()->PostMessage(WM_CLOSE);
  487. return;
  488.    default:
  489. return;
  490.    }
  491. // Probably don't ever need this
  492. //CView::OnKeyDown(nChar, nRepCnt, nFlags);
  493. }