Readme.txt
上传用户:hcfgz168
上传日期:2011-09-11
资源大小:116k
文件大小:7k
源码类别:

OpenGL

开发平台:

WINDOWS

  1. OpenGL is faster when using display lists
  2. This article was contributed by Pierre Alliez 
  3. pierre.alliez@cnet.francetelecom.fr
  4. [Runs fine under Windows NT 4.0 and Visual C++ 5.0]
  5. This contribution is a small MFC sample to learn how to :
  6. + use display lists
  7. + superimpose wireframe on a flat or smoothly shaded mesh
  8. + smoothly subdivide a 3D triangular mesh (from Charles Loop)
  9. + implement mouse interaction (rotation and translation)
  10. + build a scene graph from a vrml 2.0 file (hand-made and not lex-based)
  11. DISPLAY LIST 
  12. Using display lists is a nice way to accelerate your rendering
  13. application. A display list compiles a sequence of gl drawings 
  14. using standard gl calls, then can be recalled later using a simple
  15. list id number. When your graphic card is fully OpenGL compliant the
  16. resulting list is thus resident in the card memory, which greatly 
  17. accelerates rendering loops.
  18. A good command sequence to build a display list may be :
  19. int list = ::glGenLists(1); // ask for a free id number
  20. ::glNewList(list,GL_COMPILE_AND_EXECUTE);
  21. ::glBegin(GL_TRIANGLES);
  22. // std gl calls here... fill vertices, normals, colors
  23. ::glEnd();
  24. ::glEndList();
  25. A good command sequence to use a display list may be :
  26. if(::glIsList(list) == GL_TRUE)
  27. ::glCallList(m_ListOpenGL);
  28.  
  29. The sample builds a scene graph from a vrml 2.0 file (exported
  30. via 3D Studio Max only), then uses display lists. Each 3D mesh
  31. contains a list number, and use a glCallList command instead of
  32. standards glBegin(GL_TRIANGLES) commands when its list is built.
  33. A flag m_Modified permits to rebuild the list when the mesh is
  34. modified.
  35. //********************************************
  36. // The 3D mesh class definition
  37. //********************************************
  38. class CMesh3d : public CObject3d
  39. {
  40. private :
  41. // Std datas
  42. CArray<CVertex3d> m_ArrayVertex;
  43. CArray<CFace3d>   m_ArrayFace;
  44. // OpenGL-specific
  45. unsigned int m_ListOpenGL;
  46. BOOL m_ListDone;
  47. BOOL m_Modified;
  48. .../...
  49. public :
  50. BOOL glDraw();
  51. .../...
  52. }
  53. //********************************************
  54. // Mesh drawing
  55. //********************************************
  56. BOOL CMesh3d::glDraw()
  57. {
  58. // Build list at first
  59. if(!m_ListDone || m_Modified)
  60. glBuildList();
  61. // Is the list valid ?
  62. if(::glIsList(m_ListOpenGL)==GL_TRUE)
  63. {
  64.   ::glCallList(m_ListOpenGL);
  65. return TRUE;
  66. }
  67. return FALSE;
  68. }
  69. SUPERIMPOSING WIREFRAME
  70. Sometime you would like to view the wireframe superimposing
  71. the flat or smooth shaded mesh. A good way to do this is 
  72. to use the glPolygonOffset command, which creates a z-buffer 
  73. offset. The following code shows the RenderScene function of
  74. the document, if one resumes two rendering passes are necessary,
  75. the first render the mesh using lighted flat mode, the second
  76. cut off the light, set the line mode, set a z-buffer offset, then
  77. draw the mesh again.
  78. //***********************************************
  79. // RenderScene
  80. //***********************************************
  81. void CMeshDoc::RenderScene()
  82. {
  83. // Main drawing
  84. m_SceneGraph.glDraw();
  85. // Add wireframe (no light, and line mode)
  86. if(m_AddWireframe)
  87. {
  88. // Set state
  89. ::glDisable(GL_LIGHTING);
  90. ::glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
  91. ::glEnable(GL_POLYGON_OFFSET_LINE);
  92. ::glPolygonOffset(m_PolygonOffset,-1.0f);
  93. // Draw again...
  94. m_SceneGraph.glDraw(TYPE_MESH3D);
  95. // Restore light and mode
  96. ::glDisable(GL_POLYGON_OFFSET_LINE);
  97. ::glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  98. ::glEnable(GL_LIGHTING);
  99. }
  100. ::glFlush();
  101. }
  102. SMOOTH SUBDIVISION
  103. From a given 3D mesh, how can we improve the geometric appearence on 
  104. smooth models ? The Charles Loop smooth subdivision comes here to help
  105. us. Each triangle is divided in four triangles, and a filtering function
  106. permits the mesh to be smoothed. The command is easy-to-use in the document,
  107. and I let you discover the details in the mesh's code.
  108. //***********************************************
  109. // Smooth subdivision
  110. //***********************************************
  111. void CMeshDoc::OnMeshLoop() 
  112. {
  113. BeginWaitCursor();
  114. int NbObject = m_SceneGraph.NbObject();
  115. for(int i=0;i<NbObject;i++)
  116. {
  117.   CObject3d *pObject3d = m_SceneGraph[i];
  118.   if(pObject3d->GetType() == TYPE_MESH3D)
  119. {
  120. CMesh3d *pMesh  = (CMesh3d *)pObject3d;
  121. pMesh->SubdivisionLoop();
  122. }
  123. }
  124. UpdateAllViews(NULL);
  125. EndWaitCursor();
  126. }
  127. MOUSE INTERACTION
  128. A few variables and commands in the view permits mouse interaction.
  129. No more comments about this.
  130. //***********************************************
  131. // Left button -> x/y translation
  132. //***********************************************
  133. void CMeshView::OnLButtonDown(UINT nFlags, CPoint point) 
  134. {
  135. m_LeftButtonDown = TRUE;
  136. m_LeftDownPos = point;
  137. SetCapture();
  138. CView::OnLButtonDown(nFlags, point);
  139. }
  140. void CMeshView::OnLButtonUp(UINT nFlags, CPoint point) 
  141. {
  142. m_RightButtonDown = FALSE;
  143. m_LeftButtonDown = FALSE;
  144. ReleaseCapture();
  145. CView::OnLButtonUp(nFlags, point);
  146. }
  147. //***********************************************
  148. // Right button : z translation
  149. //***********************************************
  150. void CMeshView::OnRButtonDown(UINT nFlags, CPoint point) 
  151. {
  152. m_RightButtonDown = TRUE;
  153. m_RightDownPos = point;
  154. SetCapture();
  155. CView::OnRButtonDown(nFlags, point);
  156. }
  157. void CMeshView::OnRButtonUp(UINT nFlags, CPoint point) 
  158. {
  159. m_RightButtonDown = FALSE;
  160. m_LeftButtonDown = FALSE;
  161. ReleaseCapture();
  162. CView::OnRButtonUp(nFlags, point);
  163. }
  164. //***********************************************
  165. // Mouse move
  166. // Both : rotation
  167. // Left : x / y translation
  168. // Right : z translation
  169. //***********************************************
  170. void CMeshView::OnMouseMove(UINT nFlags, CPoint point) 
  171. {
  172. // Both : rotation
  173. if(m_LeftButtonDown && m_RightButtonDown)
  174. {
  175. if(m_xyRotation)
  176. {
  177. m_yRotation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedRotation;
  178. m_xRotation -= (float)(m_LeftDownPos.y - point.y) * m_SpeedRotation;
  179. }
  180. else
  181. {
  182. m_zRotation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedRotation;
  183. m_xRotation -= (float)(m_LeftDownPos.y - point.y) * m_SpeedRotation;
  184. }
  185. m_LeftDownPos = point;
  186. m_RightDownPos = point;
  187. InvalidateRect(NULL,FALSE);
  188. }
  189. else
  190. // Left : x / y translation
  191. if(m_LeftButtonDown)
  192. {
  193. m_xTranslation -= (float)(m_LeftDownPos.x - point.x) * m_SpeedTranslation;
  194. m_yTranslation += (float)(m_LeftDownPos.y - point.y) * m_SpeedTranslation;
  195. m_LeftDownPos = point;
  196. InvalidateRect(NULL,FALSE);
  197. }
  198. else
  199. // Right : z translation
  200. if(m_RightButtonDown)
  201. {
  202. m_zTranslation += (float)(m_RightDownPos.y - point.y) * m_SpeedTranslation;
  203. m_RightDownPos = point;
  204. InvalidateRect(NULL,FALSE);
  205. }
  206. CView::OnMouseMove(nFlags, point);
  207. }