3dObjectCSG.cpp
上传用户:shxiangxiu
上传日期:2007-01-03
资源大小:1101k
文件大小:10k
源码类别:

OpenGL

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // 3dObjectCSG.cpp : implementation file
  3. //
  4. // glOOP (OpenGL Object Oriented Programming library)
  5. // Copyright (c) Craig Fahrnbach 1997, 1998
  6. //
  7. // OpenGL is a registered trademark of Silicon Graphics
  8. //
  9. //
  10. // This program is provided for educational and personal use only and
  11. // is provided without guarantee or warrantee expressed or implied.
  12. //
  13. // Commercial use is strickly prohibited without written permission
  14. // from ImageWare Development.
  15. //
  16. // This program is -not- in the public domain.
  17. //
  18. // Constructive Solid Geometry algorithm based on information from the
  19. // Advanced OpenGL Rendering course at SIGGRAPH '96 by David Blythe and
  20. // Tom McReynolds.
  21. //
  22. /////////////////////////////////////////////////////////////////////////////
  23. #include "stdafx.h"
  24. #include "glOOP.h"
  25. #include "3dObjectDialog.h"
  26. #ifdef _DEBUG
  27. #define new DEBUG_NEW
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. //////////////////////////////////////////////////////////////////
  32. // C3dObjectCSG
  33. IMPLEMENT_DYNAMIC(C3dObjectCSG, C3dObject)
  34. /////////////////////////////////////////////////////////////////////////////
  35. // C3dShape construction
  36. C3dObjectCSG::C3dObjectCSG()
  37. {
  38. // Set the attributes to default values..
  39. m_iType = SHAPE_OBJECT;
  40.     m_szName.Format("CSG %u", nCSGObjects++);
  41. m_iCSGType = CSG_TYPE_OR;
  42. }
  43. /////////////////////////////////////////////////////////////////////////////
  44. // C3DWorld Destructor
  45. C3dObjectCSG::~C3dObjectCSG()
  46. {
  47. // TODO: add destruction code here,
  48. }
  49. /////////////////////////////////////////////////////////////////////////////
  50. // C3dObjectCSG Methods or virtual function implimentation
  51. void C3dObjectCSG::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
  52. {
  53. C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
  54. ASSERT(pSheet);
  55. // Add the page to the property sheet
  56. pSheet->AddPage(&pSheet->m_CSGPage);
  57. // Save the address of this object in the page
  58. pSheet->m_CSGPage.m_pObject = this;
  59. }
  60. void C3dObjectCSG::GetShapeBounds(C3dBoundingBox* pBox)
  61. {
  62. // Since a CSG object itself has no bounds (only its 
  63. // children), return bogus numbers.
  64. // Note: The actual bounds will be found when the 
  65. // calling function gets the CSG object's 
  66. // child bounds.
  67. // Set the Max point to a very large negetive number
  68. pBox->m_fMax[X] = -(GLfloat)LARGE_NUMBER;
  69. pBox->m_fMax[Y] = -(GLfloat)LARGE_NUMBER;
  70. pBox->m_fMax[Z] = -(GLfloat)LARGE_NUMBER;
  71. // Set the Min point to a very large positive number
  72. pBox->m_fMin[X] = (GLfloat)LARGE_NUMBER;
  73. pBox->m_fMin[Y] = (GLfloat)LARGE_NUMBER;
  74. pBox->m_fMin[Z] = (GLfloat)LARGE_NUMBER;
  75. }
  76. int C3dObjectCSG::LoadBitMapImage(CImageList* pList)
  77. {
  78. CBitmap bitmap;
  79. // If the image index has been stored in this object,
  80. // return the index.
  81. if(m_iBMImage > -1)
  82. return m_iBMImage;
  83. // If the image index for this object type has been
  84. // created, store the index for this object and
  85. // return the index.
  86. if( iObjectCSGBMImage > -1) {
  87. m_iBMImage = iObjectCSGBMImage;
  88. return m_iBMImage;
  89. }
  90. // The image index for this object type has not been
  91. // loaded and the object image index has not been
  92. // stored.
  93. //
  94. // Load the bitmap for the non-selected light
  95. bitmap.LoadBitmap(IDB_OBJECT_CSG);
  96. m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  97. bitmap.DeleteObject();
  98. // Load the bitmap for the non-selected light
  99. bitmap.LoadBitmap(IDB_OBJECT_CSG_SELECTED);
  100. pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  101. bitmap.DeleteObject();
  102. iObjectCSGBMImage = m_iBMImage;
  103. return m_iBMImage;
  104. }
  105. void C3dObjectCSG::Serialize(CArchive& ar, int iVersion)
  106. {
  107. CString szBuffer;
  108. if (ar.IsStoring())
  109. {
  110. // Save the Object Class header...
  111. szBuffer.Format("n%sC3dObjectCSG {n", szIndent);
  112. ar.WriteString(szBuffer);
  113. // Save the this objects' specific data...
  114. szBuffer.Format("%stCSG Type      < %d >n", szIndent, m_iCSGType);
  115. ar.WriteString(szBuffer);
  116. // Save the base class object data...
  117. C3dObject::Serialize(ar, iVersion);
  118. szBuffer.Format("%s}n", szIndent); // end of object def
  119. ar.WriteString(szBuffer);
  120. }
  121. else
  122. {
  123. if(iVersion < 102)
  124. // Read the base class object data...
  125. C3dObject::Serialize(ar, iVersion);
  126. // Read the derived class data..
  127. ar.ReadString(szBuffer);
  128. szBuffer.TrimLeft(); // Remove leading white spaces
  129. sscanf(szBuffer, "CSG Type      < %d >n", &m_iCSGType);
  130. if(iVersion < 102)
  131. // Read all child objects...
  132. LoadChildObjects(ar, iVersion);
  133. else
  134. // Read the base class object data...
  135. C3dObject::Serialize(ar, iVersion);
  136. }
  137. }
  138. void C3dObjectCSG::DisplayObject(C3dWorld* pWorld, C3dCamera* pCamera)
  139. {
  140. // Save the current transformation matrix..
  141.   glPushMatrix();
  142. // Transform our object
  143. TransformObject(pWorld);
  144. if(this == pWorld->m_pSelectedObj)
  145. {
  146. DisplaySelected(pWorld, FALSE);
  147. if(pWorld->m_bDisplayPoints)
  148. // Display all points in our object
  149. DisplayPoints(pWorld, pCamera);
  150. }
  151. // Save the name on the stack.  This will be used to determine
  152. // hits from the selection buffer
  153. glLoadName(m_iName);
  154. // Setup this objects polygon color material
  155. // or texture attributes
  156. SetAttributes(pWorld, m_pQuad);
  157. // if(m_bBuildLists) // Do we need to build the display lists?
  158. // {
  159. // if(!m_iDisplayLists)
  160. // m_iDisplayLists = glGenLists(1);// Create the DisplayList(s)
  161. Build(pWorld, pCamera); // Build the shape
  162. // m_bBuildLists = FALSE; // Set the flag
  163. // }
  164. // else
  165. // glCallList(m_iDisplayLists); // Display the list
  166. // Display all child objects of this object
  167. DisplayChildObjects(pWorld, pCamera);
  168. // Restore the current transformation matrix..
  169. glPopMatrix();
  170. }
  171. void C3dObjectCSG::Build(C3dWorld* pWorld, C3dCamera* pCamera)
  172. {
  173. C3dObject* a;
  174. C3dObject* b;
  175. POSITION objPos = m_ObjectList.GetHeadPosition();
  176. // Save the current gl state
  177. glPushAttrib(GL_ALL_ATTRIB_BITS);  /* TODO - should just push depth */
  178. glEnable(GL_CULL_FACE);
  179. // Clear the stencil buffer
  180. glClear(GL_STENCIL_BUFFER_BIT);
  181. switch (m_iCSGType) {
  182. case CSG_TYPE_OR:
  183. Object_OR(pWorld, pCamera);
  184. break;
  185. case CSG_TYPE_SUB_AB:
  186. if(m_ObjectList.GetCount() < 2)
  187. break;
  188. a = m_ObjectList.GetAt(objPos);
  189. m_ObjectList.GetNext(objPos);
  190. b = m_ObjectList.GetAt(objPos);
  191. Object_SUB(pWorld, pCamera, a, b);
  192. break;
  193. case CSG_TYPE_SUB_BA:
  194. if(m_ObjectList.GetCount() < 2)
  195. break;
  196. a = m_ObjectList.GetAt(objPos);
  197. m_ObjectList.GetNext(objPos);
  198. b = m_ObjectList.GetAt(objPos);
  199. Object_SUB(pWorld, pCamera, b, a);
  200. break;
  201. case CSG_TYPE_AND:
  202. if(m_ObjectList.GetCount() < 2)
  203. break;
  204. a = m_ObjectList.GetAt(objPos);
  205. m_ObjectList.GetNext(objPos);
  206. b = m_ObjectList.GetAt(objPos);
  207. Object_AND(pWorld, pCamera, a, b);
  208. break;
  209. }
  210. // Restore the gl state
  211. glPopAttrib();
  212. }
  213. /////////////////////////////////////////////////////////////////////////////
  214. // C3dObjectCSG function implimentation
  215. void C3dObjectCSG::Object_AND(C3dWorld* pWorld, C3dCamera* pCamera, C3dObject* a, C3dObject* b)
  216. {
  217. // boolean A and B (draw wherever A intersects B)
  218. // algorithm: Find where A is inside B, then find
  219. //   where B is inside A
  220. Inside(pWorld, pCamera, a, b, GL_BACK, GL_NOTEQUAL);
  221. Fixup(pWorld, pCamera, b);
  222. Inside(pWorld, pCamera, b, a, GL_BACK, GL_NOTEQUAL);
  223. // reset stencil test
  224.     glDisable(GL_STENCIL_TEST);
  225. }
  226. void C3dObjectCSG::Object_SUB(C3dWorld* pWorld, C3dCamera* pCamera, C3dObject* a, C3dObject* b)
  227. {
  228. // boolean A subtract B (draw wherever A is and B is NOT)
  229. // algorithm: Find where a is inside B, then find
  230. //   where the BACK faces of B are NOT in A
  231. Inside(pWorld, pCamera, a, b, GL_FRONT, GL_NOTEQUAL);
  232. Fixup(pWorld, pCamera, b);
  233. Inside(pWorld, pCamera, b, a, GL_BACK, GL_EQUAL);
  234. // reset stencil test
  235.     glDisable(GL_STENCIL_TEST);
  236. Fixup(pWorld, pCamera, a);
  237. }
  238. void C3dObjectCSG::Object_OR(C3dWorld* pWorld, C3dCamera* pCamera)
  239. {
  240. // boolean A or B or C...
  241. // Algorithm: simple, just draw all depth test enabled
  242. // glPushAttrib(GL_ALL_ATTRIB_BITS);  /* TODO - should just push depth */
  243. // glEnable(GL_DEPTH_TEST);
  244. // Display all child objects of this object
  245. DisplayChildObjects(pWorld, pCamera);
  246. // glPopAttrib();
  247. }
  248. void C3dObjectCSG::Inside(C3dWorld* pWorld, C3dCamera* pCamera, C3dObject* a, C3dObject* b, GLenum face, GLenum test)
  249. {
  250. // sets stencil buffer to show the part of A
  251. // (front or back face according to 'face')
  252. // that is inside of B.
  253. // draw A into depth buffer, but not into color buffer
  254.     glEnable(GL_DEPTH_TEST);
  255.     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  256.     glCullFace(face);
  257.     a->DisplayObject(pWorld, pCamera);
  258.     
  259. // use stencil buffer to find the parts of A that are
  260. // inside of B by first incrementing the stencil buffer
  261. // wherever B's front faces are...
  262.     glDepthMask(GL_FALSE);
  263.     glEnable(GL_STENCIL_TEST);
  264.     glStencilFunc(GL_ALWAYS, 0, 0);
  265.     glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
  266.     glCullFace(GL_BACK);
  267.   b->DisplayObject(pWorld, pCamera);
  268. // then decrement the stencil buffer wherever B's
  269. // back faces are
  270.     glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
  271.     glCullFace(GL_FRONT);
  272.     b->DisplayObject(pWorld, pCamera);
  273. // now draw the part of A that is inside of B
  274.     glDepthMask(GL_TRUE);
  275.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  276.     glStencilFunc(test, 0, 1);
  277.     glDisable(GL_DEPTH_TEST);
  278.     glCullFace(face);
  279.     a->DisplayObject(pWorld, pCamera);
  280. // reset stencil test
  281.     glDisable(GL_STENCIL_TEST);
  282. }
  283. void C3dObjectCSG::Fixup(C3dWorld* pWorld, C3dCamera* pCamera, C3dObject* pObject)
  284. {
  285. // fixes up the depth buffer with pObject's depth
  286. // values
  287.  
  288. // fix up the depth buffer
  289. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
  290. glEnable(GL_DEPTH_TEST);
  291. glDisable(GL_STENCIL_TEST);
  292. glDepthFunc(GL_ALWAYS);
  293. pObject->DisplayObject(pWorld, pCamera);
  294. // reset depth func
  295. glDepthFunc(GL_LESS);
  296. }