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

OpenGL

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // 3dObjectCylinder.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. // C3dObjectCylinder
  29. IMPLEMENT_DYNAMIC(C3dObjectCylinder, C3dObject)
  30. /////////////////////////////////////////////////////////////////////////////
  31. // C3dObjectCylinder construction
  32. C3dObjectCylinder::C3dObjectCylinder()
  33. {
  34. // Set the attributes to default values..
  35. m_iType = SHAPE_OBJECT;
  36.     m_szName.Format("Cylinder %u", nCylinderObjects++);
  37. m_bSolid  = TRUE;
  38. m_bSmooth = TRUE;
  39. m_fHeight = 2.0f;
  40. m_fTopRadius  = 1.0f;
  41. m_fBaseRadius = 1.0f;
  42. m_iSegments = 40;
  43. // Create our C3dPointArray object
  44. m_pPointArray = new C3dPointArray;
  45. ASSERT(m_pPointArray);
  46. // Create an array of points for our vertices
  47. m_pPointArray->Create((m_iSegments*2)+2);
  48. // Initialize our cubes vertices (points)
  49. InitVertices();
  50. }
  51. /////////////////////////////////////////////////////////////////////////////
  52. // C3dObjectCylinder Destructor
  53. C3dObjectCylinder::~C3dObjectCylinder()
  54. {
  55. // Delete our point array
  56. if(m_pPointArray)
  57. delete m_pPointArray;
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. // C3dObjectCylinder Methods or virtual function implimentation
  61. void C3dObjectCylinder::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
  62. {
  63. C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
  64. ASSERT(pSheet);
  65. // Add the page to the property sheet
  66. pSheet->AddPage(&pSheet->m_CylinderPage);
  67. // Save the address of this object in the page
  68. pSheet->m_CylinderPage.m_pObject = this;
  69. }
  70. int C3dObjectCylinder::LoadBitMapImage(CImageList* pList)
  71. {
  72. CBitmap bitmap;
  73. // If the image index has been stored in this object,
  74. // return the index.
  75. if(m_iBMImage > -1)
  76. return m_iBMImage;
  77. // If the image index for this object type has been
  78. // created, store the index for this object and
  79. // return the index.
  80. if( iObjectCylinderBMImage > -1) {
  81. m_iBMImage = iObjectCylinderBMImage;
  82. return m_iBMImage;
  83. }
  84. // The image index for this object type has not been
  85. // loaded and the object image index has not been
  86. // stored.
  87. //
  88. // Load the bitmap for the non-selected light
  89. bitmap.LoadBitmap(IDB_OBJECT_CYLINDER);
  90. m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  91. bitmap.DeleteObject();
  92. // Load the bitmap for the non-selected light
  93. bitmap.LoadBitmap(IDB_OBJECT_CYLINDER_SELECTED);
  94. pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  95. bitmap.DeleteObject();
  96. iObjectCylinderBMImage = m_iBMImage;
  97. return m_iBMImage;
  98. }
  99. void C3dObjectCylinder::Serialize(CArchive& ar, int iVersion)
  100. {
  101. CString szBuffer;
  102. if (ar.IsStoring())
  103. {
  104. // Save the Object Class header...
  105. szBuffer.Format("n%sC3dObjectCylinder {n", szIndent);
  106. ar.WriteString(szBuffer);
  107. // Save the this objects' specific data...
  108. szBuffer.Format("%stSolid         < %d >n", szIndent, m_bSolid);
  109. ar.WriteString(szBuffer);
  110. szBuffer.Format("%stHeight        < %f >n", szIndent, m_fHeight);
  111. ar.WriteString(szBuffer);
  112. szBuffer.Format("%stTopRadius     < %f >n", szIndent, m_fTopRadius);
  113. ar.WriteString(szBuffer);
  114. szBuffer.Format("%stBaseRadius    < %f >n", szIndent, m_fBaseRadius);
  115. ar.WriteString(szBuffer);
  116. szBuffer.Format("%stSmooth        < %d >n", szIndent, m_bSmooth);
  117. ar.WriteString(szBuffer);
  118. szBuffer.Format("%stSegments      < %d >n", szIndent, m_iSegments);
  119. ar.WriteString(szBuffer);
  120. szBuffer.Format("%stSolid Color   < %d >n", szIndent, m_bSolidColor);
  121. ar.WriteString(szBuffer);
  122. szBuffer.Format("%stNum Points    < %d >n", szIndent, m_pPointArray->m_iNumPoints);
  123. ar.WriteString(szBuffer);
  124. m_pPointArray->Serialize(ar, iVersion, !m_bSolidColor);
  125. // Save the base class object data...
  126. C3dObject::Serialize(ar, iVersion);
  127. szBuffer.Format("%s}n", szIndent); // end of object def
  128. ar.WriteString(szBuffer);
  129. }
  130. else
  131. {
  132. if(iVersion < 102)
  133. // Read the base class object data...
  134. C3dObject::Serialize(ar, iVersion);
  135. // Read the derived class data..
  136. ar.ReadString(szBuffer);
  137. szBuffer.TrimLeft(); // Remove leading white spaces
  138. sscanf(szBuffer, "Solid         < %d >n", &m_bSolid);
  139. ar.ReadString(szBuffer);
  140. szBuffer.TrimLeft();
  141. sscanf(szBuffer, "Height        < %f >n", &m_fHeight);
  142. ar.ReadString(szBuffer);
  143. szBuffer.TrimLeft();
  144. sscanf(szBuffer, "TopRadius     < %f >n", &m_fTopRadius);
  145. ar.ReadString(szBuffer);
  146. szBuffer.TrimLeft();
  147. sscanf(szBuffer, "BaseRadius    < %f >n", &m_fBaseRadius);
  148. if(iVersion < 110)
  149. {
  150. // Version 1.1 changed the definition of our member m_iNumMajor to
  151. // m_iSegments and added point manipulation
  152. ar.ReadString(szBuffer);
  153. szBuffer.TrimLeft();
  154. sscanf(szBuffer, "MajorSlices   < %d >n", &m_iSegments);
  155. // Eliminated member m_iNumMinor (minor slices), so 
  156. // just read the string
  157. ar.ReadString(szBuffer);
  158. // Set the cones point array size
  159. if(m_pPointArray->SetArraySize((m_iSegments*2)+2))
  160. return;
  161. // Initialize our point array vertices
  162. InitVertices();
  163. }
  164. else
  165. {
  166. // Version 1.1 added smooth normals
  167. ar.ReadString(szBuffer);
  168. szBuffer.TrimLeft();
  169. sscanf(szBuffer, "Smooth        < %d >n", &m_bSmooth);
  170. ar.ReadString(szBuffer);
  171. szBuffer.TrimLeft();
  172. sscanf(szBuffer, "Segments      < %d >n", &m_iSegments);
  173. if(iVersion > 130)
  174. {
  175. // Version 1.4 added point color capability
  176. ar.ReadString(szBuffer);
  177. szBuffer.TrimLeft();
  178. sscanf(szBuffer, "Solid Color   < %d >n", &m_bSolidColor);
  179. }
  180. ar.ReadString(szBuffer);
  181. szBuffer.TrimLeft();
  182. sscanf(szBuffer, "Num Points    < %d >n", &m_pPointArray->m_iNumPoints);
  183. // Set the cones point array size
  184. if(m_pPointArray->SetArraySize((m_iSegments*2)+2))
  185. return;
  186. // Read the shape vertice, or point data
  187. m_pPointArray->Serialize(ar, iVersion, !m_bSolidColor);
  188. }
  189. if(iVersion < 102)
  190. // Read all child objects...
  191. LoadChildObjects(ar, iVersion);
  192. else
  193. // Read the base class object data...
  194. C3dObject::Serialize(ar, iVersion);
  195. }
  196. }
  197. void C3dObjectCylinder::Build(C3dWorld* pWorld, C3dCamera* pCamera)
  198. {
  199. C3dPointArray Normals;
  200. VECTORF Normal;
  201. GLfloat x0, y0, x1, y1;
  202. double a0, a1;
  203. int i;
  204. // Create an array to hold the segment normals
  205. Normals.Create((m_iSegments*2)+4);
  206. // Calculate our smooth face normals
  207. CalNormals(Normals.m_pPoints, m_bSmooth);
  208. C3dPoint* pBaseCenter; // Center point of our cones base
  209. C3dPoint* pTopCenter; // Center point of our cones top
  210. C3dPoint* pRadialPoint; // Pointer to the first radial base point
  211. C3dPoint* pNextBasePoint; // Pointer to the next radial base point
  212. C3dPoint* pNextTopPoint; // Pointer to the next radial top point
  213. C3dPoint* pNormal; // Pointer to the radial point normals
  214. C3dPoint* pNextBaseNormal; // Pointer to the next radial base normal
  215. C3dPoint* pNextTopNormal; // Pointer to the next radial top normal
  216. pBaseCenter = &m_pPointArray->m_pPoints[0]; // first point in array
  217. pTopCenter = &m_pPointArray->m_pPoints[1]; // second point in array
  218. pRadialPoint = &m_pPointArray->m_pPoints[2]; // third point in array
  219. pNormal = &Normals.m_pPoints[2]; // third normal in array
  220. // Compile and build the list
  221. glNewList(m_iDisplayLists, GL_COMPILE_AND_EXECUTE);
  222. // Initialize our disks vertice points
  223. for(i=0; i<m_iSegments; i++)
  224. {
  225. a0 = i * (360/(double)m_iSegments);
  226. x0 = Cosf((GLfloat)a0);
  227. y0 = Sinf((GLfloat)a0);
  228. a1 = (i+1) * (360/(double)m_iSegments);
  229. x1 = Cosf((GLfloat)a1);
  230. y1 = Sinf((GLfloat)a1);
  231. if(i==m_iSegments-1)
  232. {
  233. // First radial point
  234. pNextBasePoint = &m_pPointArray->m_pPoints[2];
  235. pNextTopPoint = &m_pPointArray->m_pPoints[3];
  236. // First radial point normal
  237. pNextBaseNormal = &Normals.m_pPoints[2];
  238. pNextTopNormal = &Normals.m_pPoints[3];
  239. }
  240. else
  241. {
  242. // First radial point
  243. pNextBasePoint = &pRadialPoint[(i*2)+2];
  244. pNextTopPoint = &pRadialPoint[(i*2)+3];
  245. // First radial point normal
  246. pNextBaseNormal = &pNormal[(i*2)+2];
  247. pNextTopNormal = &pNormal[(i*2)+3];
  248. }
  249. if(m_bSmooth)
  250. {
  251. glBegin(GL_TRIANGLE_STRIP);
  252. // ** Side of the Cylinder **
  253. glNormal3fv(pNormal[(i*2)].m_fOrigin);
  254. glTexCoord2d(i*(1/(double)m_iSegments), 0);
  255. if(!m_bSolidColor)
  256. glColor4fv(pRadialPoint[(i*2)].m_Color.m_fColor);
  257. glVertex3fv(pRadialPoint[(i*2)].m_fOrigin);
  258. glNormal3fv(pNextBaseNormal->m_fOrigin);
  259. glTexCoord2d((i+1)*(1/(double)m_iSegments), 0); 
  260. if(!m_bSolidColor)
  261. glColor4fv(pNextBasePoint->m_Color.m_fColor);
  262. glVertex3fv(pNextBasePoint->m_fOrigin);
  263. glNormal3fv(pNormal[(i*2)+1].m_fOrigin);
  264. glTexCoord2d(i*(1/(double)m_iSegments), 1);
  265. if(!m_bSolidColor)
  266. glColor4fv(pRadialPoint[(i*2)+1].m_Color.m_fColor);
  267. glVertex3fv(pRadialPoint[(i*2)+1].m_fOrigin);
  268. glNormal3fv(pNextTopNormal->m_fOrigin);
  269. glTexCoord2d((i+1)*(1/(double)m_iSegments), 1); 
  270. if(!m_bSolidColor)
  271. glColor4fv(pNextTopPoint->m_Color.m_fColor);
  272. glVertex3fv(pNextTopPoint->m_fOrigin);
  273. glEnd();
  274. }
  275. else
  276. {
  277. glBegin(GL_TRIANGLE_STRIP);
  278. // ** Side of the Cylinder **
  279. glNormal3fv(pNormal[(i*2)].m_fOrigin);
  280. glTexCoord2d(i*(1/(double)m_iSegments), 0);
  281. if(!m_bSolidColor)
  282. glColor4fv(pRadialPoint[(i*2)].m_Color.m_fColor);
  283. glVertex3fv(pRadialPoint[(i*2)].m_fOrigin);
  284. glTexCoord2d((i+1)*(1/(double)m_iSegments), 0); 
  285. if(!m_bSolidColor)
  286. glColor4fv(pNextBasePoint->m_Color.m_fColor);
  287. glVertex3fv(pNextBasePoint->m_fOrigin);
  288. glTexCoord2d(i*(1/(double)m_iSegments), 1);
  289. if(!m_bSolidColor)
  290. glColor4fv(pRadialPoint[(i*2)+1].m_Color.m_fColor);
  291. glVertex3fv(pRadialPoint[(i*2)+1].m_fOrigin);
  292. glTexCoord2d((i+1)*(1/(double)m_iSegments), 1); 
  293. if(!m_bSolidColor)
  294. glColor4fv(pNextTopPoint->m_Color.m_fColor);
  295. glVertex3fv(pNextTopPoint->m_fOrigin);
  296. glEnd();
  297. }
  298. if(m_bSolid)
  299. {
  300. glBegin(GL_TRIANGLES);
  301. // ** Bottom of the Cylinder **
  302. // Calculate the normal for the triangle
  303. CalNormalf(pBaseCenter->m_fOrigin,
  304.    pRadialPoint[(i*2)].m_fOrigin,
  305.    pNextBasePoint->m_fOrigin,
  306.    Normal);
  307. glNormal3fv(Normal);
  308. glTexCoord2d(0.5, 0.5);
  309. if(!m_bSolidColor)
  310. glColor4fv(pBaseCenter->m_Color.m_fColor);
  311. glVertex3fv(pBaseCenter->m_fOrigin);
  312. glTexCoord2d((x1*0.5)+0.5, 1-((y1*0.5)+0.5)); 
  313. if(!m_bSolidColor)
  314. glColor4fv(pNextBasePoint->m_Color.m_fColor);
  315. glVertex3fv(pNextBasePoint->m_fOrigin);
  316. glTexCoord2d((x0*0.5)+0.5, 1-((y0*0.5)+0.5)); 
  317. if(!m_bSolidColor)
  318. glColor4fv(pRadialPoint[(i*2)].m_Color.m_fColor);
  319. glVertex3fv(pRadialPoint[(i*2)].m_fOrigin);
  320. // ** Top of the Cylinder **
  321. // Calculate the normal for the triangle
  322. CalNormalf(pTopCenter->m_fOrigin,
  323.    pNextTopPoint->m_fOrigin,
  324.    pRadialPoint[(i*2)+1].m_fOrigin,
  325.    Normal);
  326. glNormal3fv(Normal);
  327. glTexCoord2d(0.5, 0.5);
  328. if(!m_bSolidColor)
  329. glColor4fv(pTopCenter->m_Color.m_fColor);
  330. glVertex3fv(pTopCenter->m_fOrigin);
  331. glTexCoord2d((x0*0.5)+0.5, 1-((y0*0.5)+0.5)); 
  332. if(!m_bSolidColor)
  333. glColor4fv(pRadialPoint[(i*2)+1].m_Color.m_fColor);
  334. glVertex3fv(pRadialPoint[(i*2)+1].m_fOrigin);
  335. glTexCoord2d((x1*0.5)+0.5, 1-((y1*0.5)+0.5)); 
  336. if(!m_bSolidColor)
  337. glColor4fv(pNextTopPoint->m_Color.m_fColor);
  338. glVertex3fv(pNextTopPoint->m_fOrigin);
  339. glEnd();
  340. }
  341. }
  342. glEndList();
  343. }
  344. /////////////////////////////////////////////////////////////////////////////
  345. // C3dObjectCylinder Methods or Implementation
  346. void C3dObjectCylinder::InitVertices()
  347. {
  348. /* We define our cone as follows:
  349.          p7 ------ p5
  350.           /         
  351.         /             
  352.     p9 |       *p0    | p3
  353.        |              | 
  354.                     / 
  355.                   /  
  356.         P11 ------ pN+1
  357.          p6 ------ p4
  358.           /         
  359.         /             
  360.     p8 |       *p0    | p2
  361.        |              | 
  362.             BASE    / 
  363.                   /  
  364.         P10 ------ pN
  365. */
  366. C3dPoint* pPoint;
  367. int i;
  368. // Resize our array to ensure we have the memory for our points
  369. if(m_pPointArray->SetArraySize((m_iSegments*2)+2))
  370. return; // function failed
  371. // Set the point to the address of the first point
  372. // in the array
  373. pPoint= m_pPointArray->m_pPoints;
  374. // Initialize our disks vertice points
  375. Vec3f(0.0f, 0.0f, -m_fHeight/2, pPoint[0].m_fOrigin); // Set the base center
  376. Vec3f(0.0f, 0.0f,  m_fHeight/2, pPoint[1].m_fOrigin); // Apex
  377. // Now the points about the base radius
  378. for(i=0; i<m_iSegments; i++)
  379. {
  380. double a0  = i * (360/(double)m_iSegments);
  381. double x0 = Cosd(a0);
  382. double y0 = Sind(a0);
  383. pPoint[(i*2)+2].m_fOrigin[X] = (GLfloat)(m_fBaseRadius*x0);
  384. pPoint[(i*2)+2].m_fOrigin[Y] = (GLfloat)(m_fBaseRadius*y0);
  385. pPoint[(i*2)+2].m_fOrigin[Z] = (GLfloat)(-m_fHeight/2);
  386. pPoint[(i*2)+3].m_fOrigin[X] = (GLfloat)(m_fTopRadius*x0);
  387. pPoint[(i*2)+3].m_fOrigin[Y] = (GLfloat)(m_fTopRadius*y0);
  388. pPoint[(i*2)+3].m_fOrigin[Z] = (GLfloat)(m_fHeight/2);
  389. }
  390. }
  391. void C3dObjectCylinder::CalNormals(C3dPoint* pNormals, BOOL bSmooth)
  392. {
  393. // Calculate the normals for each point about the sides of 
  394. // the cylinder.
  395. C3dPointArray FaceNormals;
  396. int i;
  397. // Create a temporary array to store our face normals
  398. FaceNormals.Create((m_iSegments*2)+2);
  399. C3dPoint* pRadialPoint = &m_pPointArray->m_pPoints[2]; // third point in array
  400. C3dPoint* pNextBasePoint; // Pointer to the next radial base point
  401. C3dPoint* pNextTopPoint; // Pointer to the next radial top point
  402. C3dPoint* pFaceNormal = &FaceNormals.m_pPoints[2];
  403. // First calculate the normals for each face (triangle) of the cylinder
  404. // and store them in the FaceNormal array.
  405. for(i=0; i<m_iSegments; i++)
  406. {
  407. if(i==m_iSegments-1)
  408. {
  409. // First radial points
  410. pNextBasePoint = &m_pPointArray->m_pPoints[2];
  411. pNextTopPoint  = &m_pPointArray->m_pPoints[3];
  412. }
  413. else
  414. {
  415. // Next radial points
  416. pNextBasePoint = &pRadialPoint[(i*2)+2];
  417. pNextTopPoint  = &pRadialPoint[(i*2)+3];
  418. }
  419. // Calculate the normal for the triangle
  420. CalNormalf(pRadialPoint[(i*2)].m_fOrigin,
  421.    pRadialPoint[(i*2)+1].m_fOrigin,
  422.    pNextBasePoint->m_fOrigin,
  423.    pFaceNormal[(i*2)].m_fOrigin);
  424. CalNormalf(pRadialPoint[(i*2)+1].m_fOrigin,
  425.    pNextTopPoint->m_fOrigin,
  426.    pRadialPoint[(i*2)].m_fOrigin,
  427.    pFaceNormal[(i*2)+1].m_fOrigin);
  428. }
  429. if(bSmooth)
  430. {
  431. // Now that we have the face normals, calculate the point normals for each
  432. // vertice by averaging the adjacent face normals of each vertice.
  433. C3dPoint* PreviousBaseNormal;
  434. C3dPoint* PreviousTopNormal;
  435. for(i=0; i<m_iSegments; i++)
  436. {
  437. if(i==0)
  438. {
  439. // Last face normal
  440. PreviousBaseNormal = &pFaceNormal[(m_iSegments*2)-2];
  441. PreviousTopNormal  = &pFaceNormal[(m_iSegments*2)-1];
  442. }
  443. else
  444. {
  445. // Previous face normal
  446. PreviousBaseNormal = &pFaceNormal[(i*2)-2];
  447. PreviousTopNormal  = &pFaceNormal[(i*2)-1];
  448. }
  449. VecAddf(PreviousBaseNormal->m_fOrigin,
  450. pFaceNormal[(i*2)].m_fOrigin,
  451. pNormals[(i*2)+2].m_fOrigin); // Bottom radial point normal
  452. pNormals[(i*2)+2].m_fOrigin[X] = pNormals[(i*2)+2].m_fOrigin[X]/2;
  453. pNormals[(i*2)+2].m_fOrigin[Y] = pNormals[(i*2)+2].m_fOrigin[Y]/2;
  454. pNormals[(i*2)+2].m_fOrigin[Z] = pNormals[(i*2)+2].m_fOrigin[Z]/2;
  455. VecAddf(PreviousTopNormal->m_fOrigin,
  456. pFaceNormal[(i*2)+1].m_fOrigin,
  457. pNormals[(i*2)+3].m_fOrigin); // Top radial point normal
  458. pNormals[(i*2)+3].m_fOrigin[X] = pNormals[(i*2)+3].m_fOrigin[X]/2;
  459. pNormals[(i*2)+3].m_fOrigin[Y] = pNormals[(i*2)+3].m_fOrigin[Y]/2;
  460. pNormals[(i*2)+3].m_fOrigin[Z] = pNormals[(i*2)+3].m_fOrigin[Z]/2;
  461. }
  462. }
  463. else
  464. {
  465. // Just copy the normals
  466. for(i=0; i<=(m_iSegments*2); i++)
  467. VecCopy3f(pFaceNormal[i].m_fOrigin,
  468.   pNormals[i+2].m_fOrigin);
  469. }
  470. }