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

OpenGL

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // 3dObjectNURB.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. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "glOOP.h"
  21. #include "3dObjectDialog.h"
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. //////////////////////////////////////////////////////////////////
  28. // C3dObjectNURB Static functions
  29. // NURBS callback error handler
  30. void CALLBACK NurbsErrorHandler()
  31. {
  32. char cMessage[64];
  33. GLenum nErrorCode;
  34. // Get the error code
  35. nErrorCode = glGetError();
  36. // Extract the text message of the error
  37. strcpy(cMessage, "NURBS error occured: ");
  38. strcat(cMessage, (const char*)gluErrorString(nErrorCode));
  39. // Display the message to the user
  40. MessageBox(NULL, cMessage, NULL, MB_OK | MB_ICONEXCLAMATION);
  41. return;
  42. }
  43. //////////////////////////////////////////////////////////////////
  44. // C3dObjectNURB
  45. IMPLEMENT_DYNAMIC(C3dObjectNURB, C3dObject)
  46. /////////////////////////////////////////////////////////////////////////////
  47. // C3dShape construction
  48. C3dObjectNURB::C3dObjectNURB()
  49. {
  50. // Set the attributes to default values..
  51.   m_iType = SHAPE_OBJECT;
  52.    m_szName.Format("NURB %u", nNURBObjects++);
  53. m_fDepth  = 3.0f;
  54. m_fWidth  = 3.0f;
  55. m_iUSegments = 10;
  56. m_iVSegments = 10;
  57. m_iNumUCtrlPoints = 4;
  58. m_iNumVCtrlPoints = 4;
  59. m_hUKnots = NULL;
  60. m_hVKnots = NULL;
  61. m_pUKnots = NULL;
  62. m_pVKnots = NULL;
  63. // Create a NURBS rendering object
  64. m_pNURBObj = gluNewNurbsRenderer();
  65. ASSERT(m_pNURBObj);
  66. // Install error handler to notify the user of NURBS errors
  67. gluNurbsCallback(m_pNURBObj, GLU_ERROR, NurbsErrorHandler);
  68. // Create our C3dPointArray object
  69. m_pPointArray = new C3dPointArray;
  70. ASSERT(m_pPointArray);
  71. // Create an array of points for our vertices
  72. m_pPointArray->Create(m_iNumUCtrlPoints*m_iNumVCtrlPoints);
  73. // Initialize our cubes vertices (points)
  74. InitVertices();
  75. }
  76. /////////////////////////////////////////////////////////////////////////////
  77. // C3DWorld Destructor
  78. C3dObjectNURB::~C3dObjectNURB()
  79. {
  80. // Free our points array memory
  81. if(m_hUKnots)
  82. {
  83. GlobalUnlock(m_hUKnots);
  84. GlobalFree(m_hUKnots);
  85. m_hUKnots = NULL;
  86. m_pUKnots = NULL;
  87. }
  88. // Free our points array memory
  89. if(m_hVKnots)
  90. {
  91. GlobalUnlock(m_hVKnots);
  92. GlobalFree(m_hVKnots);
  93. m_hVKnots = NULL;
  94. m_pVKnots = NULL;
  95. }
  96. // Delete our point array
  97. if(m_pPointArray)
  98. delete m_pPointArray;
  99. if(m_pNURBObj)
  100. gluDeleteNurbsRenderer(m_pNURBObj);
  101. }
  102. /////////////////////////////////////////////////////////////////////////////
  103. // C3dObjectNURB Methods or virtual function implimentation
  104. void C3dObjectNURB::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
  105. {
  106. C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
  107. ASSERT(pSheet);
  108. // Add the page to the property sheet
  109. pSheet->AddPage(&pSheet->m_NURBPage);
  110. // Save the address of this object in the page
  111. pSheet->m_NURBPage.m_pObject = this;
  112. }
  113. int C3dObjectNURB::LoadBitMapImage(CImageList* pList)
  114. {
  115. CBitmap bitmap;
  116. // If the image index has been stored in this object,
  117. // return the index.
  118. if(m_iBMImage > -1)
  119. return m_iBMImage;
  120. // If the image index for this object type has been
  121. // created, store the index for this object and
  122. // return the index.
  123. if( iObjectNURBBMImage > -1) {
  124. m_iBMImage = iObjectNURBBMImage;
  125. return m_iBMImage;
  126. }
  127. // The image index for this object type has not been
  128. // loaded and the object image index has not been
  129. // stored.
  130. //
  131. // Load the bitmap for the non-selected light
  132. bitmap.LoadBitmap(IDB_OBJECT_NURB);
  133. m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  134. bitmap.DeleteObject();
  135. // Load the bitmap for the non-selected light
  136. bitmap.LoadBitmap(IDB_OBJECT_NURB_SELECTED);
  137. pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  138. bitmap.DeleteObject();
  139. iObjectNURBBMImage = m_iBMImage;
  140. return m_iBMImage;
  141. }
  142. void C3dObjectNURB::Serialize(CArchive& ar, int iVersion)
  143. {
  144. CString szBuffer;
  145. if (ar.IsStoring())
  146. {
  147. // Save the Object Class header...
  148. szBuffer.Format("n%sC3dObjectNURB {n", szIndent);
  149. ar.WriteString(szBuffer);
  150. // Save the this objects' specific data...
  151. szBuffer.Format("%stDepth         < %f >n", szIndent, m_fDepth);
  152. ar.WriteString(szBuffer);
  153. szBuffer.Format("%stWidth         < %f >n", szIndent, m_fWidth);
  154. ar.WriteString(szBuffer);
  155. szBuffer.Format("%stNumUSegments  < %d >n", szIndent, m_iUSegments);
  156. ar.WriteString(szBuffer);
  157. szBuffer.Format("%stNumVSegments  < %d >n", szIndent, m_iVSegments);
  158. ar.WriteString(szBuffer);
  159. szBuffer.Format("%stNumUCtrlPnts  < %d >n", szIndent, m_iNumUCtrlPoints);
  160. ar.WriteString(szBuffer);
  161. szBuffer.Format("%stNumVCtrlPnts  < %d >n", szIndent, m_iNumVCtrlPoints);
  162. ar.WriteString(szBuffer);
  163. szBuffer.Format("%stNum Points    < %d >n", szIndent, m_pPointArray->m_iNumPoints);
  164. ar.WriteString(szBuffer);
  165. for(int i=0; i<m_pPointArray->m_iNumPoints; i++)
  166. {
  167. szBuffer.Format("%stt        < %f, %f, %f >n", szIndent, m_pPointArray->m_pPoints[i].m_fOrigin[0],
  168. m_pPointArray->m_pPoints[i].m_fOrigin[1],
  169. m_pPointArray->m_pPoints[i].m_fOrigin[2]);
  170. ar.WriteString(szBuffer);
  171. }
  172. // Save the base class object data...
  173. C3dObject::Serialize(ar, iVersion);
  174. szBuffer.Format("%s}n", szIndent); // end of object def
  175. ar.WriteString(szBuffer);
  176. }
  177. else
  178. {
  179. ar.ReadString(szBuffer);
  180. szBuffer.TrimLeft(); // Remove leading white spaces
  181. sscanf(szBuffer, "Depth         < %f >n", &m_fDepth);
  182. ar.ReadString(szBuffer);
  183. szBuffer.TrimLeft();
  184. sscanf(szBuffer, "Width         < %f >n", &m_fWidth);
  185. ar.ReadString(szBuffer);
  186. szBuffer.TrimLeft();
  187. sscanf(szBuffer, "NumUSegments  < %d >n", &m_iUSegments);
  188. ar.ReadString(szBuffer);
  189. szBuffer.TrimLeft();
  190. sscanf(szBuffer, "NumVSegments  < %d >n", &m_iVSegments);
  191. ar.ReadString(szBuffer);
  192. szBuffer.TrimLeft();
  193. sscanf(szBuffer, "NumUCtrlPnts  < %d >n", &m_iNumUCtrlPoints);
  194. ar.ReadString(szBuffer);
  195. szBuffer.TrimLeft();
  196. sscanf(szBuffer, "NumVCtrlPnts  < %d >n", &m_iNumVCtrlPoints);
  197. ar.ReadString(szBuffer);
  198. szBuffer.TrimLeft();
  199. sscanf(szBuffer, "Num Points    < %d >n", &m_pPointArray->m_iNumPoints);
  200. // Resize our control point array
  201. if(m_pPointArray->SetArraySize(m_iNumUCtrlPoints*m_iNumVCtrlPoints))
  202. return;
  203. // Read the shape vertice, or point data
  204. for(int i=0; i<m_pPointArray->m_iNumPoints; i++)
  205. {
  206. ar.ReadString(szBuffer);
  207. szBuffer.TrimLeft();
  208. sscanf(szBuffer, "< %f, %f, %f >n", &m_pPointArray->m_pPoints[i].m_fOrigin[X],
  209.  &m_pPointArray->m_pPoints[i].m_fOrigin[Y],
  210.  &m_pPointArray->m_pPoints[i].m_fOrigin[Z]);
  211. }
  212. // Initialize our knots
  213. InitKnots();
  214. // Read the base class object data...
  215. C3dObject::Serialize(ar, iVersion);
  216. }
  217. }
  218. void C3dObjectNURB::DisplayObject(C3dWorld* pWorld, C3dCamera* pCamera)
  219. {
  220. // Save the current transformation matrix..
  221.   glPushMatrix();
  222. // Transform our object
  223. TransformObject(pWorld);
  224. if(this == pWorld->m_pSelectedObj)
  225. {
  226. DisplaySelected(pWorld, FALSE);
  227. if(pWorld->m_bDisplayPoints)
  228. // Display all points in our object
  229. DisplayPoints(pWorld, pCamera);
  230. }
  231. // Save the name on the stack.  This will be used to determine
  232. // hits from the selection buffer
  233. glLoadName(m_iName);
  234. // Setup this objects polygon color material
  235. // or texture attributes
  236. SetAttributes(pWorld, m_pQuad);
  237. // Special case for NURBS objects.  Set the fill/outline mode.
  238. if(pWorld->m_iRenderMode == RENDER_WIREFRAME)
  239. gluNurbsProperty(m_pNURBObj, GLU_DISPLAY_MODE, (GLfloat)GLU_OUTLINE_POLYGON);
  240. else
  241. gluNurbsProperty(m_pNURBObj, GLU_DISPLAY_MODE, (GLfloat)GLU_FILL);
  242. // Do we need to build the display lists?
  243. if(m_bBuildLists)
  244. {
  245. if(!m_iDisplayLists)
  246. m_iDisplayLists = glGenLists(1);// Create the DisplayList(s)
  247. Build(pWorld, pCamera); // Build the shape
  248. m_bBuildLists = FALSE; // Set the flag
  249. }
  250. else
  251. glCallList(m_iDisplayLists); // Display the list
  252. // Display all child objects of this object
  253. DisplayChildObjects(pWorld, pCamera);
  254. // Restore the current transformation matrix..
  255. glPopMatrix();
  256. }
  257. void C3dObjectNURB::Build(C3dWorld* pWorld, C3dCamera* pCamera)
  258. {
  259. GLint u_knot_count, v_knot_count;
  260. GLint u_offset, v_offset;
  261. GLint u_order, v_order;
  262. // Initialize our variables
  263. u_knot_count = m_iNumUCtrlPoints*2;
  264. v_knot_count = m_iNumVCtrlPoints*2;
  265. v_offset  = sizeof(C3dPoint)/sizeof(GLfloat);
  266. u_offset  = v_offset*m_iNumVCtrlPoints;
  267. u_order  = m_iNumUCtrlPoints;
  268. v_order  = m_iNumVCtrlPoints;
  269. // Compile and build the list
  270. glNewList(m_iDisplayLists, GL_COMPILE_AND_EXECUTE);
  271. // We use GLU_DOMAIN_DISTANCE to specify, in parametric coordinates,
  272. // how many sample points per unit length to take in the u and v dimensions.
  273. gluNurbsProperty(m_pNURBObj, GLU_SAMPLING_METHOD, (GLfloat)GLU_DOMAIN_DISTANCE);
  274. gluNurbsProperty(m_pNURBObj, GLU_U_STEP, (GLfloat)m_iUSegments);
  275. gluNurbsProperty(m_pNURBObj, GLU_V_STEP, (GLfloat)m_iVSegments);
  276. gluBeginSurface(m_pNURBObj);
  277. gluNurbsSurface(m_pNURBObj,
  278. u_knot_count, m_pUKnots,
  279. v_knot_count, m_pVKnots,
  280. u_offset,
  281. v_offset,
  282. (GLfloat*)m_pPointArray->m_pPoints->m_fOrigin,
  283. u_order, v_order,
  284. GL_MAP2_VERTEX_3);
  285. gluNurbsSurface(m_pNURBObj,
  286. u_knot_count, m_pUKnots,
  287. v_knot_count, m_pVKnots,
  288. u_offset,
  289. v_offset,
  290. (GLfloat*)m_pPointArray->m_pPoints->m_fOrigin,
  291. u_order, v_order,
  292. GL_MAP2_NORMAL);
  293. /*
  294. gluNurbsSurface(m_pNURBObj,
  295. u_knot_count, m_pUKnots,
  296. v_knot_count, m_pVKnots,
  297. u_offset,
  298. v_offset,
  299. (GLfloat*)m_pPointArray->m_pPoints->m_fOrigin,
  300. u_order, v_order,
  301. GL_MAP2_COLOR_4);
  302. */
  303. gluNurbsSurface(m_pNURBObj,
  304. u_knot_count, m_pUKnots,
  305. v_knot_count, m_pVKnots,
  306. u_offset,
  307. v_offset,
  308. (GLfloat*)m_pPointArray->m_pPoints->m_fOrigin,
  309. u_order, v_order,
  310. GL_MAP2_TEXTURE_COORD_2);
  311. gluEndSurface(m_pNURBObj);
  312. glEndList();
  313. }
  314. /////////////////////////////////////////////////////////////////////////////
  315. // C3dObjectNURB Methods or Implementation
  316. void C3dObjectNURB::InitVertices()
  317. {
  318. // Our NURBS plane is created by positioning the control points along the 
  319. // u & v vector.  The vector points, for a typical 4 x 4 grid, are
  320. // initialized as follows:
  321. /*
  322.                          V
  323.                        /         ---------------------
  324.                      /     p3* /     / *p7  / *p11  / *p15
  325.                    /         /     /      /       /
  326.                  /     p2* /     / *p6  / *p10  / *p14
  327.                /         /     /      /       /
  328.              /     p1* /     / *p5  / *p9   / *p13
  329.            /         /     /      /       /
  330.          /     p0* /-----/------/-------/ *p12
  331.        /                * p4   * p8 
  332.      /
  333.      -------------------------------------> U
  334.     */
  335. int u, v;
  336. // Resize our control point array
  337. if(m_pPointArray->SetArraySize(m_iNumUCtrlPoints*m_iNumVCtrlPoints))
  338. return; // function failed
  339. // Initialize our control points
  340. for(u=0; u<m_iNumUCtrlPoints; u++)
  341. {
  342. for(v=0; v<m_iNumVCtrlPoints; v++)
  343. {
  344. m_pPointArray->m_pPoints[(u*m_iNumVCtrlPoints)+v].m_fOrigin[X] = ((u*m_fWidth)/(m_iNumUCtrlPoints-1))-(m_fWidth/2);
  345. m_pPointArray->m_pPoints[(u*m_iNumVCtrlPoints)+v].m_fOrigin[Y] = ((v*m_fDepth)/(m_iNumVCtrlPoints-1))-(m_fDepth/2);
  346. m_pPointArray->m_pPoints[(u*m_iNumVCtrlPoints)+v].m_fOrigin[Z] = 0.0f;
  347. }
  348. }
  349. // Initialize our Knot arrays
  350. InitKnots();
  351. }
  352. int C3dObjectNURB::InitKnots()
  353. {
  354. int u, v;
  355. // Create an array of nondecreasing knot values in the parametric u direction.
  356. if(m_hUKnots) // Does the array already exist?
  357. {
  358. // Unlock the memory handle
  359. GlobalUnlock(m_hUKnots);
  360. // Reallocate the memory block
  361. m_hUKnots = GlobalReAlloc(m_hUKnots, m_iNumUCtrlPoints*2*sizeof(GLfloat),
  362.   GMEM_MOVEABLE | GMEM_ZEROINIT);
  363. }
  364. else
  365. m_hUKnots = GlobalAlloc(GPTR, m_iNumUCtrlPoints*2*sizeof(GLfloat));
  366. if(m_hUKnots == NULL)
  367. {
  368. AfxMessageBox("Not enought memory to create U Knot Array!", MB_OK, NULL);
  369. return(-1);
  370. }
  371. m_pUKnots = (GLfloat*)GlobalLock(m_hUKnots);
  372. if(m_pUKnots == NULL) {
  373. AfxMessageBox("Not enought memory to create U Knot Array!", MB_OK, NULL);
  374. GlobalFree(m_hUKnots);
  375. m_hUKnots = NULL;
  376. return(-1);
  377. }
  378. // Create an array of nondecreasing knot values in the parametric v direction.
  379. if(m_hVKnots) // Does the array already exist?
  380. {
  381. // Unlock the memory handle
  382. GlobalUnlock(m_hVKnots);
  383. // Reallocate the memory block
  384. m_hVKnots = GlobalReAlloc(m_hVKnots, m_iNumVCtrlPoints*2*sizeof(GLfloat),
  385.   GMEM_MOVEABLE | GMEM_ZEROINIT);
  386. }
  387. else
  388. m_hVKnots = GlobalAlloc(GPTR, m_iNumVCtrlPoints*2*sizeof(GLfloat));
  389. if(m_hVKnots == NULL)
  390. {
  391. AfxMessageBox("Not enought memory to create V Knot Array!", MB_OK, NULL);
  392. return(-1);
  393. }
  394. m_pVKnots = (GLfloat*)GlobalLock(m_hVKnots);
  395. if(m_pVKnots == NULL) {
  396. AfxMessageBox("Not enought memory to create V Knot Array!", MB_OK, NULL);
  397. GlobalFree(m_hVKnots);
  398. m_hVKnots = NULL;
  399. return(-1);
  400. }
  401. // Now that our Knot array memory has been allocated, initialize in nondecreasing
  402. // order
  403. for(u=0; u<m_iNumUCtrlPoints; u++)
  404. {
  405. m_pUKnots[u] = 0.0f;
  406. m_pUKnots[u+m_iNumUCtrlPoints] = 1.0f;
  407. }
  408. for(v=0; v<m_iNumVCtrlPoints; v++)
  409. {
  410. m_pVKnots[v] = 0.0f;
  411. m_pVKnots[v+m_iNumVCtrlPoints] = 1.0f;
  412. }
  413. return 0;
  414. }