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

OpenGL

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // 3dObjectLight.cpp : implementation file
  3. //
  4. // glOOP (OpenGL Object Oriented Programming library)
  5. // Copyright (c) Craig Fahrnbach 1997, 1998
  6. //
  7. // OpenGL is a registered trademark of Silicon Graphics
  8. //
  9. //
  10. // This program is provided for educational and personal use only and
  11. // is provided without guarantee or warrantee expressed or implied.
  12. //
  13. // Commercial use is strickly prohibited without written permission
  14. // from ImageWare Development.
  15. //
  16. // This program is -not- in the public domain.
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "glOOP.h"
  21. #include "3dObjectDialog.h"
  22. #include <math.h>
  23. #ifdef _DEBUG
  24. #define new DEBUG_NEW
  25. #undef THIS_FILE
  26. static char THIS_FILE[] = __FILE__;
  27. #endif
  28. //////////////////////////////////////////////////////////////////
  29. // C3dObjectLight local variables
  30. // To allow the user to modify certain characteristics of the light object,
  31. // such as moving the lights' direction and the spot lights direction points
  32. // we have defined the following local global variables to 'mimic' these
  33. // object features.
  34. static C3dPoint SpotRadius1;
  35. static C3dPoint SpotRadius2;
  36. static C3dPoint SpotRadius3;
  37. static C3dPoint SpotRadius4;
  38. static C3dPoint LightDirection;
  39. static GLfloat fSelectedRotation[3]; // User selected light rotation
  40. //////////////////////////////////////////////////////////////////
  41. // C3dObjectLight
  42. IMPLEMENT_SERIAL(C3dObjectLight, C3dObject, 0)
  43. /////////////////////////////////////////////////////////////////////////////
  44. // C3dObjectLight construction
  45. C3dObjectLight::C3dObjectLight()
  46. {
  47. // Set the member attributes to default values..
  48.   m_iType = LIGHT_OBJECT;
  49.     m_szName.Format("Light %u", nLights++);
  50. m_iLightType = LIGHT_POINT;
  51. m_iDisplayAs = DISPLAY_SPHERE;
  52. // If the w component of the position is 0.0, the light
  53. // is treated as a directional source. Diffuse and specular
  54. // lighting calculations take the lights direction, but
  55. // not its actual position, into account, and attenuation
  56. // is disabled. Otherwise, diffuse and specular lighting
  57. // calculations are based on the actual location of the
  58. // light in eye coordinates, and attenuation is enabled. 
  59. // Note:
  60. // The W component is initialized at creation and is 
  61. // NEVER modified again (this defines the type of light)
  62. m_fOrigin[0] = 5.0f; // X coordinate
  63. m_fOrigin[1] = -5.0f; // Y coordinate
  64. m_fOrigin[2] = 5.0f; // X coordinate
  65. m_fOrigin[3] = 1.0f; // W coordinate
  66. SetDirection(0.0f, 0.0f, 6.5f); // Light points along the Z-Axis
  67. SetRotation(225.0f, -35.0f, 0.0f); // Rotate so that Z-Axis looks at world origin
  68. m_ColorAmbient.SetColor4f(0.2f, 0.2f, 0.2f, 1.0f);
  69. m_ColorDiffuse.SetColor4f(0.7f, 0.7f, 0.7f, 1.0f);
  70. m_ColorSpecular.SetColor4f(0.9f, 0.9f, 0.9f, 1.0f);
  71. m_fRadius  = 0.5f;
  72. m_fLength  = 2.0f;
  73. m_fSpotAngle = 180.0f;
  74. m_fSpecHighlight = 0.0f;
  75. m_fConstantAttenuation = 1.0f;
  76. m_fLinearAttenuation = 0.0f;
  77. m_fQuadraticAttenuation = 0.0f;
  78. // Create a quadratic object so that we can display
  79. // the light source in the world
  80. m_pQuad = gluNewQuadric();
  81. }
  82. /////////////////////////////////////////////////////////////////////////////
  83. // C3dObjectLight Destructor
  84. C3dObjectLight::~C3dObjectLight()
  85. {
  86. gluDeleteQuadric(m_pQuad);
  87. }
  88. /////////////////////////////////////////////////////////////////////////////
  89. // C3dObjectLight Methods or virtual function implimentation
  90. void C3dObjectLight::AddAttributePage(C3dWorld* pWorld, LPVOID pSht)
  91. {
  92. C3dObjectPropSheet* pSheet = (C3dObjectPropSheet*)pSht;
  93. ASSERT(pSheet);
  94. // Add the Directional Light attributes page to the property sheet
  95. pSheet->AddPage(&pSheet->m_LightPage);
  96. // Save the address of this light in the page
  97. pSheet->m_LightPage.m_pLight = this;
  98. pSheet->m_LightPage.m_pWorld = pWorld;
  99. // Add the Directional Light attributes page to the property sheet
  100. pSheet->AddPage(&pSheet->m_LightColorPage);
  101. // Save the address of this light in the page
  102. pSheet->m_LightColorPage.m_pLight = this;
  103. pSheet->m_LightColorPage.m_pWorld = pWorld;
  104. }
  105. void C3dObjectLight::GetShapeBounds(C3dBoundingBox* pBox)
  106. {
  107. // Calculate the bounds of the shape
  108. if(m_iDisplayAs == DISPLAY_NONE)
  109. {
  110. VecClear3f(pBox->m_fMax);
  111. VecClear3f(pBox->m_fMin);
  112. }
  113. else if(m_iDisplayAs == DISPLAY_SPHERE)
  114. {
  115. pBox->m_fMax[X] = m_fRadius;
  116. pBox->m_fMax[Y] = m_fRadius;
  117. pBox->m_fMax[Z] = m_fRadius;
  118. pBox->m_fMin[X] = -m_fRadius;
  119. pBox->m_fMin[Y] = -m_fRadius;
  120. pBox->m_fMin[Z] = -m_fRadius;
  121. }
  122. else if(m_iDisplayAs == DISPLAY_CYLINDER)
  123. {
  124. pBox->m_fMax[X] = m_fLength/2;
  125. pBox->m_fMax[Y] = m_fRadius;
  126. pBox->m_fMax[Z] = m_fRadius;
  127. pBox->m_fMin[X] = -m_fLength/2;
  128. pBox->m_fMin[Y] = -m_fRadius;
  129. pBox->m_fMin[Z] = -m_fRadius;
  130. }
  131. else if(m_iDisplayAs == DISPLAY_RECTANGLE)
  132. {
  133. pBox->m_fMax[X] = m_fRadius;
  134. pBox->m_fMax[Y] = m_fRadius;
  135. pBox->m_fMax[Z] = 0.0f;
  136. pBox->m_fMin[X] = -m_fRadius;
  137. pBox->m_fMin[Y] = -m_fRadius;
  138. pBox->m_fMin[Z] = 0.0f;
  139. }
  140. }
  141. int C3dObjectLight::LoadBitMapImage(CImageList* pList)
  142. {
  143. CBitmap bitmap;
  144. // If the image index has been stored in this object,
  145. // return the index.
  146. if(m_iBMImage > -1)
  147. return m_iBMImage;
  148. // If the image index for this object type has been
  149. // created, store the index for this object and
  150. // return the index.
  151. if( iObjectLightBMImage > -1) {
  152. m_iBMImage = iObjectLightBMImage;
  153. return m_iBMImage;
  154. }
  155. // The image index for this object type has not been
  156. // loaded and the object image index has not been
  157. // stored.
  158. //
  159. // Load the bitmap for the non-selected light
  160. bitmap.LoadBitmap(IDB_OBJECT_LIGHT);
  161. m_iBMImage = pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  162. bitmap.DeleteObject();
  163. // Load the bitmap for the non-selected light
  164. bitmap.LoadBitmap(IDB_OBJECT_LIGHT_SELECTED);
  165. pList->Add(&bitmap, (COLORREF)0xFFFFFF);
  166. bitmap.DeleteObject();
  167. iObjectLightBMImage = m_iBMImage;
  168. return m_iBMImage;
  169. }
  170. void C3dObjectLight::Serialize(CArchive& ar, int iVersion)
  171. {
  172. CString szBuffer;
  173. if (ar.IsStoring())
  174. {
  175. // Save the Light Class header...
  176. szBuffer.Format("n%sC3dObjectLight {n", szIndent);
  177. ar.WriteString(szBuffer);
  178. // Save the this objects' specific data...
  179. szBuffer.Format("%stRadius        < %f >n", szIndent, m_fRadius);
  180. ar.WriteString(szBuffer);
  181. szBuffer.Format("%stDirection     < %f %f %f >n", szIndent, m_fDirection[X], m_fDirection[Y], m_fDirection[Z]);
  182. ar.WriteString(szBuffer);
  183. szBuffer.Format("%stLight Type    < %i >n", szIndent, m_iLightType);
  184. ar.WriteString(szBuffer);
  185. szBuffer.Format("%stDisplay As    < %i >n", szIndent, m_iDisplayAs);
  186. ar.WriteString(szBuffer);
  187. szBuffer.Format("%stAmbientColor  < %f %f %f %f > //RGBAn", szIndent, m_ColorAmbient.m_fColor[0], m_ColorAmbient.m_fColor[1], m_ColorAmbient.m_fColor[2], m_ColorAmbient.m_fColor[3]);
  188. ar.WriteString(szBuffer);
  189. szBuffer.Format("%stDiffuseColor  < %f %f %f %f > //RGBAn", szIndent, m_ColorDiffuse.m_fColor[0], m_ColorDiffuse.m_fColor[1], m_ColorDiffuse.m_fColor[2], m_ColorDiffuse.m_fColor[3]);
  190. ar.WriteString(szBuffer);
  191. szBuffer.Format("%stSpecularColor < %f %f %f %f > //RGBAn", szIndent, m_ColorSpecular.m_fColor[0], m_ColorSpecular.m_fColor[1], m_ColorSpecular.m_fColor[2], m_ColorSpecular.m_fColor[3]);
  192. ar.WriteString(szBuffer);
  193. szBuffer.Format("%stSpot Exponent < %f >n", szIndent, m_fSpecHighlight);
  194. ar.WriteString(szBuffer);
  195. szBuffer.Format("%stCutoff Angle  < %f >n", szIndent, m_fSpotAngle);
  196. ar.WriteString(szBuffer);
  197. szBuffer.Format("%stConstant Attenuation  < %f >n", szIndent, m_fConstantAttenuation);
  198. ar.WriteString(szBuffer);
  199. szBuffer.Format("%stLinear Attenuation    < %f >n", szIndent, m_fLinearAttenuation);
  200. ar.WriteString(szBuffer);
  201. szBuffer.Format("%stQuadratic Atenuation  < %f >n", szIndent, m_fQuadraticAttenuation);
  202. ar.WriteString(szBuffer);
  203. // Save the base class object data...
  204. C3dObject::Serialize(ar, iVersion);
  205. szBuffer.Format("%s}n", szIndent); // end of object def
  206. ar.WriteString(szBuffer);
  207. }
  208. else
  209. {
  210. if(iVersion < 102)
  211. // Read the base class object data...
  212. C3dObject::Serialize(ar, iVersion);
  213. // Read the derived class data..
  214. ar.ReadString(szBuffer);
  215. szBuffer.TrimLeft(); // Remove leading white spaces
  216. sscanf(szBuffer, "Radius        < %f >n", &m_fRadius);
  217. ar.ReadString(szBuffer);
  218. szBuffer.TrimLeft();
  219. sscanf(szBuffer, "Direction     < %f %f %f >n", &m_fDirection[X], &m_fDirection[Y], &m_fDirection[Z]);
  220. if(iVersion > 103)
  221. {
  222. // Set equal to our default direction vector
  223. SetDirection(0.0f, 0.0f, 6.5f); // Light points along the Z-Axis
  224. SetRotation(225.0f, -35.0f, 0.0f); // Rotate so that Z-Axis looks at world origin
  225. // Read new light type and display parameters
  226. ar.ReadString(szBuffer);
  227. szBuffer.TrimLeft();
  228. sscanf(szBuffer, "Light Type    < %i >n", &m_iLightType);
  229. ar.ReadString(szBuffer);
  230. szBuffer.TrimLeft();
  231. sscanf(szBuffer, "Display As    < %i >n", &m_iDisplayAs);
  232. }
  233. ar.ReadString(szBuffer);
  234. szBuffer.TrimLeft();
  235. sscanf(szBuffer, "AmbientColor  < %f %f %f %f >n", &m_ColorAmbient.m_fColor[0], &m_ColorAmbient.m_fColor[1], &m_ColorAmbient.m_fColor[2], &m_ColorAmbient.m_fColor[3]);
  236. ar.ReadString(szBuffer);
  237. szBuffer.TrimLeft();
  238. sscanf(szBuffer, "DiffuseColor  < %f %f %f %f >n", &m_ColorDiffuse.m_fColor[0], &m_ColorDiffuse.m_fColor[1], &m_ColorDiffuse.m_fColor[2], &m_ColorDiffuse.m_fColor[3]);
  239. ar.ReadString(szBuffer);
  240. szBuffer.TrimLeft();
  241. sscanf(szBuffer, "SpecularColor < %f %f %f %f >n", &m_ColorSpecular.m_fColor[0], &m_ColorSpecular.m_fColor[1], &m_ColorSpecular.m_fColor[2], &m_ColorSpecular.m_fColor[3]);
  242. ar.ReadString(szBuffer);
  243. szBuffer.TrimLeft();
  244. sscanf(szBuffer, "Spot Exponent < %f >n", &m_fSpecHighlight);
  245. ar.ReadString(szBuffer);
  246. szBuffer.TrimLeft();
  247. sscanf(szBuffer, "Cutoff Angle  < %f >n", &m_fSpotAngle);
  248. ar.ReadString(szBuffer);
  249. szBuffer.TrimLeft();
  250. sscanf(szBuffer, "Constant Attenuation  < %f >n", &m_fConstantAttenuation);
  251. ar.ReadString(szBuffer);
  252. szBuffer.TrimLeft();
  253. sscanf(szBuffer, "Linear Attenuation    < %f >n", &m_fQuadraticAttenuation);
  254. ar.ReadString(szBuffer);
  255. szBuffer.TrimLeft();
  256. sscanf(szBuffer, "Quadratic Attenuation < %f >n", &m_fQuadraticAttenuation);
  257. if(iVersion < 102)
  258. // Read all child objects...
  259. LoadChildObjects(ar, iVersion);
  260. else
  261. // Read the base class object data...
  262. C3dObject::Serialize(ar, iVersion);
  263. }
  264. }
  265. void C3dObjectLight::Build(C3dWorld* pWorld, C3dCamera* pCamera)
  266. {
  267. if(m_iLightType == LIGHT_AMBIENT) {
  268. // Set the lights color component equal to the ambient component
  269. glColor4fv(m_ColorAmbient.m_fColor);
  270. // Copy this color to the default color
  271. m_Color.SetColor4fv(&m_ColorAmbient);
  272. }
  273. else {
  274. // Set the lights color component equal to the diffuse component
  275. glColor4fv(m_ColorDiffuse.m_fColor);
  276. m_Color.SetColor4fv(&m_ColorDiffuse);
  277. }
  278. // Compile and build the list
  279. glNewList(m_iDisplayLists, GL_COMPILE_AND_EXECUTE);
  280. // Disable lighting calculations..
  281. glDisable(GL_LIGHTING);
  282. if(m_iDisplayAs == DISPLAY_SPHERE)
  283. {
  284. gluSphere(m_pQuad,
  285.   m_fRadius, // radius
  286.   10, // slices
  287.   10); // stacks
  288. }
  289. if(m_iDisplayAs == DISPLAY_CYLINDER)
  290. {
  291. // Orient along the X-Axis, centered about the XY-Axis
  292. glTranslatef(0.0f, 1.0f, 0.0f);
  293. glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
  294. gluCylinder(m_pQuad,
  295. m_fRadius, // Base Radius
  296. m_fRadius, // Top Radius
  297. m_fLength, // Length of the tube
  298. 10, // slices
  299. 10); // stacks
  300. // Put ends on our tube light
  301. // Translate to top of Cylinder
  302. glTranslated(0.0f, 0.0f, m_fLength);
  303. gluDisk(m_pQuad, 0.0f, m_fRadius, 10, 1);
  304. // Translate to back to bottom of Cylinder
  305. glTranslated(0.0f, 0.0f, -m_fLength);
  306. // Rotate 180 so that bottom is visible
  307. glRotated(180.0f, 1.0f, 0.0f, 0.0f);
  308. gluDisk(m_pQuad, 0.0f, m_fRadius, 10, 1);
  309. }
  310. if(m_iDisplayAs == DISPLAY_RECTANGLE)
  311. {
  312. // Place the Rectangle centered about the Z-Axis on the XY plane
  313. glBegin(GL_POLYGON); // CCW order...
  314. glVertex3f(-m_fRadius,  m_fRadius, 0.0f);
  315. glVertex3f( m_fRadius,  m_fRadius, 0.0f);
  316. glVertex3f( m_fRadius, -m_fRadius, 0.0f);
  317. glVertex3f(-m_fRadius, -m_fRadius, 0.0f);
  318. glEnd();
  319. }
  320. // Re-enable lighting calculations
  321. glEnable(GL_LIGHTING);
  322. glEndList();
  323. }
  324. void C3dObjectLight::DisplayPoints(C3dWorld* pWorld, C3dCamera* pCamera)
  325. {
  326. GLfloat fRadius = 0.12f;
  327. GLfloat fPointColor[4]   = { 0.2f, 0.9f, 0.2f, 1.0f };
  328. GLfloat fSelectedColor[4] = { 0.9f, 0.0f, 0.2f, 1.0f };
  329. GLfloat fLineColor[4]   = { 0.7f, 0.7f, 0.5f, 1.0f };
  330. // Disable lighting calculations
  331. glDisable(GL_LIGHTING);
  332. // Set new line width
  333. glLineWidth(2.0f);
  334. if(m_iLightType != LIGHT_AMBIENT && m_fOrigin[W] != 0.0f)
  335. {
  336. // Light is positional and not an ambient light, so display
  337. // our focal point.
  338. // Set our light object user selectable point value
  339. LightDirection.SetOrigin(m_fDirection[X], m_fDirection[Y], m_fDirection[Z]);
  340. if(pWorld->m_pSelectedPnt == &LightDirection)
  341. LightDirection.Display(fRadius, fSelectedColor, TRUE);
  342. else
  343. LightDirection.Display(fRadius, fPointColor, TRUE);
  344. // Draw a line from the center of the light to the end point of the 
  345. // lights' focal direction
  346. glColor4fv(fLineColor);
  347. glBegin(GL_LINES);
  348. glVertex3f(0.0f, 0.0f, 0.0f);
  349. glVertex3fv(m_fDirection);
  350. glEnd();
  351. }
  352. if(m_iLightType == LIGHT_SPOT)
  353. {
  354. float fSpotRadius;
  355. fSpotRadius = m_fDirection[Z]*(sinf(Radiansf(m_fSpotAngle)));
  356. // Calculate four (4) spot light radial points around the focal point
  357. // of the light and set our user selectable point values
  358. SpotRadius1.SetOrigin(fSpotRadius, 0.0f, 0.0f);
  359. VecAddf(SpotRadius1.m_fOrigin, m_fDirection, SpotRadius1.m_fOrigin);
  360. SpotRadius2.SetOrigin(0.0f, fSpotRadius, 0.0f);
  361. VecAddf(SpotRadius2.m_fOrigin, m_fDirection, SpotRadius2.m_fOrigin);
  362. SpotRadius3.SetOrigin(-fSpotRadius, 0.0f, 0.0f);
  363. VecAddf(SpotRadius3.m_fOrigin, m_fDirection, SpotRadius3.m_fOrigin);
  364. SpotRadius4.SetOrigin(0.0f, -fSpotRadius, 0.0f);
  365. VecAddf(SpotRadius4.m_fOrigin, m_fDirection, SpotRadius4.m_fOrigin);
  366. if(pWorld->m_pSelectedPnt == &SpotRadius1)
  367. SpotRadius1.Display(fRadius, fSelectedColor, TRUE);
  368. else
  369. SpotRadius1.Display(fRadius, fPointColor, TRUE);
  370. if(pWorld->m_pSelectedPnt == &SpotRadius2)
  371. SpotRadius2.Display(fRadius, fSelectedColor, TRUE);
  372. else
  373. SpotRadius2.Display(fRadius, fPointColor, TRUE);
  374. if(pWorld->m_pSelectedPnt == &SpotRadius3)
  375. SpotRadius3.Display(fRadius, fSelectedColor, TRUE);
  376. else
  377. SpotRadius3.Display(fRadius, fPointColor, TRUE);
  378. if(pWorld->m_pSelectedPnt == &SpotRadius4)
  379. SpotRadius4.Display(fRadius, fSelectedColor, TRUE);
  380. else
  381. SpotRadius4.Display(fRadius, fPointColor, TRUE);
  382. // Draw a line from the center of the light around the radius of the 
  383. // end point of the lights' focal direction
  384. glColor4fv(fLineColor);
  385. glBegin(GL_LINES);
  386. glVertex3fv(SpotRadius1.m_fOrigin);
  387. glVertex3f(0.0f, 0.0f, 0.0f);
  388. glVertex3fv(SpotRadius2.m_fOrigin);
  389. glVertex3f(0.0f, 0.0f, 0.0f);
  390. glVertex3fv(SpotRadius3.m_fOrigin);
  391. glVertex3f(0.0f, 0.0f, 0.0f);
  392. glVertex3fv(SpotRadius4.m_fOrigin);
  393. glVertex3f(0.0f, 0.0f, 0.0f);
  394. glEnd();
  395. // Draw a wireframe circle around the spot lights focal point
  396. float slices = 18.0f;
  397. for(float i=0.0f; i<=360-slices; i+=slices)
  398. {
  399. glBegin(GL_LINES);
  400. glVertex3f(fSpotRadius*cosf(Radiansf(i)),
  401.    fSpotRadius*sinf(Radiansf(i)),
  402.    m_fDirection[Z]);
  403. glVertex3f(fSpotRadius*cosf(Radiansf(i+slices)),
  404.    fSpotRadius*sinf(Radiansf(i+slices)),
  405.    m_fDirection[Z]);
  406. glEnd();
  407. }
  408. }
  409. // Enable lighting calculations and reset the line width
  410. glEnable(GL_LIGHTING);
  411. glLineWidth(1.0f);
  412. }
  413. C3dPoint* C3dObjectLight::FindPoint(C3dCamera* pCamera, float x, float y, float z)
  414. {
  415. Matx4x4 ObjXformMatrix;
  416. // Get the objects transformation matrix.  We will use this to
  417. // transform each point to world coordinates.
  418. GetTransformMatrix(ObjXformMatrix);
  419. // Check to see if the coordinates are our light's 'Direction' end point
  420. if(LightDirection.IsPoint(pCamera, ObjXformMatrix, x, y, z))
  421. return &LightDirection;
  422. if(m_iLightType == LIGHT_SPOT)
  423. {
  424. // Check to see if the coordinates are our one of our spot lights'
  425. // radial points
  426. if(SpotRadius1.IsPoint(pCamera, ObjXformMatrix, x, y, z))
  427. return &SpotRadius1;
  428. if(SpotRadius2.IsPoint(pCamera, ObjXformMatrix, x, y, z))
  429. return &SpotRadius2;
  430. if(SpotRadius3.IsPoint(pCamera, ObjXformMatrix, x, y, z))
  431. return &SpotRadius3;
  432. if(SpotRadius4.IsPoint(pCamera, ObjXformMatrix, x, y, z))
  433. return &SpotRadius4;
  434. }
  435. // No user selectable light points found
  436. return NULL;
  437. }
  438. void C3dObjectLight::GetObjPointOrigin(C3dPoint* pPoint, float* x, float* y, float* z)
  439. {
  440. if(!pPoint)
  441. return; // No point given
  442. if(pPoint == &LightDirection)
  443. {
  444. // Get the xyz coordinates of our lights direction vector and 
  445. // save the lights current rotation values.  (We will use these values
  446. // in the SetObjPointOrigin() function below.)
  447. GetDirection(x, y, z);
  448. VecCopy3f(m_fRotation, fSelectedRotation);
  449. return;
  450. }
  451. // Return the xyz coordinates of the lights spot radius
  452. if(pPoint == &SpotRadius1)
  453. {
  454. *x = m_fDirection[X]+SpotRadius1.m_fOrigin[X];
  455. *y = m_fDirection[Y];
  456. *z = m_fDirection[Z];
  457. return;
  458. }
  459. if(pPoint == &SpotRadius2)
  460. {
  461. *x = m_fDirection[X];
  462. *y = m_fDirection[Y]+SpotRadius2.m_fOrigin[Y];
  463. *z = m_fDirection[Z];
  464. return;
  465. }
  466. if(pPoint == &SpotRadius3)
  467. {
  468. *x = m_fDirection[X]+SpotRadius3.m_fOrigin[X];
  469. *y = m_fDirection[Y];
  470. *z = m_fDirection[Z];
  471. return;
  472. }
  473. if(pPoint == &SpotRadius4)
  474. {
  475. *x = m_fDirection[X];
  476. *y = m_fDirection[Y]+SpotRadius4.m_fOrigin[Y];
  477. *z = m_fDirection[Z];
  478. return;
  479. }
  480. // The point is not a selected point of this light
  481. *x = *y = *z = 0.0f;
  482. }
  483. void C3dObjectLight::SetObjPointOrigin(C3dPoint* pPoint, float x, float y, float z)
  484. {
  485. if(!pPoint)
  486. return; // No point given
  487. if(pPoint == &LightDirection)
  488. {
  489. // User has moved the lights direction vector.  We want the light vector
  490. // looking along the z-axis, so we must rotate about the xy-axis to 
  491. // maintain this relationship.  
  492. Matx4x4 InvZRotateMatrix;
  493. VECTORF LightRotation;
  494. float rx, ry;
  495. VecClear3f(LightRotation);
  496. // Calculate the rotation value of the light based on its
  497. // new direction vector
  498. rx = atan(y/m_fDirection[Z]);
  499. ry = atan(x/m_fDirection[Z]);
  500. if(rx)
  501. LightRotation[X] = Degreesf(rx);
  502. if(ry)
  503. LightRotation[Y] = Degreesf(ry);
  504. // Since our light may have a z-axis rotation, we must calcualte
  505. // the inverse z-axis transformation matrix, then multiply our
  506. // xy rotation values by the inverse matrix to ensure that our light
  507. // is rotated properly.
  508. Rotate3D(Z, -m_fRotation[Z], InvZRotateMatrix);
  509. VecTransformf(LightRotation, LightRotation, InvZRotateMatrix);
  510. // Now that we have the oriented xy rotations, add/subtract from
  511. // our saved values.
  512. m_fRotation[X] = fSelectedRotation[X] - LightRotation[X];
  513. m_fRotation[Y] = fSelectedRotation[Y] + LightRotation[Y];
  514. // We allow the user to move the lights focal point, (direction vector)
  515. // along the z-axis, so set its coordinate as (0, 0, z)
  516. m_fDirection[Z] = z;
  517. }
  518. // Has the user selected a spot light radial point?
  519. if(pPoint == &SpotRadius1)
  520. {
  521. // Set the spot light radial point coordinate and calculate
  522. // a new spot angle.
  523. SpotRadius1.m_fOrigin[X] = x;
  524. m_fSpotAngle = Degreesf(sin(x/m_fDirection[Z]));
  525. }
  526. if(pPoint == &SpotRadius2)
  527. {
  528. SpotRadius2.m_fOrigin[Y] = y;
  529. m_fSpotAngle = Degreesf(sin(y/m_fDirection[Z]));
  530. }
  531. if(pPoint == &SpotRadius3)
  532. {
  533. SpotRadius3.m_fOrigin[X] = x;
  534. m_fSpotAngle = Degreesf(sin(-x/m_fDirection[Z]));
  535. }
  536. if(pPoint == &SpotRadius4)
  537. {
  538. SpotRadius4.m_fOrigin[Y] = y;
  539. m_fSpotAngle = Degreesf(sin(-y/m_fDirection[Z]));
  540. }
  541. }
  542. /////////////////////////////////////////////////////////////////////////////
  543. // C3dObjectLight methods
  544. void C3dObjectLight::EnableLight(GLenum lightNum, C3dWorld* pWorld, C3dCamera* pCamera)
  545. {
  546. GLfloat colorBlack[4] = {0.0f, 0.0f, 0.0f, 0.0f};
  547. Matx4x4 LightTransformMatrix;
  548. VECTORF fLightOrigin; // The center of our light
  549. VECTORF fLightDirection; // The direction our light is pointing to
  550. VECTORF fLightDirVec; // The direction vector of our light
  551. // To ensure that our 3d surfaces are lighted properly, we must enable all
  552. // lights in our scene before we display any surface. Lights should be enabled
  553. // AFTER positioning of our 'camera' to ensure that the light is properly 
  554. // positioned.
  555. GetTransformMatrix(LightTransformMatrix);
  556. if(m_pParent)
  557. {
  558. // Since we allow lights to be child objects, we must calculate its'
  559. // position and direction vector in world coordinates.
  560. // Initialize our vectors
  561. VecClear4f(fLightOrigin); // Set to (0,0,0,0) or our World origin.
  562. // Calculate the light's position in World coordinates.
  563. VecTransformf(fLightOrigin, fLightOrigin, LightTransformMatrix);
  564. fLightOrigin[W] = m_fOrigin[W]; // copy the 'W' or light 'type' parameter
  565. }
  566. else
  567. VecCopy4f(m_fOrigin, fLightOrigin);
  568. // Calculate the lights' direction vector. Get the direction of the light
  569. // and multiply it by the lights Inverse Rotation transformation matrix.
  570. // Subtract this from the light's World coordinalte position then normalize.
  571. VecTransformf(m_fDirection, fLightDirection, LightTransformMatrix);
  572. VecSubf(fLightDirection, fLightOrigin, fLightDirVec);
  573. VecNormalizef(fLightDirVec);
  574. // Set the Lights Parameters and Enable...
  575. glLightfv(lightNum, GL_AMBIENT, m_ColorAmbient.m_fColor);
  576. if(m_iLightType == LIGHT_AMBIENT)
  577. {
  578. // Ambient light has no Diffuse or Specular color
  579. glLightfv(lightNum, GL_DIFFUSE, colorBlack);
  580. glLightfv(lightNum, GL_SPECULAR, colorBlack);
  581. }
  582. else
  583. {
  584. glLightfv(lightNum, GL_DIFFUSE, m_ColorDiffuse.m_fColor);
  585. glLightfv(lightNum, GL_SPECULAR, m_ColorSpecular.m_fColor);
  586. }
  587. glLightfv(lightNum, GL_POSITION, fLightOrigin);
  588. glLightfv(lightNum, GL_SPOT_DIRECTION, fLightDirVec);
  589. glLightf(lightNum, GL_SPOT_CUTOFF, m_fSpotAngle); // in Degrees
  590. glLightf(lightNum, GL_SPOT_EXPONENT, m_fSpecHighlight);
  591. glLightf(lightNum, GL_CONSTANT_ATTENUATION, m_fConstantAttenuation);
  592. glLightf(lightNum, GL_LINEAR_ATTENUATION, m_fLinearAttenuation);
  593. glLightf(lightNum, GL_QUADRATIC_ATTENUATION, m_fQuadraticAttenuation);
  594. glEnable(lightNum);
  595. }
  596. void C3dObjectLight::GetDirection(GLfloat *x, GLfloat *y, GLfloat *z)
  597. {
  598. // Get the light direction
  599. *x = m_fDirection[X];
  600. *y = m_fDirection[Y];
  601. *z = m_fDirection[Z];
  602. }
  603. void C3dObjectLight::GetAttenuation(GLfloat *k, GLfloat *l, GLfloat *q)
  604. {
  605. // Get the lights attenuation variables
  606. *k = m_fConstantAttenuation;
  607. *l = m_fLinearAttenuation;
  608. *q = m_fQuadraticAttenuation;
  609. }
  610. void C3dObjectLight::GetSpecularPwr(GLfloat *pwr)
  611. {
  612. // Get the lights specular power or spot exponent
  613. *pwr = m_fSpecHighlight;
  614. }
  615. void C3dObjectLight::GetSpotAngle(GLfloat *angle)
  616. {
  617. // Get the lights cutoff angle (degrees)
  618. *angle = m_fSpotAngle;
  619. }
  620. void C3dObjectLight::GetRadius(GLfloat *radius)
  621. {
  622. // Get the lights radius or size
  623. *radius = m_fRadius;
  624. }
  625. void C3dObjectLight::SetDirection(GLfloat x, GLfloat y, GLfloat z)
  626. {
  627. // Set the light objects direction to the supplied
  628. // values.
  629. m_fDirection[X] = x;
  630. m_fDirection[Y] = y;
  631. m_fDirection[Z] = z;
  632. }
  633. void C3dObjectLight::SetAttenuation(GLfloat k, GLfloat l, GLfloat q)
  634. {
  635. // Set the lights attenuation variables
  636. m_fConstantAttenuation = k;
  637. m_fLinearAttenuation = l;
  638. m_fQuadraticAttenuation = q;
  639. }
  640. void C3dObjectLight::SetSpecularPwr(GLfloat pwr)
  641. {
  642. // Set the lights specular power or spot exponent
  643. m_fSpecHighlight = pwr;
  644. }
  645. void C3dObjectLight::SetSpotAngle(GLfloat angle)
  646. {
  647. // Set the lights cutoff angle (degrees)
  648. m_fSpotAngle = angle;
  649. }
  650. void C3dObjectLight::SetRadius(GLfloat radius)
  651. {
  652. // Set the lights radius or size
  653. m_fRadius = radius;
  654. }