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

OpenGL

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // 3dObject.cpp : Implementation file of the C3dObject class
  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. #include "AnimationDialog.h"
  23. #include "MyFileIO.h"
  24. #include <stdio.h>
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. //////////////////////////////////////////////////////////////////
  31. // C3dObject
  32. IMPLEMENT_DYNAMIC(C3dObject, CObject)
  33. /////////////////////////////////////////////////////////////////////////////
  34. // C3dObject construction
  35. C3dObject::C3dObject()
  36. {
  37. // Assign default values to member attributes..
  38. m_Color.SetColor4f(1.0f, 1.0f, 1.0f, 1.0f); // White
  39. SetOrigin(0.0f, 0.0f, 0.0f, 0.0f);
  40. SetRotation(0.0f, 0.0f, 0.0f);
  41. SetScale(1.0f, 1.0f, 1.0f);
  42. SetTranslation(0.0f, 0.0f, 0.0f);
  43. m_pParent = NULL;
  44. m_pMaterial = NULL;
  45. m_pTexture = NULL;
  46. m_pQuad         = NULL;
  47. m_pPointArray = NULL;
  48. m_bInside = FALSE;
  49. m_bSolidColor = TRUE;
  50. m_iBMImage = -1;
  51. m_bBuildLists = TRUE;
  52. m_iDisplayLists = 0;
  53. // Assign an integer name to this object
  54. m_iName = iGlobalNamesList++;
  55. }
  56. /////////////////////////////////////////////////////////////////////////////
  57. // C3DWorld Destructor
  58. C3dObject::~C3dObject()
  59. {
  60. if(m_pTexture)
  61. delete m_pTexture;
  62. // Delete the Objects attached to this Object
  63. m_ObjectList.DeleteAll();
  64. // Delete the DisplayLists if the Derived object
  65. // did not...
  66. if(m_iDisplayLists)
  67. {
  68. glDeleteLists(m_iDisplayLists, 1);
  69. m_iDisplayLists = 0;
  70. }
  71. // Delete all animation procedures attached to this object
  72. m_AnimList.DeleteAll();
  73. }
  74. /////////////////////////////////////////////////////////////////////////////
  75. // C3dObject virtual methods or functions
  76. void C3dObject::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
  77. {
  78. // Virtual prototype function only!  Add specific
  79. // functionality to your derived object class!
  80. }
  81. void C3dObject::Animate(double time)
  82. {
  83. // Animate the shape based on its animation procedures
  84. CAnimation* pAnimation = NULL;
  85. // walk the list
  86. POSITION Pos = m_AnimList.GetHeadPosition();
  87. while (Pos) {
  88. pAnimation = m_AnimList.GetAt(Pos);
  89. pAnimation->AnimateObject(this, time);
  90. pAnimation = m_AnimList.GetNext(Pos);
  91. }
  92. // Animate all child objects of this object
  93. C3dObject* pObject = NULL;
  94. // walk the list
  95. Pos = m_ObjectList.GetHeadPosition();
  96. while (Pos) {
  97. pObject = m_ObjectList.GetAt(Pos);
  98. pObject->Animate(time);
  99. pObject = m_ObjectList.GetNext(Pos);
  100. }
  101. }
  102. void C3dObject::GetShapeBounds(C3dBoundingBox* pBox)
  103. {
  104. if(m_pPointArray)
  105. m_pPointArray->GetMinMax(pBox);
  106. }
  107. void C3dObject::DisplayObject(C3dWorld* pWorld, C3dCamera* pCamera)
  108. {
  109. // Save the current transformation matrix..
  110.   glPushMatrix();
  111. // Transform our object
  112. TransformObject(pWorld);
  113. if(this == pWorld->m_pSelectedObj)
  114. {
  115. DisplaySelected(pWorld, FALSE);
  116. if(pWorld->m_bDisplayPoints)
  117. // Display all points in our object
  118. DisplayPoints(pWorld, pCamera);
  119. }
  120. // Save the name on the stack.  This will be used to determine
  121. // hits from the selection buffer
  122. glLoadName(m_iName);
  123. // Setup this objects polygon color material
  124. // or texture attributes
  125. SetAttributes(pWorld, m_pQuad);
  126. if(m_bBuildLists) // Do we need to build the display lists?
  127. {
  128. if(!m_iDisplayLists)
  129. m_iDisplayLists = glGenLists(1);// Create the DisplayList(s)
  130. Build(pWorld, pCamera); // Build the shape
  131. m_bBuildLists = FALSE; // Set the flag
  132. }
  133. else
  134. glCallList(m_iDisplayLists); // Display the list
  135. // Display all child objects of this object
  136. DisplayChildObjects(pWorld, pCamera);
  137. // Restore the current transformation matrix..
  138. glPopMatrix();
  139. }
  140. int C3dObject::LoadBitMapImage(CImageList* pList)
  141. {
  142. // Virtual prototype function only!  Add specific
  143. // functionality to your derived object class!
  144. return 0;
  145. }
  146. void C3dObject::Serialize(CArchive& ar, int iVersion)
  147. {
  148. CString szBuffer;
  149. CString szName;
  150. CString szTemp;
  151. CString szIndentSave;
  152. szBuffer.GetBuffer(256);
  153. szName.GetBuffer(128);
  154. if (ar.IsStoring())
  155. {
  156. // Save the Base Class Object Data...
  157. szBuffer.Format("%stName          < %s >n", szIndent, m_szName);
  158. ar.WriteString(szBuffer);
  159. szBuffer.Format("%stColor         < %f %f %f %f > // RGBAn", szIndent, m_Color.m_fColor[0], m_Color.m_fColor[1], m_Color.m_fColor[2], m_Color.m_fColor[3]);
  160. ar.WriteString(szBuffer);
  161. szBuffer.Format("%stOrigin        < %f %f %f %f >n", szIndent, m_fOrigin[0], m_fOrigin[1], m_fOrigin[2], m_fOrigin[3]);
  162. ar.WriteString(szBuffer);
  163. szBuffer.Format("%stRotation      < %f %f %f >n", szIndent, m_fRotation[0], m_fRotation[1], m_fRotation[2]);
  164. ar.WriteString(szBuffer);
  165. szBuffer.Format("%stScale         < %f %f %f >n", szIndent, m_fScale[0], m_fScale[1], m_fScale[2]);
  166. ar.WriteString(szBuffer);
  167. szBuffer.Format("%stTranslate     < %f %f %f >n", szIndent, m_fTranslate[0], m_fTranslate[1], m_fTranslate[2]);
  168. ar.WriteString(szBuffer);
  169. // If there is a material attached to this object
  170. // save the material name
  171. if(m_pMaterial)
  172. szName = m_pMaterial->m_szName;
  173. else
  174. szName = "None";
  175. szBuffer.Format("%stMaterial Name < %s >n", szIndent, szName);
  176. ar.WriteString(szBuffer);
  177. // If there is a texture map attached to this object
  178. // save the file name and serialize the object
  179. if(m_pTexture)
  180. {
  181. szName = m_pTexture->m_szFileName;
  182. szBuffer.Format("%stTexture Map   < %s >n", szIndent, szName);
  183. ar.WriteString(szBuffer);
  184. // Save the current indention and indent
  185. // all CAnimation class procedures
  186. szIndentSave = szIndent;
  187. szIndent += _T("tt"); // Add tabs
  188. // Serialize the texturemap
  189. m_pTexture->Serialize(ar, iVersion);
  190. // Restore indent position
  191. szIndent = szIndentSave; // restore indent
  192. }
  193. else
  194. {
  195. szName = "None";
  196. szBuffer.Format("%stTexture Map   < %s >n", szIndent, szName);
  197. ar.WriteString(szBuffer);
  198. }
  199. // Save any CAnimation derived class procedure(s)
  200. m_AnimList.Serialize(ar, iVersion);
  201. // Finished saving object data //
  202. // Save all child objects of this object
  203. SaveChildObjects(ar, iVersion);
  204. }
  205. else
  206. {
  207. // Read the Base Class Object data...
  208. // Get the Name of this object.  Note that the
  209. // name may contain spaces, so we extract the 
  210. // string between the < > characters..
  211. ar.ReadString(szBuffer);
  212. // locate the position of the brackets
  213. int begin = szBuffer.Find("<");
  214. int end = szBuffer.Find(">");
  215. if(end > begin)
  216. {
  217. // extract the objectname from within the barckets
  218. m_szName = szBuffer.Mid(begin+1, (end-begin)-1);
  219. m_szName.TrimLeft(); // trim leading spaces
  220. m_szName.TrimRight(); // trim tailing spaces
  221. }
  222. ar.ReadString(szBuffer);
  223. szBuffer.TrimLeft();
  224. sscanf(szBuffer, "Color         < %f %f %f %f >n", &m_Color.m_fColor[0], &m_Color.m_fColor[1], &m_Color.m_fColor[2], &m_Color.m_fColor[3]);
  225. ar.ReadString(szBuffer);
  226. szBuffer.TrimLeft();
  227. sscanf(szBuffer, "Origin        < %f %f %f %f >n", &m_fOrigin[0], &m_fOrigin[1], &m_fOrigin[2], &m_fOrigin[3]);
  228. ar.ReadString(szBuffer);
  229. szBuffer.TrimLeft();
  230. sscanf(szBuffer, "Rotation      < %f %f %f >n", &m_fRotation[0], &m_fRotation[1], &m_fRotation[2]);
  231. ar.ReadString(szBuffer);
  232. szBuffer.TrimLeft();
  233. sscanf(szBuffer, "Scale         < %f %f %f >n", &m_fScale[0], &m_fScale[1], &m_fScale[2]);
  234. ar.ReadString(szBuffer);
  235. szBuffer.TrimLeft();
  236. sscanf(szBuffer, "Translate     < %f %f %f >n", &m_fTranslate[0], &m_fTranslate[1], &m_fTranslate[2]);
  237. ar.ReadString(szBuffer);
  238. szBuffer.TrimLeft();
  239. sscanf(szBuffer, "Material Name < %s >n", szName);
  240. if(szName.Compare("None") !=0) {
  241. // Object has a material name assigned...
  242. if(pMatlList) {
  243. // Get a pointer to the material name stored
  244. // in the file and save the address in our
  245. // member pointer.
  246. m_pMaterial = pMatlList->Find(szName);
  247. }
  248. }
  249. ar.ReadString(szBuffer);
  250. szBuffer.TrimLeft();
  251. szTemp = szBuffer.Left(11);
  252. if(szTemp.Compare("Texture Map") == 0)
  253. {
  254. // locate the position of the brackets
  255. int begin = szBuffer.Find("<");
  256. int end = szBuffer.Find(">");
  257. if(end > begin)
  258. {
  259. // extract the texture file name from within the barckets
  260. szName = szBuffer.Mid(begin+1, (end-begin)-1);
  261. szName.TrimLeft(); // trim leading spaces
  262. szName.TrimRight(); // trim tailing spaces
  263. if(szName.Compare("None") !=0)
  264. {
  265. AddTexture(szName.GetBuffer(128));
  266. if(iVersion > 102)
  267. {
  268. if(m_pTexture)
  269. m_pTexture->Serialize(ar, iVersion);
  270. else
  271. {
  272. // File could not be opened, so we must read ahead to
  273. // the next object attribute.
  274. // We must continue reading until we find the texture
  275. // derived class defined end marker!
  276. while(ar.ReadString(szBuffer))
  277. {
  278. szBuffer.TrimLeft();
  279. if(strcmp(szBuffer, "}n") == 0)
  280. break;
  281. if(strcmp(szBuffer, "}") == 0)
  282. break;
  283. }
  284. }
  285. }
  286. }
  287. }
  288. }
  289. if(iVersion > 101)
  290. {
  291. // Load any CAnimation derived class procedure(s)
  292. m_AnimList.Serialize(ar, iVersion);
  293. // Read all child objects...
  294. LoadChildObjects(ar, iVersion);
  295. }
  296. if(m_bSolidColor)
  297. // copy our current color to all point vertices
  298. SetColor4fv(&m_Color);
  299. }
  300. }
  301. void C3dObject::Build(C3dWorld* pWorld, C3dCamera* pCamera)
  302. {
  303. // Virtual prototype function only!  Add specific
  304. // functionality to your derived object class!
  305. }
  306. void C3dObject::DisplayPoints(C3dWorld* pWorld, C3dCamera* pCamera)
  307. {
  308. // Display all points in our object
  309. if(m_pPointArray)
  310. {
  311. if(m_pPointArray->m_pPoints)
  312. m_pPointArray->Display(pWorld, pCamera, this, 2.0f, FALSE);
  313. }
  314. }
  315. C3dPoint* C3dObject::FindPoint(C3dCamera* pCamera, float x, float y, float z)
  316. {
  317. // Search the array for a C3dPoint which passes through the vector from the
  318. // camera to the xyz World coordinate.
  319. if(m_pPointArray)
  320. return m_pPointArray->Find(pCamera, this, x, y, z);
  321. else
  322. return NULL;
  323. }
  324. void C3dObject::SetObjPointOrigin(C3dPoint* pPoint, float x, float y, float z)
  325. {
  326. ASSERT(pPoint);
  327. pPoint->SetOrigin(x, y, z);
  328. }
  329. void C3dObject::GetObjPointOrigin(C3dPoint* pPoint, float *x, float *y, float *z)
  330. {
  331. ASSERT(pPoint);
  332. pPoint->GetOrigin(x, y, z);
  333. }
  334. /////////////////////////////////////////////////////////////////////////////
  335. // C3dObject static functions
  336. C3dObject* C3dObject::IsLightClass(CString* szString)
  337. {
  338. // Dynamically create an object given its run-time
  339. // class.  Use the following code to dynamically
  340. // create an object by using the CreateObject
  341. // function of the CRuntimeClass. Note that on 
  342. // failure, CreateObject returns NULL instead of
  343. // raising an exception:
  344. /*
  345.   
  346. // this is not working properly.. replaced with manual 
  347. // string comparisons..
  348.   
  349. CString szClassName;
  350. szClassName.GetBuffer(128);
  351. szClassName.Format("%s", szString);
  352. szClassName.TrimRight();
  353. C3dObject object;
  354. CRuntimeClass* prt = object.GetRuntimeClass();
  355. if( strcmp( prt->m_lpszClassName, "C3dObject" )  == 0 );
  356. int temp = 0;
  357. // CRuntimeClass* pRuntimeClass = RUNTIME_CLASS( szClassName );
  358. // CObject* pObject = pRuntimeClass->CreateObject();
  359. // ASSERT( pObject->IsKindOf( RUNTIME_CLASS( szClassName ) ) );
  360. */
  361. if(szString->Compare("C3dObjectLight {") == 0) {
  362. C3dObjectLight* pLight = new C3dObjectLight;
  363. ASSERT(pLight);
  364. return pLight;
  365. }
  366. // The following class is left for compatability with versions
  367. // 1.03 and earlier.
  368. if(szString->Compare("C3dLightAmbient {") == 0) {
  369. C3dObjectLight* pLight = new C3dObjectLight;
  370. ASSERT(pLight);
  371. return pLight;
  372. }
  373. if(szString->Compare("C3dLightDirectional {") == 0) {
  374. C3dObjectLight* pLight = new C3dObjectLight;
  375. ASSERT(pLight);
  376. return pLight;
  377. }
  378. // light object does not match available types..
  379. return NULL;
  380. }
  381. C3dObject* C3dObject::IsShapeClass(CString* szString)
  382. {
  383. // If other C3dObject derived classes are created, either
  384. // add the appropriate string comparison/creation function or
  385. // figure out how to create based on Runtime class..
  386. // 
  387. if(szString->Compare("C3dObjectCloud {") == 0) {
  388. C3dObjectCloud* pObject = new C3dObjectCloud;
  389. ASSERT(pObject);
  390. return pObject;
  391. }
  392. if(szString->Compare("C3dObjectCone {") == 0) {
  393. C3dObjectCone* pObject = new C3dObjectCone;
  394. ASSERT(pObject);
  395. return pObject;
  396. }
  397. if(szString->Compare("C3dObjectCSG {") == 0) {
  398. C3dObjectCSG* pObject = new C3dObjectCSG;
  399. ASSERT(pObject);
  400. return pObject;
  401. }
  402. if(szString->Compare("C3dObjectCube {") == 0) {
  403. C3dObjectCube* pObject = new C3dObjectCube;
  404. ASSERT(pObject);
  405. return pObject;
  406. }
  407. if(szString->Compare("C3dObjectCylinder {") == 0) {
  408. C3dObjectCylinder* pObject = new C3dObjectCylinder;
  409. ASSERT(pObject);
  410. return pObject;
  411. }
  412. if(szString->Compare("C3dObjectDisk {") == 0) {
  413. C3dObjectDisk* pObject = new C3dObjectDisk;
  414. ASSERT(pObject);
  415. return pObject;
  416. }
  417. if(szString->Compare("C3dObjectGrid {") == 0) {
  418. C3dObjectGrid* pObject = new C3dObjectGrid;
  419. ASSERT(pObject);
  420. return pObject;
  421. }
  422. if(szString->Compare("C3dObjectHSpline {") == 0) {
  423. C3dObjectHSpline* pObject = new C3dObjectHSpline;
  424. ASSERT(pObject);
  425. return pObject;
  426. }
  427. if(szString->Compare("C3dObjectLathe {") == 0) {
  428. C3dObjectLathe* pObject = new C3dObjectLathe;
  429. ASSERT(pObject);
  430. return pObject;
  431. }
  432. if(szString->Compare("C3dObjectNURB {") == 0) {
  433. C3dObjectNURB* pObject = new C3dObjectNURB;
  434. ASSERT(pObject);
  435. return pObject;
  436. }
  437. if(szString->Compare("C3dObjectPlane {") == 0) {
  438. C3dObjectPlane* pObject = new C3dObjectPlane;
  439. ASSERT(pObject);
  440. return pObject;
  441. }
  442. if(szString->Compare("C3dObjectSphere {") == 0) {
  443. C3dObjectSphere* pObject = new C3dObjectSphere;
  444. ASSERT(pObject);
  445. return pObject;
  446. }
  447. if(szString->Compare("C3dObjectTerrain {") == 0) {
  448. C3dObjectTerrain* pObject = new C3dObjectTerrain;
  449. ASSERT(pObject);
  450. return pObject;
  451. }
  452. if(szString->Compare("C3dObjectTorus {") == 0) {
  453. C3dObjectTorus* pObject = new C3dObjectTorus;
  454. ASSERT(pObject);
  455. return pObject;
  456. }
  457. if(szString->Compare("C3dObjectTriangle {") == 0) {
  458. C3dObjectTriangle* pObject = new C3dObjectTriangle;
  459. ASSERT(pObject);
  460. return pObject;
  461. }
  462. if(szString->Compare("C3dObjectTTF {") == 0) {
  463. C3dObjectTTF* pObject = new C3dObjectTTF;
  464. ASSERT(pObject);
  465. return pObject;
  466. }
  467. // Object shape does not match available types..
  468. return NULL;
  469. }
  470. C3dObject* C3dObject::LoadObject(CString szFileName, int* iType)
  471. {
  472. CFile f;
  473. CFileException fe;
  474. float fVersion;
  475. int iVersion;
  476. if( !f.Open( szFileName, CFile::modeRead, &fe ) ) {
  477. // Error!  Display message to the user..
  478. CString buffer;
  479. buffer.Format("Could not open object file '%s'!n", szFileName);
  480. AfxMessageBox(buffer, MB_OK, 0);
  481. #ifdef _DEBUG
  482. afxDump << "Unable to open object file" << "n";
  483. #endif
  484. return NULL;
  485. }
  486. CArchive ar( &f, CArchive::load );
  487.  
  488. // Load the object data...
  489. try {
  490. CString szBuffer;
  491. // Read the version number
  492. ar.ReadString(szBuffer);
  493. sscanf(szBuffer, "// Version: %fn", &fVersion);
  494. iVersion = Roundf(fVersion*100);
  495. if(iVersion < 101)
  496. iVersion  = 101; // File had no version number, so assign default
  497. // Load all C3dObjects derived objects..
  498. while(ar.ReadString(szBuffer)) {
  499. C3dObject* pObject = NULL;
  500. szBuffer.TrimLeft(); // Remove leading white spaces
  501. pObject = C3dObject::IsShapeClass(&szBuffer);
  502. if(pObject)
  503. {
  504. *iType = SHAPE_OBJECT;
  505. pObject->Serialize(ar, iVersion);
  506. return pObject;
  507. }
  508. pObject = C3dObject::IsLightClass(&szBuffer);
  509. if(pObject)
  510. {
  511. *iType = LIGHT_OBJECT;
  512. pObject->Serialize(ar, iVersion);
  513. return pObject;
  514. }
  515. }
  516. }
  517. catch (CFileException exception) {
  518. // Catch any exceptions that may be thrown and
  519. // display for the user...
  520. DisplayFileIOException(&exception);
  521. }
  522. AfxMessageBox("Invalid File Format!  3D Object type not found.", MB_OK, NULL);
  523. return NULL;
  524. }
  525. /////////////////////////////////////////////////////////////////////////////
  526. // C3dObject implementation
  527. void C3dObject::AddAnimationPages(C3dWorld* pWorld, LPVOID pSht)
  528. {
  529. CAnimPropSheet* pSheet = (CAnimPropSheet*)pSht;
  530. ASSERT(pSheet);
  531. // Load all animation pages for this object
  532. CAnimation* pAnimation = NULL;
  533. // walk the list
  534. POSITION Pos = m_AnimList.GetHeadPosition();
  535. while (Pos) {
  536. pAnimation = m_AnimList.GetAt(Pos);
  537. pAnimation->AddAnimationPage(pSht, this, NULL, NULL);
  538. pAnimation = m_AnimList.GetNext(Pos);
  539. }
  540. }
  541. void C3dObject::ResetAnimation()
  542. {
  543. // Reset the objects animation variables
  544. CAnimation* pAnimation = NULL;
  545. // walk the list
  546. POSITION Pos = m_AnimList.GetHeadPosition();
  547. while (Pos) {
  548. pAnimation = m_AnimList.GetAt(Pos);
  549. pAnimation->RestoreObjectAttributes(this);
  550. pAnimation = m_AnimList.GetNext(Pos);
  551. }
  552. // Reset all child objects of this object
  553. C3dObject* pObject = NULL;
  554. // walk the list
  555. Pos = m_ObjectList.GetHeadPosition();
  556. while (Pos) {
  557. pObject = m_ObjectList.GetAt(Pos);
  558. pObject->ResetAnimation();
  559. pObject = m_ObjectList.GetNext(Pos);
  560. }
  561. }
  562. void C3dObject::SaveObject(CString szFileName)
  563. {
  564. CFile f;
  565. CFileException fe;
  566. if( !f.Open( szFileName, CFile::modeCreate | CFile::modeReadWrite, &fe))
  567. {
  568. // Error!  Display message to the user..
  569. CString buffer;
  570. buffer.Format("Could not open object file '%s'!n", szFileName);
  571. AfxMessageBox(buffer, MB_OK, 0);
  572. #ifdef _DEBUG
  573. afxDump << "Unable to open file" << "n";
  574. #endif
  575. }
  576. // Construct a CArchive object and specify whether it will be used for
  577. // loading or storing objects.
  578. CArchive ar( &f, CArchive::store );
  579. // Store, or save the object data...
  580. try
  581. {
  582. // Save the file version information
  583. ar.WriteString(szFileVersion);
  584. // Save the file header information
  585. ar.WriteString(szObjectFileHeader);
  586. ar.WriteString(szIWDFileHeader);
  587. // Save the object data
  588. Serialize(ar, iFileVersion);
  589. }
  590. catch (CFileException exception)
  591. {
  592. // Catch any exceptions that may be thrown and
  593. // display for the user...
  594. DisplayFileIOException(&exception);
  595. }
  596. }
  597. void C3dObject::LoadChildObjects(CArchive& ar, int iVersion)
  598. {
  599. CString szBuffer;
  600. // Load all Child Objects...
  601. ar.ReadString(szBuffer);
  602. do {
  603. C3dObject* pChildObject = NULL;
  604. szBuffer.TrimLeft(); // Remove leading white spaces
  605. if(szBuffer.Compare("}") == 0) // end of object def
  606. break;
  607. pChildObject = C3dObject::IsShapeClass(&szBuffer);
  608. if(pChildObject) {
  609. pChildObject->Serialize(ar, iVersion);
  610. AddChildObject(pChildObject);
  611. }
  612. } while(ar.ReadString(szBuffer));
  613. }
  614. void C3dObject::SaveChildObjects(CArchive& ar, int iVersion)
  615. {
  616. CString szIndentSave;
  617. CString szBuffer;
  618. // Save the current indention and indent
  619. // child object
  620. szIndentSave = szIndent;
  621. szIndent += _T("t"); // Add tab
  622. // Store, or save all Child Object data...
  623. C3dObject* pChildObject = NULL;
  624. // walk the list
  625. POSITION objectPos = m_ObjectList.GetHeadPosition();
  626. while (objectPos) {
  627. pChildObject = m_ObjectList.GetAt(objectPos);
  628. pChildObject->Serialize(ar, iVersion);
  629. pChildObject = m_ObjectList.GetNext(objectPos);
  630. }
  631. // Restore indent position
  632. szIndent = szIndentSave; // restore indent
  633. }
  634. void C3dObject::TransformObject(C3dWorld* pWorld)
  635. {
  636. // Translate the objects origin to world coordinates
  637. glTranslated(m_fOrigin[0], m_fOrigin[1], m_fOrigin[2]);
  638. // Rotate the object
  639. glRotated(m_fRotation[0], 1.0, 0.0, 0.0);
  640. glRotated(m_fRotation[1], 0.0, 1.0, 0.0);
  641. glRotated(m_fRotation[2], 0.0, 0.0, 1.0);
  642. if(this == pWorld->m_pSelectedObj)
  643. {
  644. // Display the objects axis?
  645. if(pWorld->m_bDisplayAxis)
  646. // Display the axis before we scale the object
  647. // and translate the object from its origin.
  648. DisplayAxis(pWorld);
  649. }
  650. // Scale the object
  651. glScaled(m_fScale[0], m_fScale[1], m_fScale[2]);
  652. // Translate the object relative to its origin (origin offset)
  653. glTranslated(m_fTranslate[0], m_fTranslate[1], m_fTranslate[2]);
  654. }
  655. void C3dObject::GetTransformMatrix(Matx4x4 XformMatrix, BOOL bGetParent)
  656. {
  657. // Calculate the objects' transformation matrix
  658. PrepareMatrix(m_fOrigin[X],    m_fOrigin[Y],    m_fOrigin[Z],
  659.   m_fScale[X],     m_fScale[Y],     m_fScale[Z],
  660.   m_fRotation[X],  m_fRotation[Y],  m_fRotation[Z],
  661.   m_fTranslate[X], m_fTranslate[Y], m_fTranslate[Z],
  662.   XformMatrix);
  663. // If this object has a parent, get the parents matrix and multiply by
  664. // its own
  665. if(m_pParent && bGetParent)
  666. {
  667. Matx4x4 ParentMatrix, temp;
  668. m_pParent->GetTransformMatrix(ParentMatrix);
  669. MultiplyMatricies(ParentMatrix, XformMatrix, temp);
  670. MatrixCopy(temp, XformMatrix);
  671. }
  672. }
  673. void C3dObject::GetInvTransformMatrix(Matx4x4 XformMatrix, BOOL bGetParent)
  674. {
  675. // Calculate the objects' transformation matrix
  676. PrepareInvMatrix(m_fOrigin[X],    m_fOrigin[Y],    m_fOrigin[Z],
  677.  m_fScale[X],     m_fScale[Y],     m_fScale[Z],
  678.  m_fRotation[X],  m_fRotation[Y],  m_fRotation[Z],
  679.  m_fTranslate[X], m_fTranslate[Y], m_fTranslate[Z],
  680.  XformMatrix);
  681. // If this object has a parent, get the parents matrix and multiply by
  682. // its own
  683. if(m_pParent && bGetParent)
  684. {
  685. Matx4x4 ParentMatrix, temp;
  686. m_pParent->GetInvTransformMatrix(ParentMatrix);
  687. MultiplyMatricies(XformMatrix, ParentMatrix, temp);
  688. MatrixCopy(temp, XformMatrix);
  689. }
  690. }
  691. void C3dObject::GetRotationMatrix(Matx4x4 XformMatrix, BOOL bGetParent)
  692. {
  693. // Calculate the objects' rotation matrix
  694. PrepareMatrix(0.0f, 0.0f, 0.0f, // Origin
  695.   1.0f, 1.0f, 1.0f, // Scale 
  696.   m_fRotation[X],  m_fRotation[Y],  m_fRotation[Z],
  697.   0.0f, 0.0f, 0.0f, // Translation
  698.   XformMatrix);
  699. // If this object has a parent, get the parents matrix and multiply by
  700. // its own
  701. if(m_pParent && bGetParent)
  702. {
  703. Matx4x4 ParentMatrix, temp;
  704. m_pParent->GetRotationMatrix(ParentMatrix);
  705. MultiplyMatricies(ParentMatrix, XformMatrix, temp);
  706. MatrixCopy(temp, XformMatrix);
  707. }
  708. }
  709. void C3dObject::GetInvRotationMatrix(Matx4x4 XformMatrix, BOOL bGetParent)
  710. {
  711. // Calculate the objects' transformation matrix
  712. PrepareInvMatrix(0.0f, 0.0f, 0.0f, // Origin
  713.  1.0f, 1.0f, 1.0f, // Scale 
  714.  m_fRotation[X], m_fRotation[Y], m_fRotation[Z],
  715.  0.0f, 0.0f, 0.0f, // Translation
  716.  XformMatrix);
  717. // If this object has a parent, get the parents matrix and multiply by
  718. // its own
  719. if(m_pParent && bGetParent)
  720. {
  721. Matx4x4 ParentMatrix, temp;
  722. m_pParent->GetInvRotationMatrix(ParentMatrix);
  723. MultiplyMatricies(XformMatrix, ParentMatrix, temp);
  724. MatrixCopy(temp, XformMatrix);
  725. }
  726. }
  727. void C3dObject::GetBounds(C3dBoundingBox* pBox, BOOL bWorldCoordinates)
  728. {
  729. Matx4x4 ObjXformMatrix;
  730. // Get the non-transformed shape bounding box coordinates
  731. GetShapeBounds(pBox);
  732. // Get the bounds of all child objects
  733. C3dObject* pChild = NULL;
  734. // walk the list
  735. POSITION childPos = m_ObjectList.GetHeadPosition();
  736. while (childPos) {
  737. Matx4x4 ChildXformMatrix;
  738. C3dBoundingBox childBoundingBox;
  739. // Get a pointer to the child object
  740. pChild = m_ObjectList.GetAt(childPos);
  741. // Get the non-transformed child object bounding rectangle
  742. pChild->GetBounds(&childBoundingBox, FALSE);
  743. // Get the transformation matrix of this child
  744. pChild->GetTransformMatrix(ChildXformMatrix);
  745. // Transform the child bounding box by its transformation
  746. // matrix to convert the bounding box to this childs 
  747. // coordinate space.
  748. childBoundingBox.TransformBounds(ChildXformMatrix);
  749. // Get the transformation matrix of this child objects' parent
  750. GetInvTransformMatrix(ObjXformMatrix);
  751. // Transform the child bounding box by its parents transformation
  752. // matrix to convert the bounding box to Parent coordinate space.
  753. childBoundingBox.TransformBounds(ObjXformMatrix);
  754. // Set the Min/Max bounding coordinates between the 
  755. // parent and child objects.
  756. pBox->SetMinMax(&childBoundingBox);
  757. // Get the next child object
  758. pChild = m_ObjectList.GetNext(childPos);
  759. }
  760. if(bWorldCoordinates)
  761. {
  762. // Get the object's transformation matrix
  763. GetTransformMatrix(ObjXformMatrix);
  764. // Transform the objects bounds by its transformation
  765. // matrix to convert the bounding box to world coordinates.
  766. pBox->TransformBounds(ObjXformMatrix);
  767. }
  768. }
  769. void C3dObject::AddChildObject(C3dObject* pObject)
  770. {
  771. // Add the object to 'this' objects' list
  772. ASSERT(pObject);
  773. pObject->m_pParent = (C3dObject*)this;
  774. this->m_ObjectList.Append(pObject);
  775. }
  776. void C3dObject::SetColor4fv(C3dColor* pColor)
  777. {
  778. // Set the objects color
  779. m_Color.SetColor4fv(pColor);
  780. if(m_pPointArray)
  781. {
  782. for(int i=0; i<m_pPointArray->m_iNumPoints; i++)
  783. m_pPointArray->m_pPoints[i].m_Color.SetColor4fv(pColor);
  784. }
  785. }
  786. void C3dObject::SetColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
  787. {
  788. // Set the objects color
  789. m_Color.SetColor4f(r, g, b, a);
  790. if(m_pPointArray)
  791. {
  792. for(int i=0; i<m_pPointArray->m_iNumPoints; i++)
  793. m_pPointArray->m_pPoints[i].m_Color.SetColor4f(r, g, b, a);
  794. }
  795. }
  796. void C3dObject::SetOrigin(GLfloat x, GLfloat y, GLfloat z)
  797. {
  798. // Set the origin to the supplied values..
  799. m_fOrigin[0] = x;
  800. m_fOrigin[1] = y;
  801. m_fOrigin[2] = z;
  802. }
  803. void C3dObject::SetOrigin(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  804. {
  805. // Set the origin to the supplied values..
  806. m_fOrigin[0] = x;
  807. m_fOrigin[1] = y;
  808. m_fOrigin[2] = z;
  809. m_fOrigin[3] = w;
  810. }
  811. void C3dObject::SetScale(GLfloat x, GLfloat y, GLfloat z)
  812. {
  813. // Prevent Scaling by Zero!
  814. if(x==0)
  815. x=(GLfloat)SMALL_NUMBER;
  816. if(y==0)
  817. y=(GLfloat)SMALL_NUMBER;
  818. if(z==0)
  819. z=(GLfloat)SMALL_NUMBER;
  820. m_fScale[0] = x;
  821. m_fScale[1] = y;
  822. m_fScale[2] = z;
  823. }
  824. void C3dObject::SetRotation(GLfloat x, GLfloat y, GLfloat z)
  825. {
  826. m_fRotation[0] = x;
  827. m_fRotation[1] = y;
  828. m_fRotation[2] = z;
  829. }
  830. void C3dObject::SetTranslation(GLfloat x, GLfloat y, GLfloat z)
  831. {
  832. m_fTranslate[0] = x;
  833. m_fTranslate[1] = y;
  834. m_fTranslate[2] = z;
  835. }
  836. void C3dObject::RemoveDibImage()
  837. {
  838. if(m_pTexture) {
  839. delete m_pTexture;
  840. m_pTexture = NULL;
  841. }
  842. else
  843. AfxMessageBox("No Bitmap to Remove..", MB_OK, 0);
  844. }
  845. void C3dObject::SetTexture(CTexture* pTexture)
  846. {
  847. // Set our objects texture map pointer
  848. if(m_pTexture)
  849. delete m_pTexture;
  850. m_pTexture = pTexture;
  851. }
  852. void C3dObject::SetMaterial(C3dMaterial* pMaterial)
  853. {
  854. // Set our objects material pointer
  855. m_pMaterial = pMaterial;
  856. }
  857. int C3dObject::EditAnimation(CWnd* pParentWnd, C3dWorld* pWorld)
  858. {
  859. char szName[80];
  860. sprintf(szName, "Edit Animation Attributes of object '%s'", m_szName);
  861. CAnimPropSheet* pAnimPropSheet = new CAnimPropSheet(szName, pParentWnd, this, NULL, pWorld);
  862. // Create and display the modal dialog box
  863. return( pAnimPropSheet->DoModal() );
  864. }
  865. int C3dObject::EditAttributes(CWnd* pParentWnd, C3dWorld* pWorld)
  866. {
  867. char szName[80];
  868. sprintf(szName, "Edit Attributes of object '%s'", m_szName);
  869. C3dObjectPropSheet* pObjectPropSheet = new C3dObjectPropSheet(szName, pParentWnd, this, pWorld);
  870. // Create and display the modal dialog box
  871. return( pObjectPropSheet->DoModal() );
  872. }
  873. void C3dObject::SetAttributes(C3dWorld* pWorld, void *pData)
  874. {
  875. GLUquadricObj* pQuad = (GLUquadricObj*) pData;
  876. if(pWorld)
  877. {
  878. if(pWorld->m_iRenderMode == RENDER_WIREFRAME)
  879. {
  880. // Reset color parameters to default values
  881. glDisable(GL_TEXTURE_2D);
  882. glDisable(GL_BLEND);
  883. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  884. glColor4fv(m_Color.m_fColor);
  885. glLineWidth(0.05f);
  886. if(pQuad)
  887. {
  888. gluQuadricDrawStyle(pQuad, GLU_LINE);
  889. gluQuadricTexture(pQuad, FALSE);
  890. }
  891. return;
  892. }
  893. }
  894. if(m_bInside)
  895. glFrontFace(GL_CW);
  896. else
  897. glFrontFace(GL_CCW);
  898. // Set the material properties
  899. if(m_pMaterial)
  900. // Set our objects material properties
  901. m_pMaterial->SetMaterialAttrib();
  902. else
  903. // Reset the material properties to default
  904. // settings and track the current color
  905. C3dMaterial::ResetMaterialAttrib();
  906. if(m_pTexture)
  907. {
  908. if(m_pTexture->m_iEnvmode == GL_BLEND)
  909. {
  910. glEnable(GL_BLEND);
  911. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  912. }
  913. else
  914. // Disable blend function
  915. glDisable(GL_BLEND);
  916. if(pQuad)
  917. {
  918. gluQuadricDrawStyle(pQuad, GLU_FILL);
  919. gluQuadricTexture(pQuad, TRUE);
  920. }
  921. if(m_pTexture->m_pBits)
  922. {
  923. // Apply the Dib Image to our shape..
  924. m_pTexture->SetTexture();
  925. return;
  926. }
  927. }
  928. else
  929. {
  930. // Reset color parameters to default values
  931. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  932. glDisable(GL_TEXTURE_2D);
  933. glColor4fv(m_Color.m_fColor);
  934. if(pQuad)
  935. {
  936. gluQuadricDrawStyle(pQuad, GLU_FILL);
  937. gluQuadricTexture(pQuad, FALSE);
  938. }
  939. if(m_Color.m_fColor[3] < 1.0f)
  940. {
  941. glEnable(GL_BLEND);
  942. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  943. }
  944. }
  945. }
  946. void C3dObject::GetOrigin(GLfloat *x, GLfloat *y, GLfloat *z)
  947. {
  948. // Get the origin
  949. *x = m_fOrigin[0];
  950. *y = m_fOrigin[1];
  951. *z = m_fOrigin[2];
  952. }
  953. void C3dObject::GetOrigin(GLfloat *x, GLfloat *y, GLfloat *z, GLfloat *w)
  954. {
  955. // Get the origin
  956. *x = m_fOrigin[0];
  957. *y = m_fOrigin[1];
  958. *z = m_fOrigin[2];
  959. *w = m_fOrigin[3];
  960. }
  961. void C3dObject::GetRotation(GLfloat *x, GLfloat *y, GLfloat *z)
  962. {
  963. // Get the lights rotation
  964. *x = m_fRotation[0];
  965. *y = m_fRotation[1];
  966. *z = m_fRotation[2];
  967. }
  968. void C3dObject::GetScale(GLfloat *x, GLfloat *y, GLfloat *z)
  969. {
  970. // Get the lights rotation
  971. *x = m_fScale[0];
  972. *y = m_fScale[1];
  973. *z = m_fScale[2];
  974. }
  975. void C3dObject::GetTranslation(GLfloat *x, GLfloat *y, GLfloat *z)
  976. {
  977. // Get the lights translation
  978. *x = m_fTranslate[0];
  979. *y = m_fTranslate[1];
  980. *z = m_fTranslate[2];
  981. }
  982. C3dObject* C3dObject::IsName(GLuint i, BOOL bSelParent)
  983. {
  984. if(i == m_iName)
  985. return this;
  986. // Name is not this object, is it one of its children?
  987. C3dObject* pSelectedObject; // C3dObject pointer
  988. // Display all objects attached to this world..
  989. C3dObject* pObject = NULL;
  990. // walk the list
  991. POSITION objectPos = m_ObjectList.GetHeadPosition();
  992. while (objectPos)
  993. {
  994. pObject = m_ObjectList.GetAt(objectPos);
  995. pSelectedObject = pObject->IsName(i, bSelParent);
  996. if(pSelectedObject)
  997. {
  998. if(bSelParent)
  999. return this;
  1000. else
  1001. return pSelectedObject;
  1002. }
  1003. pObject = m_ObjectList.GetNext(objectPos);
  1004. }
  1005. return NULL;
  1006. }
  1007. void C3dObject::DisplayChildObjects(C3dWorld* pWorld, C3dCamera* pCamera)
  1008. {
  1009. // Display all child objects attached to this object
  1010. C3dObject* pObject = NULL;
  1011. // walk the list
  1012. POSITION objectPos = m_ObjectList.GetHeadPosition();
  1013. while (objectPos) {
  1014. pObject = m_ObjectList.GetAt(objectPos);
  1015. pObject->DisplayObject(pWorld, pCamera);
  1016. pObject = m_ObjectList.GetNext(objectPos);
  1017. }
  1018. }
  1019. void C3dObject::DisplayAxis(C3dWorld* pWorld)
  1020. {
  1021. // Display the X, Y, Z Axis relative to this objects
  1022. // origin
  1023. pWorld->m_pAxis->Display( 3.0f, // Axis length
  1024.   0.05f, // Axis diameter
  1025.   0.5f, // Arrow length
  1026.   0.15f,// Arrow diameter
  1027.   6, // Number of slices around dia.
  1028.   2, // Number of Stacks about length
  1029.   NULL, // X-Axis Color (Use default..)
  1030.   NULL, // Y-Axis Color
  1031.   NULL, // Z-Axis Color
  1032.   TRUE); // Display as Solid
  1033. }
  1034. void C3dObject::DisplaySelected(C3dWorld* pWorld, BOOL bWorldCoordinates)
  1035. {
  1036. // Display a Bounding Box around the object
  1037. C3dBoundingBox BoundingBox;
  1038. GetBounds(&BoundingBox, bWorldCoordinates);
  1039. BoundingBox.Display(0.1f, // Rectangle offset
  1040. 0.3f, // box line width
  1041. 10, // line slices 
  1042. 2, // line segments
  1043. NULL, // box color (use Default)
  1044. TRUE); // display solid?
  1045. }
  1046. CAnimKeyFrame* C3dObject::GetKeyFrameList(int *iNumKeys) 
  1047. {
  1048. // Do we have a KeyFrame Procedure attached to this object?
  1049. CAnimKeyFrame* pAnimKey = (CAnimKeyFrame*) m_AnimList.Find("KeyFrame");
  1050. if(pAnimKey)
  1051. {
  1052. // Get the number of Keyframes in the list
  1053. *iNumKeys = pAnimKey->m_pKeyFrameList->GetNumKeys();
  1054. return pAnimKey;
  1055. }
  1056. *iNumKeys = 0;
  1057. return NULL;
  1058. }
  1059. BOOL C3dObject::AddTexture(LPSTR szFileName)
  1060. {
  1061. if(m_pTexture)
  1062. // If we already have a texture, delete it
  1063. DeleteTexture();
  1064. // Create a TextureMap of the appropriate type
  1065. CTexture::CreateTexture(szFileName, the3dEngine.m_hPalette, &m_pTexture);
  1066. if(m_pTexture)
  1067. {
  1068. // Is the TextureMap an CTextureAviMovie?
  1069. if( m_pTexture->IsKindOf(RUNTIME_CLASS(CTextureAviMovie)) )
  1070. {
  1071. // Create an AVI animation and add to the list
  1072. CAnimAVI* pAnim = new CAnimAVI;
  1073. ASSERT(pAnim);
  1074. m_AnimList.Append(pAnim);
  1075. // Cross link the two objects so that they are 'aware' of
  1076. // each other..
  1077. // Save the CTextureAviMovie pointer
  1078. pAnim->m_pAviMovie = (CTextureAviMovie*)m_pTexture;
  1079. // Save the CAnimAVI pointer
  1080. CTextureAviMovie* pAviVideo = (CTextureAviMovie*)m_pTexture;
  1081. pAviVideo->m_pAnimAVI = pAnim;
  1082. }
  1083. return TRUE;
  1084. }
  1085. else
  1086. return FALSE;
  1087. }
  1088. void C3dObject::DeleteTexture()
  1089. {
  1090. if(m_pTexture)
  1091. {
  1092. if( m_pTexture->IsKindOf(RUNTIME_CLASS(CTextureAviMovie)) )
  1093. {
  1094. // TextureMap is of class type CTextureAviMovie, so find the animation
  1095. // procedure in the list, remove from list and delete it..
  1096. CAnimation* pAnimation = m_AnimList.Find(SZ_ANIMATE_AVI);
  1097. if(pAnimation)
  1098. {
  1099. m_AnimList.Remove(pAnimation);
  1100. delete pAnimation;
  1101. }
  1102. }
  1103. // Now that we have removed any associated object members,
  1104. // delete the texturemap
  1105. delete m_pTexture;
  1106. m_pTexture = NULL;
  1107. }
  1108. }
  1109. void C3dObject::Rebuild()
  1110. {
  1111. // This function forces all objects and their children to rebuild
  1112. // their display lists.
  1113. // Force a rebuild of this objects display list
  1114. m_bBuildLists = TRUE;
  1115. C3dObject* pChild = NULL;
  1116. // walk the list
  1117. POSITION childPos = m_ObjectList.GetHeadPosition();
  1118. while (childPos)
  1119. {
  1120. pChild = m_ObjectList.GetAt(childPos);
  1121. pChild->Rebuild();
  1122. pChild = m_ObjectList.GetNext(childPos);
  1123. }
  1124. }