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

OpenGL

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // 3dObjectCloud.cpp : implementation file
  3. //
  4. // glOOP (OpenGL Object Oriented Programming library)
  5. // Copyright (c) Craig m_pFahrnbach 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. // Adapted from source code, with permission, by: Paul E. Martz
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "glOOP.h"
  22. #include "3dObjectDialog.h"
  23. #ifdef _DEBUG
  24. #define new DEBUG_NEW
  25. #undef THIS_FILE
  26. static char THIS_FILE[] = __FILE__;
  27. #endif
  28. //////////////////////////////////////////////////////////////////
  29. // C3dObjectCloud
  30. IMPLEMENT_DYNAMIC(C3dObjectCloud, C3dObject)
  31. /////////////////////////////////////////////////////////////////////////////
  32. // C3dShape construction
  33. C3dObjectCloud::C3dObjectCloud()
  34. {
  35. // Set the attributes to dem_pFault values..
  36.   m_iType = SHAPE_OBJECT;
  37.    m_szName.Format("Cloud %u", nCloudObjects++);
  38. m_iSize = 8; // 2^8, or 256 x 256 texture map
  39. m_iTile = 1; // Only one tile
  40. m_iTextureWrap = 3; // Wrap texture three times
  41. m_iHeightSeed = 0;
  42. m_iCloudTextureMap = 0;
  43. m_iCloudImageMap = 0;
  44. m_fWidth = 50.0f;
  45. m_fDepth = 50.0f;
  46. m_fBumpHeight =  0.7f;
  47. m_fOpacity =  1.0f;
  48. m_fDensity =  0.2f;
  49. m_pFa = NULL;
  50. m_Color.SetColor4f(0.0f, 0.0f, 0.0f, 1.0f);
  51. m_ColorHighlight.SetColor4f(1.0f, 1.0f, 1.0f, 1.0f);
  52. // Create our C3dPointArray object
  53. m_pPointArray = new C3dPointArray;
  54. ASSERT(m_pPointArray);
  55. m_pPointArray->Create(5); // Create an array of points for our vertices
  56. // Initialize our cubes vertices (points)
  57. InitVertices();
  58. }
  59. void C3dObjectCloud::CopyParameters(C3dObjectCloud* pSrc, C3dObjectCloud* pDest)
  60. {
  61. // Since this function is used by the preview window, we want
  62. // the image to fit 'mostly' within the window, so we will 
  63. // use our default settings.  We also want to conserve memory
  64. // so we will use the default array size setting.
  65. // pDest->m_iSize = pSrc->m_iSize;
  66. // pDest->m_iTile = pSrc->m_iTile;
  67. // pDest->m_fDepth = pSrc->m_fDepth;
  68. // pDest->m_fWidth = pSrc->m_fWidth;
  69. pDest->m_iHeightSeed = pSrc->m_iHeightSeed;
  70. pDest->m_iTextureWrap = pSrc->m_iTextureWrap;
  71. pDest->m_fBumpHeight = pSrc->m_fBumpHeight;
  72. pDest->m_fDensity = pSrc->m_fDensity;
  73. pDest->m_fOpacity = pSrc->m_fOpacity;
  74. pDest->m_Color.SetColor4fv(&pSrc->m_Color);
  75. pDest->m_ColorHighlight.SetColor4fv(&pSrc->m_ColorHighlight);
  76. }
  77. /////////////////////////////////////////////////////////////////////////////
  78. // C3DWorld Destructor
  79. C3dObjectCloud::~C3dObjectCloud()
  80. {
  81. // Delete our point array
  82. if(m_pPointArray)
  83. delete m_pPointArray;
  84. // Delete the Terrain image 
  85. if(m_iCloudTextureMap)
  86. {
  87. glDeleteLists(m_iCloudImageMap, 1);
  88. m_iCloudImageMap = 0;
  89. }
  90. // Delete the Terrain Texturemap
  91. if(m_iCloudTextureMap)
  92. {
  93. glDeleteLists(m_iCloudTextureMap, 1);
  94. m_iCloudTextureMap = 0;
  95. }
  96. // Delete the fractural array
  97. if(m_pFa)
  98. FreeFractArray();
  99. }
  100. /////////////////////////////////////////////////////////////////////////////
  101. // C3dObjectCloud Methods or virtual function implimentation
  102. void C3dObjectCloud::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
  103. {
  104. C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
  105. ASSERT(pSheet);
  106. // Add the page to the property sheet
  107. pSheet->AddPage(&pSheet->m_CloudPage);
  108. // Save the address of this object in the page
  109. pSheet->m_CloudPage.m_pObject = this;
  110. // Add the page to the property sheet
  111. pSheet->AddPage(&pSheet->m_CloudColorPage);
  112. // Save the address of this object in the page
  113. pSheet->m_CloudColorPage.m_pObject = this;
  114. pSheet->m_CloudColorPage.m_pWorld = pWorld;
  115. }
  116. int C3dObjectCloud::LoadBitMapImage(CImageList* pList)
  117. {
  118. CBitmap bitmap;
  119. // If the image index has been stored in this object,
  120. // return the index.
  121. if(m_iBMImage > -1)
  122. return m_iBMImage;
  123. // If the image index for this object type has been
  124. // created, store the index for this object and
  125. // return the index.
  126. if( iObjectCloudBMImage > -1) {
  127. m_iBMImage = iObjectCloudBMImage;
  128. return m_iBMImage;
  129. }
  130. // The image index for this object type has not been
  131. // loaded and the object image index has not been
  132. // stored.
  133. //
  134. // Load the bitmap for the non-selected light
  135. bitmap.LoadBitmap(IDB_OBJECT_CLOUD);
  136. m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  137. bitmap.DeleteObject();
  138. // Load the bitmap for the non-selected light
  139. bitmap.LoadBitmap(IDB_OBJECT_CLOUD_SELECTED);
  140. pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  141. bitmap.DeleteObject();
  142. iObjectCloudBMImage = m_iBMImage;
  143. return m_iBMImage;
  144. }
  145. void C3dObjectCloud::GetShapeBounds(C3dBoundingBox* pBox)
  146. {
  147. if(m_pPointArray)
  148. m_pPointArray->GetMinMax(pBox);
  149. // We need to calculate the overall size of the object based
  150. // on the number of times we have tiled the basic shape
  151. pBox->m_fMax[X] *= m_iTile;
  152. pBox->m_fMax[Y] *= m_iTile;
  153. pBox->m_fMin[X] *= m_iTile;
  154. pBox->m_fMin[Y] *= m_iTile;
  155. }
  156. void C3dObjectCloud::Serialize(CArchive& ar, int iVersion)
  157. {
  158. CString szBuffer;
  159. if (ar.IsStoring())
  160. {
  161. // Save the Object Class header...
  162. szBuffer.Format("n%sC3dObjectCloud {n", szIndent);
  163. ar.WriteString(szBuffer);
  164. // Save the this objects' specific data...
  165. szBuffer.Format("%stDepth         < %f >n", szIndent, m_fDepth);
  166. ar.WriteString(szBuffer);
  167. szBuffer.Format("%stWidth         < %f >n", szIndent, m_fWidth);
  168. ar.WriteString(szBuffer);
  169. szBuffer.Format("%stBumpHeight    < %f >n", szIndent, m_fBumpHeight);
  170. ar.WriteString(szBuffer);
  171. szBuffer.Format("%stDensity       < %f >n", szIndent, m_fDensity);
  172. ar.WriteString(szBuffer);
  173. szBuffer.Format("%stOpacity       < %f >n", szIndent, m_fOpacity);
  174. ar.WriteString(szBuffer);
  175. szBuffer.Format("%stHeightSeed    < %d >n", szIndent, m_iHeightSeed);
  176. ar.WriteString(szBuffer);
  177. szBuffer.Format("%stSize          < %d >n", szIndent, m_iSize);
  178. ar.WriteString(szBuffer);
  179. szBuffer.Format("%stTextureWrap   < %d >n", szIndent, m_iTextureWrap);
  180. ar.WriteString(szBuffer);
  181. szBuffer.Format("%stTile          < %d >n", szIndent, m_iTile);
  182. ar.WriteString(szBuffer);
  183. szBuffer.Format("%stHighlightColor < %f %f %f %f > // RGBAn", szIndent, m_ColorHighlight.m_fColor[0], m_ColorHighlight.m_fColor[1], m_ColorHighlight.m_fColor[2], m_ColorHighlight.m_fColor[3]);
  184. ar.WriteString(szBuffer);
  185. szBuffer.Format("%stNum Points    < %d >n", szIndent, m_pPointArray->m_iNumPoints);
  186. ar.WriteString(szBuffer);
  187. for(int i=0; i<m_pPointArray->m_iNumPoints; i++)
  188. {
  189. szBuffer.Format("%stt        < %f, %f, %f >n", szIndent, m_pPointArray->m_pPoints[i].m_fOrigin[0],
  190. m_pPointArray->m_pPoints[i].m_fOrigin[1],
  191. m_pPointArray->m_pPoints[i].m_fOrigin[2]);
  192. ar.WriteString(szBuffer);
  193. }
  194. // Save the base class object data...
  195. C3dObject::Serialize(ar, iVersion);
  196. szBuffer.Format("%s}n", szIndent); // end of object def
  197. ar.WriteString(szBuffer);
  198. }
  199. else
  200. {
  201. // Read the derived class data..
  202. ar.ReadString(szBuffer);
  203. szBuffer.TrimLeft(); // Remove leading white spaces
  204. sscanf(szBuffer, "Depth         < %f >n", &m_fDepth);
  205. ar.ReadString(szBuffer);
  206. szBuffer.TrimLeft();
  207. sscanf(szBuffer, "Width         < %f >n", &m_fWidth);
  208. ar.ReadString(szBuffer);
  209. szBuffer.TrimLeft();
  210. sscanf(szBuffer, "BumpHeight    < %f >n", &m_fBumpHeight);
  211. ar.ReadString(szBuffer);
  212. szBuffer.TrimLeft();
  213. sscanf(szBuffer, "Density       < %f >n", &m_fDensity);
  214. ar.ReadString(szBuffer);
  215. szBuffer.TrimLeft();
  216. sscanf(szBuffer, "Opacity       < %f >n", &m_fOpacity);
  217. ar.ReadString(szBuffer);
  218. szBuffer.TrimLeft();
  219. sscanf(szBuffer, "HeightSeed    < %d >n", &m_iHeightSeed);
  220. ar.ReadString(szBuffer);
  221. szBuffer.TrimLeft();
  222. sscanf(szBuffer, "Size          < %d >n", &m_iSize);
  223. ar.ReadString(szBuffer);
  224. szBuffer.TrimLeft();
  225. sscanf(szBuffer, "TextureWrap   < %d >n", &m_iTextureWrap);
  226. ar.ReadString(szBuffer);
  227. szBuffer.TrimLeft();
  228. sscanf(szBuffer, "Tile          < %d >n", &m_iTile);
  229. ar.ReadString(szBuffer);
  230. szBuffer.TrimLeft();
  231. sscanf(szBuffer, "HighlightColor < %f %f %f %f >n", &m_ColorHighlight.m_fColor[0], &m_ColorHighlight.m_fColor[1], &m_ColorHighlight.m_fColor[2], &m_ColorHighlight.m_fColor[3]);
  232. ar.ReadString(szBuffer);
  233. szBuffer.TrimLeft();
  234. sscanf(szBuffer, "Num Points    < %d >n", &m_pPointArray->m_iNumPoints);
  235. // Read the shape vertice, or point data
  236. for(int i=0; i<m_pPointArray->m_iNumPoints; i++)
  237. {
  238. ar.ReadString(szBuffer);
  239. szBuffer.TrimLeft();
  240. sscanf(szBuffer, "< %f, %f, %f >n", &m_pPointArray->m_pPoints[i].m_fOrigin[X],
  241.  &m_pPointArray->m_pPoints[i].m_fOrigin[Y],
  242.  &m_pPointArray->m_pPoints[i]);
  243. }
  244. // Read the base class object data...
  245. C3dObject::Serialize(ar, iVersion);
  246. }
  247. }
  248. void C3dObjectCloud::DisplayPoints(C3dWorld* pWorld, C3dCamera* pCamera)
  249. {
  250. static BOOL bDisplayMsg = TRUE;
  251. if(m_iTile>1 && bDisplayMsg)
  252. {
  253. AfxMessageBox("To edit the Cloud object points, the 'Tile' membern"
  254.   "variable must be set to one.", MB_OK);
  255. // Display the message only once per session
  256. bDisplayMsg = FALSE;
  257. return;
  258. }
  259. if(m_iTile==1)
  260. {
  261. // Display all points in our object
  262. if(m_pPointArray)
  263. {
  264. if(m_pPointArray->m_pPoints)
  265. m_pPointArray->Display(pWorld, pCamera, this, 2.0f, FALSE);
  266. }
  267. }
  268. }
  269. void C3dObjectCloud::Build(C3dWorld* pWorld, C3dCamera* pCamera)
  270. {
  271. float x, y;
  272. int i, j;
  273. // This may take a while, so display an hour glass cursor
  274. CWaitCursor hourglass;
  275. // Render the cloudmap to create our texture image
  276. RenderCloudTextureMap(pWorld, pCamera);
  277. // Render the cloud image to create our display list image
  278. RenderCloudImageMap(pWorld, pCamera);
  279. // Compile and build the list
  280. glNewList(m_iDisplayLists, GL_COMPILE_AND_EXECUTE);
  281. // Center our tiled image about the objects' origin
  282. glPushMatrix();
  283. glTranslatef( (m_fWidth * (float)(m_iTile-1))/2.0f,
  284.   (m_fDepth * (float)(m_iTile-1))/2.0f,
  285.    0.0f);
  286. y = -m_fDepth * (float) (m_iTile-1);
  287. for (i=0; i<m_iTile; i++)
  288. {
  289. x = -m_fWidth * (float) (m_iTile-1);
  290. for (j=0; j<m_iTile; j++)
  291. {
  292. glPushMatrix();
  293. glTranslatef(x, y, 0.f);
  294. if(m_iCloudImageMap)
  295. glCallList(m_iCloudImageMap);
  296. glPopMatrix ();
  297. x += m_fWidth;
  298. }
  299. y += m_fDepth;
  300. }
  301. glPopMatrix();
  302. glEndList();
  303. // Restore the cursor to its' default
  304. hourglass.Restore();
  305. }
  306. /////////////////////////////////////////////////////////////////////////////
  307. // C3dObjectCloud Methods or Implementation
  308. void C3dObjectCloud::InitVertices()
  309. {
  310. /*
  311. Our cloud is mapped to four trainagles arranged to form a plane as
  312. defined by the five (5) vertices, or points below.
  313.           p3 *  ____________  * p0
  314.                /            /
  315.              /  p4 *      /
  316.            /            /
  317.     p2 * /------------/  * p1
  318. */
  319. C3dPoint* pPoint = m_pPointArray->m_pPoints;
  320. // Initialize our clouds plane vertice points p0-p3
  321. pPoint->m_fOrigin[X] = m_fWidth/2; 
  322. pPoint->m_fOrigin[Y] = m_fDepth/2;
  323. pPoint->m_fOrigin[Z] = 0.0f;
  324. pPoint++;
  325. pPoint->m_fOrigin[X] = m_fWidth/2;
  326. pPoint->m_fOrigin[Y] = -m_fDepth/2;
  327. pPoint->m_fOrigin[Z] = 0.0f;
  328. pPoint++;
  329. pPoint->m_fOrigin[X] = -m_fWidth/2;
  330. pPoint->m_fOrigin[Y] = -m_fDepth/2;
  331. pPoint->m_fOrigin[Z] = 0.0f;
  332. pPoint++;
  333. pPoint->m_fOrigin[X] = -m_fWidth/2;
  334. pPoint->m_fOrigin[Y] = m_fDepth/2;
  335. pPoint->m_fOrigin[Z] = 0.0f;
  336. pPoint++;
  337. pPoint->m_fOrigin[X] = 0.0f;
  338. pPoint->m_fOrigin[Y] = 0.0f;
  339. pPoint->m_fOrigin[Z] = 0.0f;
  340. }
  341. void C3dObjectCloud::RenderCloudImageMap(C3dWorld* pWorld, C3dCamera* pCamera)
  342. {
  343. /*
  344. Our cloud is mapped to four trainagles arranged to form a plane as
  345. defined by the five (5) vertices, or points below.
  346.           p3 *  ____________  * p0
  347.                /            /
  348.              /  p4 *      /
  349.            /            /
  350.     p2 * /------------/  * p1
  351. */
  352. float fTextureWrap = (GLfloat)m_iTextureWrap;
  353. float fTextureWrapCenter = fTextureWrap*.707f;
  354. static BOOL textureLinear = TRUE;
  355. if(!m_iCloudImageMap)
  356. // Create our cloud image map display list
  357. m_iCloudImageMap = glGenLists(1);// Create the DisplayList(s)
  358. // Compile and build the list
  359. glNewList(m_iCloudImageMap, GL_COMPILE);
  360. float pureWhite[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
  361. VECTORF Normal;
  362. // Enable blending and alpha test
  363. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  364. glEnable(GL_BLEND);
  365. glAlphaFunc(GL_GREATER, 0.0f);
  366. glEnable(GL_ALPHA_TEST);
  367. // Set the current color to white
  368. glColor4fv(pureWhite);
  369. // Goes a little m_pFaster but looks like crud:
  370. //glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
  371.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, (GLfloat)GL_MODULATE);
  372. glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, pureWhite);
  373. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  374. textureLinear ? (GLfloat) GL_LINEAR
  375. : (GLfloat) GL_NEAREST);
  376. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
  377. textureLinear ? (GLfloat) GL_LINEAR
  378. : (GLfloat) GL_NEAREST);
  379. glEnable (GL_TEXTURE_2D);
  380. // recall our cloud texture map
  381. glCallList (m_iCloudTextureMap);
  382. // Now that the environment is set, begin drawing the cloud
  383. // texture map onto our plane
  384. glBegin(GL_TRIANGLE_FAN);
  385. // Point p4: The center of our triangle fan
  386. CalNormalf(m_pPointArray->m_pPoints[4].m_fOrigin,
  387.    m_pPointArray->m_pPoints[1].m_fOrigin,
  388.    m_pPointArray->m_pPoints[2].m_fOrigin,
  389.    Normal);
  390. glNormal3fv(Normal);
  391. glTexCoord2f(fTextureWrapCenter, fTextureWrapCenter);
  392. glVertex3fv(m_pPointArray->m_pPoints[4].m_fOrigin);
  393. // Point p0
  394. CalNormalf(m_pPointArray->m_pPoints[0].m_fOrigin,
  395.    m_pPointArray->m_pPoints[1].m_fOrigin,
  396.    m_pPointArray->m_pPoints[3].m_fOrigin,
  397.    Normal);
  398. glNormal3fv(Normal);
  399. glTexCoord2f(fTextureWrap, fTextureWrap);
  400. glVertex3fv(m_pPointArray->m_pPoints[0].m_fOrigin);
  401. // Point p1
  402. CalNormalf(m_pPointArray->m_pPoints[1].m_fOrigin,
  403.    m_pPointArray->m_pPoints[2].m_fOrigin,
  404.    m_pPointArray->m_pPoints[0].m_fOrigin,
  405.    Normal);
  406. glNormal3fv(Normal);
  407. glTexCoord2f(fTextureWrap, 0.f);
  408. glVertex3fv(m_pPointArray->m_pPoints[1].m_fOrigin);
  409. // Point p2
  410. CalNormalf(m_pPointArray->m_pPoints[2].m_fOrigin,
  411.    m_pPointArray->m_pPoints[3].m_fOrigin,
  412.    m_pPointArray->m_pPoints[1].m_fOrigin,
  413.    Normal);
  414. glNormal3fv(Normal);
  415. glTexCoord2f(0.f, 0.f);
  416. glVertex3fv(m_pPointArray->m_pPoints[2].m_fOrigin);
  417. // Point p3
  418. CalNormalf(m_pPointArray->m_pPoints[3].m_fOrigin,
  419.    m_pPointArray->m_pPoints[0].m_fOrigin,
  420.    m_pPointArray->m_pPoints[2].m_fOrigin,
  421.    Normal);
  422. glNormal3fv(Normal);
  423. glTexCoord2f(0.f, fTextureWrap);
  424. glVertex3fv(m_pPointArray->m_pPoints[3].m_fOrigin);
  425. // Point p0
  426. CalNormalf(m_pPointArray->m_pPoints[0].m_fOrigin,
  427.    m_pPointArray->m_pPoints[1].m_fOrigin,
  428.    m_pPointArray->m_pPoints[3].m_fOrigin,
  429.    Normal);
  430. glNormal3fv(Normal);
  431. glTexCoord2f(fTextureWrap, fTextureWrap);
  432. glVertex3fv(m_pPointArray->m_pPoints[0].m_fOrigin);
  433. glEnd ();
  434. // Disable blending and alpha depth testing
  435. glDisable(GL_BLEND);
  436. glDisable(GL_ALPHA_TEST);
  437. glEndList();
  438. }
  439. BOOL C3dObjectCloud::RenderCloudTextureMap(C3dWorld* pWorld, C3dCamera* pCamera)
  440. {
  441. // Render the cloud texture map. If the cloud fract array
  442. // doesn't already exist, allocate it, tesselate it, and
  443. // create the texture map using SetSkyPixelColor(). Then create a 
  444. // display list with this texture map in the list.
  445. GLubyte *tmap;
  446.     int size = 1 << m_iSize;
  447. // Set the size our our cloud fractual array
  448. if(m_pFa)
  449. FreeFractArray();
  450. m_pFa = Alloc2DFractArray(size);
  451. if(!m_pFa)
  452. return (FALSE);
  453. FillFractualArray(size, 1.0f);
  454. tmap = (GLubyte *) malloc (size*size*4);
  455. if (tmap==NULL) return (FALSE);
  456. SetSkyPixelColor(size, tmap);
  457. if(!m_iCloudTextureMap)
  458. // Create our texture map display list
  459. m_iCloudTextureMap = glGenLists(1);// Create the DisplayList(s)
  460. glNewList (m_iCloudTextureMap, GL_COMPILE);
  461.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  462. glTexImage2D(GL_TEXTURE_2D, 0, // lod
  463.  4, // num components
  464.  size, size, // width, height
  465.  0, // border
  466.  GL_RGBA, // format
  467.  GL_UNSIGNED_BYTE, // type
  468.  tmap); // pointer to our bits 
  469. glEndList ();
  470. // Done with the texture map bits, so free them.
  471. free (tmap);
  472. return(TRUE); // ** Comment out this return and the remaining
  473. //    functions in Build() to see the 'raw' texture map.
  474. // Once we have the texture map, we simply draw a quad as
  475. // big as will fit in the window, with the cloud texture map
  476. // applied to it.
  477. glCallList (m_iCloudTextureMap);
  478. glMatrixMode (GL_PROJECTION);
  479.     glLoadIdentity ();
  480. if (pCamera->m_iScreenWidth > pCamera->m_iScreenHeight)
  481. glOrtho (-1.f, pCamera->m_fAspect*2.f-1.f,
  482. -1.f, 1.f, 1., -1.);
  483. else 
  484.   glOrtho (-1.f, 1.f,
  485. -1.f, 2.f/pCamera->m_fAspect-1.f, 1., -1.);
  486. glMatrixMode (GL_MODELVIEW);
  487.     glLoadIdentity ();
  488. glDisable (GL_DEPTH_TEST);
  489. glDisable (GL_FOG);
  490. glDisable (GL_LIGHTING);
  491. glDisable (GL_BLEND);
  492. glEnable (GL_TEXTURE_2D);
  493.     
  494. glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, 
  495. (GLfloat) GL_REPLACE);
  496. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
  497. (GLfloat) GL_NEAREST);
  498. glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
  499. (GLfloat) GL_NEAREST);
  500. glClear (GL_COLOR_BUFFER_BIT);
  501. glBegin (GL_QUADS); {
  502. glTexCoord2f (0.f, 0.f); glVertex2f (-1.f, -1.f);
  503. glTexCoord2f (1.f, 0.f); glVertex2f (1.f, -1.f);
  504. glTexCoord2f (1.f, 1.f); glVertex2f (1.f, 1.f);
  505. glTexCoord2f (0.f, 1.f); glVertex2f (-1.f, 1.f);
  506. } glEnd ();
  507. glFlush ();
  508. glPopAttrib ();
  509. return (TRUE);
  510. }
  511. void C3dObjectCloud::SetSkyPixelColor (int size, GLubyte *skyTex)
  512. {
  513. // Converts a 2D fract array into a nice blue and white
  514. // cloudy sky texture map. First, it finds the average height
  515. // value in the map. Then it clamps values to +/- SKY_LIMIT
  516. // around the average value. Values in the array are then
  517. // mapped from a medium blue to white. The resulting RGB 
  518. // values are stored in skyTex.
  519. //
  520. // Note that while the fract array is assumed to have dimension
  521. // (size+1)X(size+1), skyTex must have dimension sizeXsize.
  522. // This m_pFacilitates its being used as an OpenGL texture map.
  523. #define SKY_LIMIT 0.2f
  524.     int i, j;
  525.     const int subSize = size;
  526.     unsigned char *skyptr;
  527.     float shadeFactor;
  528.     float skyAv=0.f;
  529. float scaleR, scaleG, scaleB;
  530. // Calculate the scale of the RGB color components
  531. scaleR = (m_ColorHighlight.m_fColor[0]-m_Color.m_fColor[0])/.5f;
  532. scaleG = (m_ColorHighlight.m_fColor[1]-m_Color.m_fColor[1])/.5f;
  533. scaleB = (m_ColorHighlight.m_fColor[2]-m_Color.m_fColor[2])/.5f;
  534.     size++;
  535.     for (i=0; i<size*size; i++)
  536. skyAv += m_pFa[i];
  537. skyAv /= (float)(size*size);
  538.     skyptr = skyTex;
  539.     for (i=0; i<subSize; i++)
  540. {
  541. for (j=0; j<subSize; j++)
  542. {
  543. if (m_pFa[i*size+j] < (skyAv - SKY_LIMIT))
  544. shadeFactor = -SKY_LIMIT;
  545. else if (m_pFa[i*size+j] > (skyAv + SKY_LIMIT))
  546. shadeFactor = SKY_LIMIT;
  547. else
  548. shadeFactor = m_pFa[i*size+j] - skyAv;
  549. /* shadeFactor is now in range -SKY_LIMIT - SKY_LIMIT.
  550.    scale shadeFactor to range 0.0 - 0.5 */
  551. shadeFactor = ((shadeFactor + SKY_LIMIT) *
  552.    (.5f / (2.f * SKY_LIMIT)));
  553. // Set the pixels' color. (ranged from m_ColorHighlight color to m_Color)
  554. skyptr[0] = (GLubyte)((m_Color.m_fColor[0]+scaleR*shadeFactor)*255); /* red */
  555. skyptr[1] = (GLubyte)((m_Color.m_fColor[1]+scaleG*shadeFactor)*255); /* green */
  556. skyptr[2] = (GLubyte)((m_Color.m_fColor[2]+scaleB*shadeFactor)*255); /* blue */
  557. // Set the pixels' transparancy value
  558. if(shadeFactor < m_fDensity)
  559. skyptr[3] = 0x00;
  560. else if(shadeFactor < m_fDensity+.025f)
  561. skyptr[3] = (unsigned char)(0x55*m_fOpacity);
  562. else if(shadeFactor < m_fDensity+.075f)
  563. skyptr[3] = (unsigned char)(0xaa*m_fOpacity);
  564. else
  565. skyptr[3] = (unsigned char)(0xff*m_fOpacity);
  566. skyptr += 4;
  567. }
  568.     }
  569. }
  570. // randNum - Return a random floating point number such that
  571. // (min <= return-value <= max)
  572. // 32,767 values are possible for any given range.
  573. //
  574. float C3dObjectCloud::RandNum (float min, float max)
  575. {
  576. int r;
  577. float x;
  578. r = rand ();
  579. x = (float)(r & 0x7fff) /
  580. (float)0x7fff;
  581. return (x * (max - min) + min);
  582. // fractRand is a useful interm_pFace to randnum.
  583. //
  584. #define FractRand(v) RandNum (-v, v)
  585. // powerOf2 - Returns 1 if size is a power of 2. Returns 0 if size is
  586. // not a power of 2, or is zero.
  587. //
  588. int C3dObjectCloud::PowerOf2 (int size)
  589. {
  590. int i, bitcount = 0;
  591. // Note this code assumes that (sizeof(int)*8) will yield the
  592. // number of bits in an int. Should be portable to most
  593. // platforms.
  594. for (i=0; i<sizeof(int)*8; i++)
  595. if (size & (1<<i))
  596.     bitcount++;
  597. if (bitcount == 1)
  598. // One bit. Must be a power of 2.
  599. return (1);
  600.     else
  601. // either size==0, or size not a power of 2. Sorry, Charlie.
  602. return (0);
  603. }
  604. // AvgDiamondVals - Given the i,j location as the center of a diamond,
  605. // average the data values at the four corners of the diamond and
  606. // return it. "Stride" represents the distance from the diamond center
  607. // to a diamond corner.
  608. //
  609. float C3dObjectCloud::AvgDiamondVals (int i, int j, int stride,
  610.      int size, int subSize)
  611. {
  612.     /* In this diagram, our input stride is 1, the i,j location is
  613.        indicated by "X", and the four value we want to average are
  614.        "*"s:
  615.            .   *   .
  616.            *   X   *
  617.            .   *   .
  618.        */
  619. // In order to support tiled surm_pFaces which meet seamless at the
  620. // edges (that is, they "wrap"), We need to be careful how we
  621. // calculate averages when the i,j diamond center lies on an edge
  622. // of the array. The first four 'if' clauses handle these
  623. // cases. The final 'else' clause handles the general case (in
  624. // which i,j is not on an edge).
  625. if (i == 0)
  626. return ((float) (m_pFa[(i*size) + j-stride] +
  627.  m_pFa[(i*size) + j+stride] +
  628.  m_pFa[((subSize-stride)*size) + j] +
  629.  m_pFa[((i+stride)*size) + j]) * .25f);
  630. else if (i == size-1)
  631. return ((float) (m_pFa[(i*size) + j-stride] +
  632.  m_pFa[(i*size) + j+stride] +
  633.  m_pFa[((i-stride)*size) + j] +
  634.  m_pFa[((0+stride)*size) + j]) * .25f);
  635. else if (j == 0)
  636. return ((float) (m_pFa[((i-stride)*size) + j] +
  637.  m_pFa[((i+stride)*size) + j] +
  638.  m_pFa[(i*size) + j+stride] +
  639.  m_pFa[(i*size) + subSize-stride]) * .25f);
  640. else if (j == size-1)
  641. return ((float) (m_pFa[((i-stride)*size) + j] +
  642.  m_pFa[((i+stride)*size) + j] +
  643.  m_pFa[(i*size) + j-stride] +
  644.  m_pFa[(i*size) + 0+stride]) * .25f);
  645. else
  646. return ((float) (m_pFa[((i-stride)*size) + j] +
  647.  m_pFa[((i+stride)*size) + j] +
  648.  m_pFa[(i*size) + j-stride] +
  649.  m_pFa[(i*size) + j+stride]) * .25f);
  650. }
  651. // AvgSquareVals - Given the i,j location as the center of a square,
  652. // average the data values at the four corners of the square and return
  653. // it. "Stride" represents half the length of one side of the square.
  654. float C3dObjectCloud::AvgSquareVals (int i, int j, int stride, int size)
  655. {
  656.     /* In this diagram, our input stride is 1, the i,j location is
  657.        indicated by "*", and the four value we want to average are
  658.        "X"s:
  659.            X   .   X
  660.            .   *   .
  661.            X   .   X
  662.        */
  663.     return ((float) (m_pFa[((i-stride)*size) + j-stride] +
  664.      m_pFa[((i-stride)*size) + j+stride] +
  665.      m_pFa[((i+stride)*size) + j-stride] +
  666.      m_pFa[((i+stride)*size) + j+stride]) * .25f);
  667. }
  668. // FillFractualArray - Use the diamond-square algorithm to tessalate a
  669. // grid of float values into a fractal height map.
  670. //
  671. void C3dObjectCloud::FillFractualArray (int size, float heightScale)
  672. {
  673. int i, j;
  674. int stride;
  675. int oddline;
  676. int subSize;
  677. int seedValue;
  678. float ratio, scale;
  679. if (!PowerOf2(size) || (size==1))
  680. {
  681. // We can't tesselate the array if it is not a power of 2.
  682. #ifdef DEBUG
  683. printf ("Error: FillFractualArray: size %d is not a power of 2.n");
  684. #endif /* DEBUG */
  685. return;
  686.     }
  687. // subSize is the dimension of the array in terms of connected line
  688. // segments, while size is the dimension in terms of number of
  689. // vertices.
  690. subSize = size;
  691. size++;
  692. // Initialize random number generator
  693. if(m_iHeightSeed < 0)
  694. {
  695. // Seed the random-number generator with current time so that
  696. // the numbers will be different every time we run.
  697. seedValue = (unsigned)time( NULL );
  698. srand( seedValue );
  699. m_iHeightSeed = seedValue;
  700. }
  701. else
  702.     srand (m_iHeightSeed);
  703.     // Set up our roughness constants.
  704. // Random numbers are always generated in the range 0.0 to 1.0.
  705. // 'scale' is multiplied by the randum number.
  706. // 'ratio' is multiplied by 'scale' after each iteration
  707. // to effectively reduce the random number range.
  708. ratio = (float) pow ((double)2.0,(double)-m_fBumpHeight);
  709. scale = heightScale * ratio;
  710.     /* Seed the first four values. For example, in a 4x4 array, we
  711.        would initialize the data points indicated by '*':
  712.            *   .   .   .   *
  713.            .   .   .   .   .
  714.            .   .   .   .   .
  715.            .   .   .   .   .
  716.            *   .   .   .   *
  717.        In terms of the "diamond-square" algorithm, this gives us
  718.        "squares".
  719.        We want the four corners of the array to have the same
  720.        point. This will allow us to tile the arrays next to each other
  721.        such that they join seemlessly.
  722.    */
  723. stride = subSize / 2;
  724. m_pFa[(0*size)+0] = m_pFa[(subSize*size)+0] =
  725. m_pFa[(subSize*size)+subSize] =
  726. m_pFa[(0*size)+subSize] = 0.f;
  727. // Now we add ever-increasing detail based on the "diamond" seeded
  728. // values. We loop over stride, which gets cut in half at the
  729. // bottom of the loop. Since it's an int, eventually division by 2
  730. // will produce a zero result, terminating the loop.
  731. while (stride)
  732. {
  733. /* Take the existing "square" data and produce "diamond"
  734.    data. On the first pass through with a 4x4 matrix, the
  735.    existing data is shown as "X"s, and we need to generate the
  736.        "*" now:
  737.                X   .   .   .   X
  738.                .   .   .   .   .
  739.                .   .   *   .   .
  740.                .   .   .   .   .
  741.                X   .   .   .   X
  742.   It doesn't look like diamonds. What it actually is, for the
  743.       first pass, is the corners of four diamonds meeting at the
  744.       center of the array. */
  745. for (i=stride; i<subSize; i+=stride)
  746. {
  747. for (j=stride; j<subSize; j+=stride)
  748. {
  749. m_pFa[(i * size) + j] = scale * FractRand (.5f) +
  750. AvgSquareVals (i, j, stride, size);
  751. j += stride;
  752. }
  753. i += stride;
  754. }
  755. /* Take the existing "diamond" data and make it into
  756.        "squares". Back to our 4X4 example: The first time we
  757.        encounter this code, the existing values are represented by
  758.        "X"s, and the values we want to generate here are "*"s:
  759.                X   .   *   .   X
  760.                .   .   .   .   .
  761.                *   .   X   .   *
  762.                .   .   .   .   .
  763.                X   .   *   .   X
  764.        i and j represent our (x,y) position in the array. The
  765.        first value we want to generate is at (i=2,j=0), and we use
  766.        "oddline" and "stride" to increment j to the desired value.
  767.        */
  768. oddline = 0;
  769. for (i=0; i<subSize; i+=stride)
  770. {
  771.     oddline = (oddline == 0);
  772. for (j=0; j<subSize; j+=stride)
  773. {
  774. if ((oddline) && !j)
  775. j+=stride;
  776. // i and j are setup. Call avgDiamondVals with the
  777. // current position. It will return the average of the
  778. // surrounding diamond data points.
  779. m_pFa[(i * size) + j] = scale * FractRand (.5f) +
  780. AvgDiamondVals (i, j, stride, size, subSize);
  781. // To wrap edges seamlessly, copy edge values around
  782. // to other side of array.
  783. if (i==0)
  784. m_pFa[(subSize*size) + j] =
  785. m_pFa[(i * size) + j];
  786. if (j==0)
  787. m_pFa[(i*size) + subSize] =
  788. m_pFa[(i * size) + j];
  789. j+=stride;
  790. }
  791. }
  792. // reduce random number range.
  793. scale *= ratio;
  794. stride >>= 1;
  795.     }
  796. }
  797. float* C3dObjectCloud::Alloc2DFractArray(int size)
  798. {
  799. float* fp;
  800.     /* For a sizeXsize array, we need (size+1)X(size+1) space. For
  801.        example, a 2x2 mesh needs 3x3=9 data points: 
  802.            *   *   *
  803.            *   *   *
  804.            *   *   *
  805.        To account for this, increment 'size'. */
  806. size++;
  807. fp = (float*) malloc (sizeof(float) * size * size);
  808. if(!fp)
  809. {
  810. AfxMessageBox("Could not allocate cloud array points.", MB_OK);
  811. return NULL;
  812. }
  813. return fp;
  814. }
  815. void C3dObjectCloud::FreeFractArray()
  816. {
  817.     free(m_pFa);
  818. m_pFa = NULL;
  819. }