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

OpenGL

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // 3DWorld.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 "math.h"
  21. #include "glOOP.h"
  22. #include "3dObjectDialog.h"
  23. #include "3dBackgroundDialog.h"
  24. #include "AnimationDialog.h"
  25. #include "MyFileIO.h"
  26. #include <stdio.h>
  27. #include <wingdi.h>
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. /////////////////////////////////////////////////////////////////////////////
  34. // C3dWorld
  35. //IMPLEMENT_DYNAMIC(C3dWorld, CObject)
  36. IMPLEMENT_SERIAL(C3dWorld, CObject, 0)
  37. /////////////////////////////////////////////////////////////////////////////
  38. // C3dWorld construction
  39. C3dWorld::C3dWorld()
  40. {
  41. // Create a Grid class
  42. m_pGrid = C3dGrid::Create(0.0f); // use defaults
  43. ASSERT(m_pGrid);
  44. // Create a Axis class
  45. m_pAxis = C3dAxis::Create();
  46. ASSERT(m_pAxis);
  47. // Create a BoundingBox
  48. m_pBoundingBox = new C3dBoundingBox;
  49. ASSERT(m_pBoundingBox);
  50. // Create our default colors
  51. CreateDefColors(&m_ColorList);
  52. m_szColorFile = "Default.clr";
  53. // Create our default materials
  54. CreateDefMaterials(&m_MaterialList);
  55. m_szMatlFile = "Default.mtl";
  56. m_pSelectedObj = NULL;
  57. m_pSelectedPnt = NULL;
  58. m_iBMImage = -1;
  59. // Assign Default values to member variables
  60. m_szName.GetBuffer(128); // allocate 128 bytes min.
  61. m_szName = _T("");
  62. m_bAnimate = FALSE;
  63. m_bFly = FALSE;
  64. m_bDisplayAxis = TRUE;
  65. m_bDisplayGrid = TRUE;
  66. m_bDisplayPoints = FALSE;
  67. m_iRenderMode = RENDER_SMOOTH;
  68. m_bCullFaces = FALSE;
  69. m_bFogEnable = FALSE;
  70. m_pBkgndTexture = NULL;
  71. // Assign Default values to member attributes
  72. m_BackgroundColor.SetColor4f(0.0f, 0.0f, 0.0f, 1.0f); // black
  73. m_BackgroundColor.m_szName = _T("Black");
  74. // Set our default fog color to that of our background
  75. m_Fog.m_Color.SetColor3fv(&m_BackgroundColor);
  76. }
  77. /////////////////////////////////////////////////////////////////////////////
  78. // C3dWorld Destructor
  79. C3dWorld::~C3dWorld()
  80. {
  81. }
  82. void C3dWorld::DeleteWorld()
  83. {
  84. // Delete the Objects attached to the world
  85. m_ObjectList.DeleteAll();
  86. // Delete the Colors attached to the world
  87. m_ColorList.DeleteAll();
  88. // Delete the Materials attached to the world
  89. m_MaterialList.DeleteAll();
  90. // Delete the C3dGrid attached to the world
  91. if(m_pGrid) {
  92. delete m_pGrid;
  93. m_pGrid = NULL;
  94. }
  95. // Delete the C3dAxis attached to the world
  96. if(m_pAxis) {
  97. delete m_pAxis;
  98. m_pAxis = NULL;
  99. }
  100. // Delete the background texture map
  101. if(m_pBkgndTexture) {
  102. delete m_pBkgndTexture;
  103. m_pBkgndTexture = NULL;
  104. }
  105. // Delete the BoundingBox attached to the world
  106. if(m_pBoundingBox) {
  107. delete m_pBoundingBox;
  108. m_pBoundingBox = NULL;
  109. }
  110. // Delete all points in PointList
  111. m_PointList.DeleteAll();
  112. // Delete the world...
  113. delete this;
  114. }
  115. /////////////////////////////////////////////////////////////////////////////
  116. // C3dWorld static function implimentation
  117. C3dWorld* C3dWorld::CreateWorld()
  118. {
  119. // Create the World class
  120. C3dWorld* pWorld = new C3dWorld;
  121. ASSERT(pWorld);
  122. return pWorld;
  123. }
  124. /////////////////////////////////////////////////////////////////////////////
  125. // C3dWorld serialization
  126. void C3dWorld::Serialize(CArchive& ar, C3dCamera* pCamera)
  127. {
  128. CString szBuffer;
  129. CString szName;
  130. CString szFileName;
  131. CString szIndentSave;
  132. HCURSOR m_hcurSave;
  133. StartWait(); // Display hourglass cursor
  134. if (ar.IsStoring())
  135. {
  136. // Store, or save the World data...
  137. try
  138. {
  139. // Save the file version information
  140. ar.WriteString(szFileVersion);
  141. // Save the file header information
  142. ar.WriteString(szWorldFileHeader);
  143. ar.WriteString(szIWDFileHeader);
  144. // Save Include file information
  145. szBuffer.Format("#include   < %s > //Our Worlds Materialsnn", m_szMatlFile);
  146. ar.WriteString(szBuffer);
  147. // Store, or save the Camera data...
  148. pCamera->Serialize(ar, iFileVersion);
  149. // Save the World information
  150. szBuffer.Format("C3dWorld {n");
  151. ar.WriteString(szBuffer);
  152. szBuffer.Format("tName         < %s >n", m_szName);
  153. ar.WriteString(szBuffer);
  154. szBuffer.Format("tDisplayAxis  < %d >n", m_bDisplayAxis);
  155. ar.WriteString(szBuffer);
  156. szBuffer.Format("tDisplayGrid  < %d >n", m_bDisplayGrid);
  157. ar.WriteString(szBuffer);
  158. szBuffer.Format("tDisplayMode  < %d >n", m_iRenderMode);
  159. ar.WriteString(szBuffer);
  160. szBuffer.Format("tAnimateWorld < %d >n", m_bAnimate);
  161. ar.WriteString(szBuffer);
  162. // Save the fog information
  163. szBuffer.Format("tEnable Fog   < %d >n", m_bFogEnable);
  164. ar.WriteString(szBuffer);
  165. m_Fog.Serialize(ar, iFileVersion);
  166. // Save background color
  167. szBuffer.Format("tBackground Color:n");
  168. ar.WriteString(szBuffer);
  169. szIndentSave = szIndent; // Save the indent level
  170. szIndent += _T("t"); // Add tab
  171. m_BackgroundColor.Serialize(ar, iFileVersion);
  172. szIndent = szIndentSave; // Restore indention
  173. // If there is a background texture attached save the file
  174. // file name and serialize
  175. if(m_pBkgndTexture)
  176. {
  177. szName = m_pBkgndTexture->m_szFileName;
  178. szBuffer.Format("%stTexture Map   < %s >n", szIndent, szName);
  179. ar.WriteString(szBuffer);
  180. // Save the current indention and indent
  181. // all CAnimation class procedures
  182. szIndentSave = szIndent;
  183. szIndent += _T("tt"); // Add tabs
  184. // Serialize the texturemap
  185. m_pBkgndTexture->Serialize(ar, iFileVersion);
  186. // Restore indent position
  187. szIndent = szIndentSave; // restore indent
  188. }
  189. else
  190. {
  191. szName = "None";
  192. szBuffer.Format("%stTexture Map   < %s >n", szIndent, szName);
  193. ar.WriteString(szBuffer);
  194. }
  195. // Save any CAnimation derived class procedure(s)
  196. m_AnimList.Serialize(ar, iFileVersion);
  197. szBuffer.Format("}nn"); // end of world def
  198. ar.WriteString(szBuffer);
  199. // Store, or save the Object data...
  200. C3dObject* pObject = NULL;
  201. // walk the list
  202. POSITION objectPos = m_ObjectList.GetHeadPosition();
  203. while (objectPos) {
  204. pObject = m_ObjectList.GetAt(objectPos);
  205. pObject->Serialize(ar, iFileVersion);
  206. pObject = m_ObjectList.GetNext(objectPos);
  207. }
  208. }
  209. catch (CFileException exception) {
  210. // Catch any exceptions that may be thrown and
  211. // display for the user...
  212. DisplayFileIOException(&exception);
  213. }
  214. }
  215. else
  216. {
  217. float fVersion;
  218. int iVersion;
  219. pMatlList = &m_MaterialList;
  220. // Load or Read the World member variables
  221. try
  222. {
  223. // Read the version number
  224. ar.ReadString(szBuffer);
  225. sscanf(szBuffer, "// Version: %fn", &fVersion);
  226. iVersion = Roundf(fVersion*100);
  227. if(iVersion < 101)
  228. iVersion  = 101; // File had no version number, so assign default
  229. do
  230. {
  231. // Look for Inculde Files..
  232. CString sztemp;
  233. sztemp = szBuffer.Left(8);
  234. if(sztemp.Compare("#include") == 0) {
  235. // locate the position of the brackets
  236. int begin = szBuffer.Find("<");
  237. int end = szBuffer.Find(">");
  238. if(end > begin) {
  239. // extract the file name from within the barckets
  240. m_szMatlFile = szBuffer.Mid(begin+1, (end-begin)-1);
  241. m_szMatlFile.TrimLeft(); // trim leading spaces
  242. m_szMatlFile.TrimRight(); // trim tailing spaces
  243. m_MaterialList.LoadMaterials(m_szMatlFile);
  244. }
  245. }
  246. // Look for the Camera header...
  247. if(szBuffer.Compare("C3dCamera {") == 0)
  248. // Load the Camera data...
  249. pCamera->Serialize(ar, iVersion);
  250. // Look for the World header...
  251. if(szBuffer.Compare("C3dWorld {") == 0)
  252. break;
  253. } while(ar.ReadString(szBuffer));
  254. ar.ReadString(szBuffer);
  255. sscanf(szBuffer, "tName         < %s >n", m_szName);
  256. ar.ReadString(szBuffer);
  257. sscanf(szBuffer, "tDisplayAxis  < %d >n", &m_bDisplayAxis);
  258. ar.ReadString(szBuffer);
  259. sscanf(szBuffer, "tDisplayGrid  < %d >n", &m_bDisplayGrid);
  260. ar.ReadString(szBuffer);
  261. sscanf(szBuffer, "tDisplayMode  < %d >n", &m_iRenderMode);
  262. ar.ReadString(szBuffer);
  263. sscanf(szBuffer, "tAnimateWorld < %d >n", &m_bAnimate);
  264. if(iVersion > 130)
  265. {
  266. // Version 1.4 added serialization of background fog
  267. ar.ReadString(szBuffer);
  268. sscanf(szBuffer, "tEnable Fog   < %d >n", &m_bFogEnable);
  269. m_Fog.Serialize(ar, iVersion);
  270. }
  271. // Load the background color
  272. while(ar.ReadString(szBuffer))
  273. {
  274. szBuffer.TrimLeft(); // Remove leading white spaces
  275. // Look for the Color header...
  276. if(szBuffer.Compare("C3dColor {") == 0)
  277. {
  278. m_BackgroundColor.Serialize(ar, iVersion);
  279. break;
  280. }
  281. }
  282. if(iVersion > 102)
  283. {
  284. CString szTemp;
  285. ar.ReadString(szBuffer);
  286. szBuffer.TrimLeft();
  287. szTemp = szBuffer.Left(11);
  288. if(szTemp.Compare("Texture Map") == 0)
  289. {
  290. // locate the position of the brackets
  291. int begin = szBuffer.Find("<");
  292. int end = szBuffer.Find(">");
  293. if(end > begin)
  294. {
  295. // extract the texture file name from within the barckets
  296. szName = szBuffer.Mid(begin+1, (end-begin)-1);
  297. szName.TrimLeft(); // trim leading spaces
  298. szName.TrimRight(); // trim tailing spaces
  299. if(szName.Compare("None") !=0)
  300. {
  301. AddTexture(szName.GetBuffer(128));
  302. if(m_pBkgndTexture)
  303. m_pBkgndTexture->Serialize(ar, iVersion);
  304. }
  305. }
  306. }
  307. // Load any CAnimation derived class procedure(s)
  308. m_AnimList.Serialize(ar, iVersion);
  309. }
  310. ar.ReadString(szBuffer);
  311. sscanf(szBuffer, "}nn"); // end of world def
  312. // Load all Lights and Objects...
  313. while(ar.ReadString(szBuffer)) {
  314. C3dObject* pLight = NULL;
  315. C3dObject* pObject = NULL;
  316. szBuffer.TrimLeft(); // Remove leading white spaces
  317. pLight = C3dObject::IsLightClass(&szBuffer);
  318. if(pLight) {
  319. pLight->Serialize(ar, iVersion);
  320. AddObject(pLight, NULL);
  321. }
  322. pObject = C3dObject::IsShapeClass(&szBuffer);
  323. if(pObject) {
  324. pObject->Serialize(ar, iVersion);
  325. AddObject(pObject, NULL);
  326. }
  327. }
  328. }
  329. catch (CFileException exception) {
  330. // Catch any exceptions that may be thrown and
  331. // display for the user...
  332. DisplayFileIOException(&exception);
  333. }
  334. }
  335. EndWait(); // Remove hourglass cursor
  336. }
  337. /////////////////////////////////////////////////////////////////////////////
  338. // C3dWorld function implimentation
  339. void C3dWorld::AddAnimationPages(C3dWorld* pWorld, LPVOID pSht)
  340. {
  341. CAnimPropSheet* pSheet = (CAnimPropSheet*)pSht;
  342. ASSERT(pSheet);
  343. // Load all animation pages for this world
  344. CAnimation* pAnimation = NULL;
  345. // walk the list
  346. POSITION Pos = m_AnimList.GetHeadPosition();
  347. while (Pos) {
  348. pAnimation = m_AnimList.GetAt(Pos);
  349. pAnimation->AddAnimationPage(pSht, NULL, NULL, this);
  350. pAnimation = m_AnimList.GetNext(Pos);
  351. }
  352. }
  353. int C3dWorld::EditAnimation(CWnd* pParentWnd, C3dWorld* pWorld)
  354. {
  355. char szName[80];
  356. sprintf(szName, "Edit Animation Attributes of 3dWorld");
  357. CAnimPropSheet* pAnimPropSheet = new CAnimPropSheet(szName, pParentWnd, NULL, NULL, this);
  358. // Create and display the modal dialog box
  359. return( pAnimPropSheet->DoModal() );
  360. }
  361. void C3dWorld::Animate(C3dCamera* pCamera, double time)
  362. {
  363. // Animate the world based on its animation procedures
  364. CAnimation* pAnimation = NULL;
  365. // walk the list
  366. POSITION Pos = m_AnimList.GetHeadPosition();
  367. while (Pos) {
  368. pAnimation = m_AnimList.GetAt(Pos);
  369. pAnimation->AnimateWorld(this, time);
  370. pAnimation = m_AnimList.GetNext(Pos);
  371. }
  372. // Animate the camera
  373. if(pCamera)
  374. pCamera->Animate(time);
  375. // Animate all lights attached to this world..
  376. C3dObject* pLight = NULL;
  377. // walk the list
  378. POSITION lightPos = m_LightList.GetHeadPosition();
  379. while (lightPos) {
  380. pLight = m_LightList.GetAt(lightPos);
  381. pLight->Animate(time);
  382. pLight = m_LightList.GetNext(lightPos);
  383. }
  384. // Animate all objects attached to this world..
  385. C3dObject* pObject = NULL;
  386. // walk the list
  387. POSITION objectPos = m_ObjectList.GetHeadPosition();
  388. while (objectPos) {
  389. pObject = m_ObjectList.GetAt(objectPos);
  390. pObject->Animate(time);
  391. pObject = m_ObjectList.GetNext(objectPos);
  392. }
  393. }
  394. void C3dWorld::ResetAnimation(C3dCamera* pCamera)
  395. {
  396. // Reset the camera
  397. if(pCamera)
  398. pCamera->ResetAnimation();
  399. // Reset all lights attached to this world..
  400. C3dObject* pLight = NULL;
  401. // walk the list
  402. POSITION lightPos = m_LightList.GetHeadPosition();
  403. while (lightPos) {
  404. pLight = m_LightList.GetAt(lightPos);
  405. pLight->ResetAnimation();
  406. pLight = m_LightList.GetNext(lightPos);
  407. }
  408. // Reset all objects attached to this world..
  409. C3dObject* pObject = NULL;
  410. // walk the list
  411. POSITION objectPos = m_ObjectList.GetHeadPosition();
  412. while (objectPos) {
  413. pObject = m_ObjectList.GetAt(objectPos);
  414. pObject->ResetAnimation();
  415. pObject = m_ObjectList.GetNext(objectPos);
  416. }
  417. }
  418. void C3dWorld::DisplayWorld(HDC hDC, C3dCamera* pCamera, double dTime)
  419. {
  420. static double dLastTime = 0.0;
  421. // Setup our rendering context
  422. SetupRC();
  423. if(dTime != dLastTime)
  424. {
  425. Animate(pCamera, dTime);
  426. dLastTime = dTime;
  427. }
  428. // Render the 3dWorld scene
  429. RenderScene(pCamera);
  430. // Swap our scene to the front
  431. SwapBuffers(hDC);
  432. }
  433. void C3dWorld::SetupRC(void)
  434. {
  435. GLenum err; // Used for retrieving OpenGL errors
  436. static GLfloat factor = -1.0f;
  437. static GLfloat units  = -1.0f;
  438. // Set the background color
  439. glClearColor((GLclampf)m_BackgroundColor.m_fColor[0],
  440.  (GLclampf)m_BackgroundColor.m_fColor[1],
  441.  (GLclampf)m_BackgroundColor.m_fColor[2],
  442.  (GLclampf)m_BackgroundColor.m_fColor[3]);
  443. // If we have a palette, enable dithering of color before
  444. // writing to the color buffer
  445. if(the3dEngine.GetPalette())
  446. glEnable(GL_DITHER);
  447. // Enable color material
  448. glEnable(GL_COLOR_MATERIAL);
  449. if(m_bCullFaces)
  450. glEnable(GL_CULL_FACE);
  451. else
  452. glDisable(GL_CULL_FACE);
  453. // Set the rendering mode
  454. if(m_iRenderMode == RENDER_FLAT)
  455. {
  456. glShadeModel(GL_FLAT);
  457. glDisable(GL_POLYGON_OFFSET_LINE);
  458. }
  459. else if(m_iRenderMode == RENDER_SMOOTH)
  460. {
  461. glShadeModel(GL_SMOOTH);
  462. glDisable(GL_POLYGON_OFFSET_LINE);
  463. }
  464. else if(m_iRenderMode == RENDER_OUTLINE)
  465. {
  466. // glShadeModel(GL_SMOOTH);
  467. glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
  468. glEnable(GL_POLYGON_OFFSET_LINE); 
  469. glPolygonOffset(factor, units); 
  470. }
  471. // Tell OpenGL to draw into the BACK buffer.  When we are
  472. // finished, we will swap to the front.
  473. glDrawBuffer(GL_BACK);
  474. // Enable Pixel depth testing.
  475. glEnable(GL_DEPTH_TEST);
  476. glFrontFace(GL_CCW); // Counter clock-wise polygons face out
  477. // Enable lighting
  478. glEnable(GL_LIGHTING);
  479. // We want specular reflections to take the direction of our
  480. // cameras' position
  481. glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 1.0f);
  482. // Perform error checking routine
  483. #if(_DEBUG)
  484. do
  485. {
  486. err = glGetError();
  487. if (err != GL_NO_ERROR)
  488. TRACE("Error in C3dWorld::SetupRC:  %sn", gluErrorString(err));
  489. }while(err != GL_NO_ERROR);
  490. #endif
  491. }
  492. void C3dWorld::RenderScene(C3dCamera* pCamera)
  493. {
  494. GLenum err; // Used for retrieving OpenGL errors
  495. // Clear the buffers
  496. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  497. // Set the matrix mode to MODELVIEW and load
  498. // the identity matrix
  499. glMatrixMode(GL_MODELVIEW);
  500. glLoadIdentity();
  501. // Set our camera position and save its transformation matrix
  502. pCamera->PositionCamera();
  503. // Set our Fog parameters
  504. if(m_bFogEnable)
  505. m_Fog.SetAttributes();
  506. else
  507. glDisable(GL_FOG);
  508. // Initialize all lights attached to this world
  509. InitializeLights(pCamera);
  510. if(m_pBkgndTexture)
  511. // Display the background image
  512. DisplayBackgroundImage(pCamera);
  513. // Initialize the names stack
  514. glInitNames();
  515. glPushName(0);
  516. if(m_bDisplayAxis)
  517. // Display the World X, Y, Z Origin Axis
  518. m_pAxis->Display( 3.0f, // Axis length
  519.   0.1f, // Axis diameter
  520.   0.5f, // Arrow length
  521.   0.25f,// Arrow diameter
  522.   10, // Number of slices around dia.
  523.   2, // Number of Stacks about length
  524.   NULL, // X-Axis Color (Use Defaults..)
  525.   NULL, // Y-Axis Color
  526.   NULL, // Z-Axis Color
  527.   TRUE);// Display as Solid
  528. if(m_bDisplayGrid)
  529. m_pGrid->Display(this, pCamera);
  530. if(!m_PointList.IsEmpty())
  531. // Display all points in our list..
  532. m_PointList.Display(this, pCamera, TRUE);
  533. // Perform error checking routine
  534. #if(_DEBUG)
  535. do
  536. {
  537. err = glGetError();
  538. if (err != GL_NO_ERROR)
  539. TRACE("Error in C3dWorld::RenderScene:  %sn", gluErrorString(err));
  540. }while(err != GL_NO_ERROR);
  541. #endif
  542. // Display all objects attached to this world..
  543. C3dObject* pObject = NULL;
  544. // walk the list
  545. POSITION objectPos = m_ObjectList.GetHeadPosition();
  546. while (objectPos)
  547. {
  548. pObject = m_ObjectList.GetAt(objectPos);
  549. pObject->DisplayObject(this, pCamera);
  550. // Perform error checking routine
  551. #if(_DEBUG)
  552. do
  553. {
  554. err = glGetError();
  555. if (err != GL_NO_ERROR)
  556. TRACE("Error in C3dWorld::RenderScene displaying object %s:  %sn", pObject->m_szName, gluErrorString(err));
  557. }while(err != GL_NO_ERROR);
  558. #endif
  559. pObject = m_ObjectList.GetNext(objectPos);
  560. }
  561. glFlush(); // Flush any reminant commands from the buffer..
  562. }
  563. void C3dWorld::InitializeLights(C3dCamera* pCamera)
  564. {
  565. GLenum err; // Used for retrieving OpenGL errors
  566. // Initialize all lights attached to this world..
  567. C3dObject* pLightObj = NULL;
  568. C3dObjectLight* pLight = NULL;
  569. GLenum lightNum = GL_LIGHT0;
  570. // walk the list
  571. POSITION lightPos = m_LightList.GetHeadPosition();
  572. while (lightPos)
  573. {
  574. pLightObj = m_LightList.GetAt(lightPos);
  575. pLight = (C3dObjectLight*)pLightObj;
  576. pLight->EnableLight(lightNum, this, pCamera);
  577. // Perform error checking routine
  578. #if(_DEBUG)
  579. do
  580. {
  581. err = glGetError();
  582. if (err != GL_NO_ERROR)
  583. TRACE("Error in C3dWorld::RenderScene displaying light %s:  %sn", pLight->m_szName, gluErrorString(err));
  584. }while(err != GL_NO_ERROR);
  585. #endif
  586. ++lightNum;
  587. pLightObj = m_LightList.GetNext(lightPos);
  588. }
  589. }
  590. void C3dWorld::DisplayBackgroundImage(C3dCamera* pCamera)
  591. {
  592. GLfloat x, y, z;
  593. // Ensure that we have a background image
  594. if(!m_pBkgndTexture)
  595. return;
  596. // Do we blend the background image
  597. if(m_pBkgndTexture->m_iEnvmode == GL_BLEND)
  598. {
  599. glEnable(GL_BLEND);
  600. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  601. }
  602. else
  603. // Disable blend function
  604. glDisable(GL_BLEND);
  605. if(m_pBkgndTexture->m_pBits)
  606. // Apply the Dib Image to our shape..
  607. m_pBkgndTexture->SetTexture();
  608. // Calculate the size of the image
  609. z = pCamera->m_fFar;
  610. y = tan(Radiansf(pCamera->m_fFovY/2))*z;
  611. x = y*((GLfloat)pCamera->m_iScreenWidth/(GLfloat)pCamera->m_iScreenHeight);
  612. // Save our current modelview matrix and load the identity matrix
  613. glPushMatrix();
  614. glLoadIdentity();
  615. // Map the texture coordinates onto the background 'Plane'
  616. glBegin(GL_POLYGON);
  617. glNormal3d(0.0, 0.0, 1.0);
  618. glTexCoord2d(1, 0.0);
  619. glVertex3d(x, -y, -z);
  620. glTexCoord2d(1, 1);
  621. glVertex3d(x, y, -z);
  622. glTexCoord2d(0.0, 1);
  623. glVertex3d(-x, y, -z);
  624. glTexCoord2d(0.0, 0.0);
  625. glVertex3d(-x, -y, -z);
  626. glEnd();
  627. // Restore our Modelview matrix
  628. glPopMatrix();
  629. }
  630. // Process the selection, which is triggered by a right mouse
  631. // click at (xPos, yPos).
  632. #define BUFFER_LENGTH 64
  633. C3dObject* C3dWorld::ProcessSelection(C3dCamera* pCamera, int xPos, int yPos, BOOL bSelParent)
  634. {
  635. // Pointer to our selected object
  636. C3dObject* pSelectedObject = NULL;
  637. // Space for selection buffer
  638. GLuint selectBuff[BUFFER_LENGTH];
  639. // Hit counter and viewport storeage
  640. GLint hits, viewport[4];
  641. // Setup selection buffer
  642. glSelectBuffer(BUFFER_LENGTH, selectBuff);
  643. // Get the viewport
  644. glGetIntegerv(GL_VIEWPORT, viewport);
  645. // Fix the yPos value.  MS Windows origin 0,0 is upper left
  646. // while OpenGL windows origin 0,0 is lower left...
  647. yPos = viewport[3]-yPos;
  648. // Switch to projection and save the matrix
  649. glMatrixMode(GL_PROJECTION);
  650. glPushMatrix();
  651. // Change render mode
  652. glRenderMode(GL_SELECT);
  653. // Establish new clipping volume to be unit cube around
  654. // mouse cursor point (xPos, yPos) and extending two pixels
  655. // in the vertical and horzontal direction
  656. glLoadIdentity();
  657. gluPickMatrix(xPos, yPos, 0.1f, 0.1f, viewport);
  658. // Apply perspective or orthographic matrix 
  659. if(pCamera->m_bPerspective) {
  660. // Perspective transformations.
  661. gluPerspective(pCamera->m_fFovY, pCamera->m_fAspect, pCamera->m_fNear, pCamera->m_fFar);
  662. }
  663. else {
  664. // Orthographic transformations.
  665. glOrtho(pCamera->m_fLeft, pCamera->m_fRight, pCamera->m_fBottom, pCamera->m_fTop, -pCamera->m_fOrigin[Z], pCamera->m_fFar);
  666. }
  667. // Draw the scene
  668. RenderScene(pCamera);
  669. // Collect the hits
  670. hits = glRenderMode(GL_RENDER);
  671. // Restore the projection matrix
  672. glMatrixMode(GL_PROJECTION);
  673. glPopMatrix();
  674. // Go back to modelview for normal rendering
  675. glMatrixMode(GL_MODELVIEW);
  676. // If a hit occured, display the info.
  677. if(hits > 0)
  678. {
  679. // The hit record consists of the number of names in the
  680. // name stack at the time of the event; followed by the
  681. // minimum and maximum depth values of all vertices that
  682. // hit since the previous event; followed by the name stack
  683. // contents, bottom name first.  Get the 'top' name.
  684. int iHitNum = (hits*4)-1;
  685. // Check to see if the user selected a light object
  686. C3dObject* pLight = NULL;
  687. // walk the list
  688. POSITION lightPos = m_LightList.GetHeadPosition();
  689. while (lightPos)
  690. {
  691. pLight = m_LightList.GetAt(lightPos);
  692. pSelectedObject = pLight->IsName(selectBuff[iHitNum], bSelParent);
  693. if(pSelectedObject)
  694. break;
  695. pLight = m_LightList.GetNext(lightPos);
  696. }
  697. // User did not select a light; must be an object..
  698. if(!pSelectedObject)
  699. {
  700. // Display all objects attached to this world..
  701. C3dObject* pObject = NULL;
  702. // walk the list
  703. POSITION objectPos = m_ObjectList.GetHeadPosition();
  704. while (objectPos)
  705. {
  706. pObject = m_ObjectList.GetAt(objectPos);
  707. pSelectedObject = pObject->IsName(selectBuff[iHitNum], bSelParent);
  708. if(pSelectedObject)
  709. break;
  710. pObject = m_ObjectList.GetNext(objectPos);
  711. }
  712. }
  713. }
  714. return pSelectedObject;
  715. }
  716. void C3dWorld::AddObject(C3dObject* pObject, C3dObject* pParent)
  717. {
  718. ASSERT(pObject);
  719. // Light objects require special processing.  We add them to the 
  720. // Light list for Enabling and the Object list for display.
  721. if(pObject->m_iType == LIGHT_OBJECT)
  722. m_LightList.Append(pObject);
  723. if(pParent)
  724. {
  725. pParent->AddChildObject(pObject);
  726. pObject->m_pParent = pParent;
  727. }
  728. else
  729. {
  730. m_ObjectList.Append(pObject);
  731. pObject->m_pParent = NULL;
  732. }
  733. }
  734. BOOL C3dWorld::CreateDefColors(C3dColorList* pColorList)
  735. {
  736. // Create our Default Colors
  737. C3dColor* pColor = NULL; // Pointer to a color
  738. pColor = C3dColor::Create("Black", // Name
  739.   0.0f, // Red component
  740.   0.0f, // Green component
  741.   0.0f, // Blue component
  742.   1.0f); // Alpha component
  743. pColorList->Append(pColor);
  744. pColor = C3dColor::Create("White", // Name
  745.   1.0f, // Red component
  746.   1.0f, // Green component
  747.   1.0f, // Blue component
  748.   1.0f); // Alpha component
  749. pColorList->Append(pColor);
  750. pColor = C3dColor::Create("DarkGray", // Name
  751.   0.5f, // Red component
  752.   0.5f, // Green component
  753.   0.5f, // Blue component
  754.   1.0f); // Alpha component
  755. pColorList->Append(pColor);
  756. pColor = C3dColor::Create("LightGray", // Name
  757.   0.7f, // Red component
  758.   0.7f, // Green component
  759.   0.7f, // Blue component
  760.   1.0f); // Alpha component
  761. pColorList->Append(pColor);
  762. return TRUE;
  763. }
  764. BOOL C3dWorld::CreateDefMaterials(C3dMaterialList* pMatlList)
  765. {
  766. // Create our Default Materials
  767. C3dMaterial* pMatl = NULL; // Pointer to our materials
  768. pMatl = C3dMaterial::Create("<None>", // Name
  769. 0.0f, 0.0f, 0.0f, 1.0f, // Ambient Color
  770. 0.0f, 0.0f, 0.0f, 1.0f, // Diffuse Color
  771. 0.0f, 0.0f, 0.0f, 1.0f, // Specular Color
  772. 0.0f, 0.0f, 0.0f, 0.0f, // Emmissive Color
  773. 0.0f, // Specular Power
  774. 0.0f, // Index of Refraction
  775. 0.0f, // Reflection
  776. 0.0f); // Translucency
  777. pMatlList->Append(pMatl);
  778. pMatl = C3dMaterial::Create("Shiny", // Name
  779. 0.1f, 0.1f, 0.1f, 1.0f, // Ambient Color
  780. 1.0f, 1.0f, 1.0f, 1.0f, // Diffuse Color
  781. 1.0f, 1.0f, 1.0f, 1.0f, // Specular Color
  782. 0.0f, 0.0f, 0.0f, 0.0f, // Emmissive Color
  783. 20.0f, // Specular Power
  784. 0.0f, // Index of Refraction
  785. 0.0f, // Reflection
  786. 0.0f); // Translucency
  787. pMatlList->Append(pMatl);
  788. pMatl = C3dMaterial::Create("Matte", // Name
  789. 0.1f, 0.1f, 0.1f, 1.0f, // Ambient Color
  790. 0.2f, 0.2f, 0.2f, 1.0f, // Diffuse Color
  791. 0.2f, 0.2f, 0.2f, 1.0f, // Specular Color
  792. 0.0f, 0.0f, 0.0f, 0.0f, // Emmissive Color
  793. 10.0f, // Specular Power
  794. 0.0f, // Index of Refraction
  795. 0.0f, // Reflection
  796. 0.0f); // Translucency
  797. pMatlList->Append(pMatl);
  798. pMatl = C3dMaterial::Create("Metallic", // Name
  799. 0.1f, 0.1f, 0.1f, 1.0f, // Ambient Color
  800. 0.5f, 0.5f, 0.5f, 1.0f, // Diffuse Color
  801. 0.6f, 0.6f, 0.6f, 1.0f, // Specular Color
  802. 0.0f, 0.0f, 0.0f, 0.0f, // Emmissive Color
  803. 6.0f, // Specular Power
  804. 0.0f, // Index of Refraction
  805. 0.25f, // Reflection
  806. 0.0f); // Translucency
  807. pMatlList->Append(pMatl);
  808. pMatl = C3dMaterial::Create("Reflective", // Name
  809. 0.1f, 0.1f, 0.1f, 1.0f, // Ambient Color
  810. 0.5f, 0.5f, 0.5f, 1.0f, // Diffuse Color
  811. 0.5f, 0.5f, 0.5f, 1.0f, // Specular Color
  812. 0.0f, 0.0f, 0.0f, 0.0f, // Emmissive Color
  813. 7.0f, // Specular Power
  814. 0.0f, // Index of Refraction
  815. 0.5f, // Reflection
  816. 0.0f); // Translucency
  817. pMatlList->Append(pMatl);
  818. pMatl = C3dMaterial::Create("Mirror", // Name
  819. 0.0f, 0.0f, 0.0f, 1.0f, // Ambient Color
  820. 0.0f, 0.0f, 0.0f, 1.0f, // Diffuse Color
  821. 1.0f, 1.0f, 1.0f, 1.0f, // Specular Color
  822. 0.0f, 0.0f, 0.0f, 0.0f, // Emmissive Color
  823. 20.0f, // Specular Power
  824. 0.0f, // Index of Refraction
  825. 1.0f, // Reflection
  826. 0.0f); // Translucency
  827. pMatlList->Append(pMatl);
  828. pMatl = C3dMaterial::Create("Glass", // Name
  829. 0.0f, 0.0f, 0.0f, 1.0f, // Ambient Color
  830. 0.0f, 0.0f, 0.0f, 1.0f, // Diffuse Color
  831. 0.2f, 0.2f, 0.2f, 1.0f, // Specular Color
  832. 0.0f, 0.0f, 0.0f, 0.0f, // Emmissive Color
  833. 6.0f, // Specular Power
  834. 1.56f, // Index of Refraction
  835. 0.15f, // Reflection
  836. 1.0f); // Translucency
  837. pMatlList->Append(pMatl);
  838. return TRUE;
  839. }
  840. void C3dWorld::AddMaterial(C3dMaterial* pMaterial)
  841. {
  842. ASSERT(pMaterial);
  843. m_MaterialList.Append(pMaterial);
  844. }
  845. int C3dWorld::LoadBitMapImage(CImageList* pList)
  846. {
  847. CBitmap bitmap;
  848. // If the image index has been stored in this object,
  849. // return the index.
  850. if(m_iBMImage > -1)
  851. return m_iBMImage;
  852. // If the image index for this object type has been
  853. // created, store the index for this object and
  854. // return the index.
  855. if(iWorldBMImage > -1) {
  856. m_iBMImage = iWorldBMImage;
  857. return m_iBMImage;
  858. }
  859. // The image index for this object type has not been
  860. // loaded and the object image index has not been
  861. // stored.
  862. //
  863. // Load the bitmap for the non-selected world
  864. bitmap.LoadBitmap(IDB_WORLD);
  865. m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  866. bitmap.DeleteObject();
  867. // Load the bitmap for the selected world
  868. bitmap.LoadBitmap(IDB_WORLD_SELECTED);
  869. pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  870. bitmap.DeleteObject();
  871. iWorldBMImage = m_iBMImage;
  872. return m_iBMImage;
  873. }
  874. BOOL C3dWorld::EditAttributes()
  875. {
  876. char szName[80];
  877. sprintf(szName, "Edit Attributes of world '%s'", m_szName);
  878. m_pBackgroundPropSheet = new C3dBackgroundPropSheet(szName, NULL, this);
  879. m_pBackgroundPropSheet->DoModal();
  880. return 0;
  881. }
  882. void C3dWorld::DeleteObject(C3dObject* pObject)
  883. {
  884. if(!pObject)
  885. return; // Nothing to delete..
  886. // Remove the object from the Light list?
  887. if(pObject->m_iType == LIGHT_OBJECT)
  888. m_LightList.Delete(pObject);
  889. // Remove the object from the Object list
  890. if(!pObject->m_pParent)
  891. m_ObjectList.Delete(pObject);
  892. else
  893. // Let parent delete child
  894. pObject->m_pParent->m_ObjectList.Delete(pObject);
  895. pObject = NULL;
  896. }
  897. BOOL C3dWorld::AddTexture(LPSTR szFileName)
  898. {
  899. if(m_pBkgndTexture)
  900. // If we already have a texture, delete it
  901. DeleteTexture();
  902. // Create a TextureMap of the appropriate type
  903. CTexture::CreateTexture(szFileName, the3dEngine.m_hPalette, &m_pBkgndTexture);
  904. if(m_pBkgndTexture)
  905. {
  906. // Is the TextureMap an CTextureAviMovie?
  907. if( m_pBkgndTexture->IsKindOf(RUNTIME_CLASS(CTextureAviMovie)) )
  908. {
  909. // Create an AVI animation and add to the list
  910. CAnimAVI* pAnim = new CAnimAVI;
  911. ASSERT(pAnim);
  912. m_AnimList.Append(pAnim);
  913. // Save the CTextureAviMovie pointer
  914. pAnim->m_pAviMovie = (CTextureAviMovie*)m_pBkgndTexture;
  915. }
  916. return TRUE;
  917. }
  918. else
  919. return FALSE;
  920. }
  921. void C3dWorld::DeleteTexture()
  922. {
  923. if(m_pBkgndTexture)
  924. {
  925. if( m_pBkgndTexture->IsKindOf(RUNTIME_CLASS(CTextureAviMovie)) )
  926. {
  927. // TextureMap is of class type CTextureAviMovie, so find the animation
  928. // procedure in the list, remove from list and delete it..
  929. CAnimation* pAnimation = m_AnimList.Find(SZ_ANIMATE_AVI);
  930. if(pAnimation)
  931. {
  932. m_AnimList.Remove(pAnimation);
  933. delete pAnimation;
  934. }
  935. }
  936. // Now that we have removed any associated object members,
  937. // delete the texturemap
  938. delete m_pBkgndTexture;
  939. m_pBkgndTexture = NULL;
  940. }
  941. }
  942. void C3dWorld::RebuildAllObjects()
  943. {
  944. // This function forces all objects to rebuild their display
  945. // lists.
  946. // Display all objects attached to this world..
  947. C3dObject* pObject = NULL;
  948. // walk the list
  949. POSITION objectPos = m_ObjectList.GetHeadPosition();
  950. while (objectPos)
  951. {
  952. pObject = m_ObjectList.GetAt(objectPos);
  953. pObject->Rebuild();
  954. pObject = m_ObjectList.GetNext(objectPos);
  955. }
  956. }