llcamera.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:19k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llcamera.cpp
  3.  * @brief Implementation of the LLCamera class.
  4.  *
  5.  * $LicenseInfo:firstyear=2000&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2000-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "linden_common.h"
  33. #include "llmath.h"
  34. #include "llcamera.h"
  35. // ---------------- Constructors and destructors ----------------
  36. LLCamera::LLCamera() :
  37. LLCoordFrame(),
  38. mView(DEFAULT_FIELD_OF_VIEW),
  39. mAspect(DEFAULT_ASPECT_RATIO),
  40. mViewHeightInPixels( -1 ), // invalid height
  41. mNearPlane(DEFAULT_NEAR_PLANE),
  42. mFarPlane(DEFAULT_FAR_PLANE),
  43. mFixedDistance(-1.f),
  44. mPlaneCount(6),
  45. mFrustumCornerDist(0.f)
  46. {
  47. calculateFrustumPlanes();
  48. LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) :
  49. LLCoordFrame(),
  50. mViewHeightInPixels(view_height_in_pixels),
  51. mFixedDistance(-1.f),
  52. mPlaneCount(6),
  53. mFrustumCornerDist(0.f)
  54. {
  55. mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
  56. mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
  57. if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE;
  58. mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE);
  59. setView(vertical_fov_rads);
  60. // ---------------- LLCamera::getFoo() member functions ----------------
  61. F32 LLCamera::getMinView() const 
  62. {
  63. // minimum vertical fov needs to be constrained in narrow windows.
  64. return mAspect > 1
  65. ? MIN_FIELD_OF_VIEW // wide views
  66. : MIN_FIELD_OF_VIEW * 1/mAspect; // clamps minimum width in narrow views
  67. }
  68. F32 LLCamera::getMaxView() const 
  69. {
  70. // maximum vertical fov needs to be constrained in wide windows.
  71. return mAspect > 1 
  72. ? MAX_FIELD_OF_VIEW / mAspect  // clamps maximum width in wide views
  73. : MAX_FIELD_OF_VIEW; // narrow views
  74. }
  75. // ---------------- LLCamera::setFoo() member functions ----------------
  76. void LLCamera::setUserClipPlane(LLPlane plane)
  77. {
  78. mPlaneCount = 7;
  79. mAgentPlanes[6].p = plane;
  80. mAgentPlanes[6].mask = calcPlaneMask(plane);
  81. }
  82. void LLCamera::disableUserClipPlane()
  83. {
  84. mPlaneCount = 6;
  85. }
  86. void LLCamera::setView(F32 vertical_fov_rads) 
  87. {
  88. mView = llclamp(vertical_fov_rads, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW);
  89. calculateFrustumPlanes();
  90. }
  91. void LLCamera::setViewHeightInPixels(S32 height)
  92. {
  93. mViewHeightInPixels = height;
  94. // Don't really need to do this, but update the pixel meter ratio with it.
  95. calculateFrustumPlanes();
  96. }
  97. void LLCamera::setAspect(F32 aspect_ratio) 
  98. {
  99. mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
  100. calculateFrustumPlanes();
  101. }
  102. void LLCamera::setNear(F32 near_plane) 
  103. {
  104. mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
  105. calculateFrustumPlanes();
  106. }
  107. void LLCamera::setFar(F32 far_plane) 
  108. {
  109. mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE);
  110. calculateFrustumPlanes();
  111. }
  112. // ---------------- read/write to buffer ---------------- 
  113. size_t LLCamera::writeFrustumToBuffer(char *buffer) const
  114. {
  115. memcpy(buffer, &mView, sizeof(F32)); /* Flawfinder: ignore */
  116. buffer += sizeof(F32);
  117. memcpy(buffer, &mAspect, sizeof(F32)); /* Flawfinder: ignore */
  118. buffer += sizeof(F32);
  119. memcpy(buffer, &mNearPlane, sizeof(F32)); /* Flawfinder: ignore */
  120. buffer += sizeof(F32);
  121. memcpy(buffer, &mFarPlane, sizeof(F32)); /* Flawfinder: ignore */
  122. return 4*sizeof(F32);
  123. }
  124. size_t LLCamera::readFrustumFromBuffer(const char *buffer)
  125. {
  126. memcpy(&mView, buffer, sizeof(F32)); /* Flawfinder: ignore */
  127. buffer += sizeof(F32);
  128. memcpy(&mAspect, buffer, sizeof(F32)); /* Flawfinder: ignore */
  129. buffer += sizeof(F32);
  130. memcpy(&mNearPlane, buffer, sizeof(F32)); /* Flawfinder: ignore */
  131. buffer += sizeof(F32);
  132. memcpy(&mFarPlane, buffer, sizeof(F32)); /* Flawfinder: ignore */
  133. return 4*sizeof(F32);
  134. }
  135. // ---------------- test methods  ---------------- 
  136. S32 LLCamera::AABBInFrustum(const LLVector3 &center, const LLVector3& radius) 
  137. {
  138. static const LLVector3 scaler[] = {
  139. LLVector3(-1,-1,-1),
  140. LLVector3( 1,-1,-1),
  141. LLVector3(-1, 1,-1),
  142. LLVector3( 1, 1,-1),
  143. LLVector3(-1,-1, 1),
  144. LLVector3( 1,-1, 1),
  145. LLVector3(-1, 1, 1),
  146. LLVector3( 1, 1, 1)
  147. };
  148. U8 mask = 0;
  149. S32 result = 2;
  150. /*if (mFrustumCornerDist > 0.f && radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist)
  151. { //box is larger than frustum, check frustum quads against box planes
  152. static const LLVector3 dir[] = 
  153. {
  154. LLVector3(1, 0, 0),
  155. LLVector3(-1, 0, 0),
  156. LLVector3(0, 1, 0),
  157. LLVector3(0, -1, 0),
  158. LLVector3(0, 0, 1),
  159. LLVector3(0, 0, -1)
  160. };
  161. U32 quads[] = 
  162. {
  163. 0, 1, 2, 3,
  164. 0, 1, 5, 4,
  165. 2, 3, 7, 6,
  166. 3, 0, 7, 4,
  167. 1, 2, 6, 4,
  168. 4, 5, 6, 7
  169. };
  170. result = 0;
  171. BOOL total_inside = TRUE;
  172. for (U32 i = 0; i < 6; i++)
  173. LLVector3 p = center + radius.scaledVec(dir[i]);
  174. F32 d = -p*dir[i];
  175. for (U32 j = 0; j < 6; j++)
  176. { //for each quad
  177. F32 dist = mAgentFrustum[quads[j*4+0]]*dir[i] + d;
  178. if (dist > 0)
  179. { //at least one frustum point is outside the AABB
  180. total_inside = FALSE;
  181. for (U32 k = 1; k < 4; k++)
  182. { //for each other point on quad
  183. if ( mAgentFrustum[quads[j*4+k]]*dir[i]+d  <= 0.f)
  184. { //quad is straddling some plane of AABB
  185. return 1;
  186. }
  187. }
  188. }
  189. else
  190. {
  191. for (U32 k = 1; k < 4; k++)
  192. {
  193. if (mAgentFrustum[quads[j*4+k]]*dir[i]+d > 0.f)
  194. {
  195. return 1;
  196. }
  197. }
  198. }
  199. }
  200. }
  201. if (total_inside)
  202. {
  203. result = 1;
  204. }
  205. }
  206. else*/
  207. {
  208. for (U32 i = 0; i < mPlaneCount; i++)
  209. {
  210. mask = mAgentPlanes[i].mask;
  211. if (mask == 0xff)
  212. {
  213. continue;
  214. }
  215. LLPlane p = mAgentPlanes[i].p;
  216. LLVector3 n = LLVector3(p);
  217. float d = p.mV[3];
  218. LLVector3 rscale = radius.scaledVec(scaler[mask]);
  219. LLVector3 minp = center - rscale;
  220. LLVector3 maxp = center + rscale;
  221. if (n * minp > -d) 
  222. {
  223. return 0;
  224. }
  225. if (n * maxp > -d)
  226. {
  227. result = 1;
  228. }
  229. }
  230. }
  231. return result;
  232. }
  233. S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 &center, const LLVector3& radius) 
  234. {
  235. static const LLVector3 scaler[] = {
  236. LLVector3(-1,-1,-1),
  237. LLVector3( 1,-1,-1),
  238. LLVector3(-1, 1,-1),
  239. LLVector3( 1, 1,-1),
  240. LLVector3(-1,-1, 1),
  241. LLVector3( 1,-1, 1),
  242. LLVector3(-1, 1, 1),
  243. LLVector3( 1, 1, 1)
  244. };
  245. U8 mask = 0;
  246. S32 result = 2;
  247. for (U32 i = 0; i < mPlaneCount; i++)
  248. {
  249. if (i == 5)
  250. {
  251. continue;
  252. }
  253. mask = mAgentPlanes[i].mask;
  254. if (mask == 0xff)
  255. {
  256. continue;
  257. }
  258. LLPlane p = mAgentPlanes[i].p;
  259. LLVector3 n = LLVector3(p);
  260. float d = p.mV[3];
  261. LLVector3 rscale = radius.scaledVec(scaler[mask]);
  262. LLVector3 minp = center - rscale;
  263. LLVector3 maxp = center + rscale;
  264. if (n * minp > -d) 
  265. {
  266. return 0;
  267. }
  268. if (n * maxp > -d)
  269. {
  270. result = 1;
  271. }
  272. }
  273. return result;
  274. }
  275. int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius) 
  276. {
  277. LLVector3 dist = sphere_center-mFrustCenter;
  278. float dsq = dist * dist;
  279. float rsq = mFarPlane*0.5f + radius;
  280. rsq *= rsq;
  281. if (dsq < rsq) 
  282. {
  283. return 1;
  284. }
  285. return 0;
  286. }
  287. // HACK: This version is still around because the version below doesn't work
  288. // unless the agent planes are initialized.
  289. // Return 1 if sphere is in frustum, 2 if fully in frustum, otherwise 0.
  290. // NOTE: 'center' is in absolute frame.
  291. int LLCamera::sphereInFrustumOld(const LLVector3 &sphere_center, const F32 radius) const 
  292. {
  293. // Returns 1 if sphere is in frustum, 0 if not.
  294. // modified so that default view frust is along X with Z vertical
  295. F32 x, y, z, rightDist, leftDist, topDist, bottomDist;
  296. // Subtract the view position 
  297. //LLVector3 relative_center;
  298. //relative_center = sphere_center - getOrigin();
  299. LLVector3 rel_center(sphere_center);
  300. rel_center -= mOrigin;
  301. bool all_in = TRUE;
  302. // Transform relative_center.x to camera frame
  303. x = mXAxis * rel_center;
  304. if (x < MIN_NEAR_PLANE - radius)
  305. {
  306. return 0;
  307. }
  308. else if (x < MIN_NEAR_PLANE + radius)
  309. {
  310. all_in = FALSE;
  311. }
  312. if (x > mFarPlane + radius)
  313. {
  314. return 0;
  315. }
  316. else if (x > mFarPlane - radius)
  317. {
  318. all_in = FALSE;
  319. }
  320. // Transform relative_center.y to camera frame
  321. y = mYAxis * rel_center;
  322. // distance to plane is the dot product of (x, y, 0) * plane_normal
  323. rightDist = x * mLocalPlanes[PLANE_RIGHT][VX] + y * mLocalPlanes[PLANE_RIGHT][VY];
  324. if (rightDist < -radius)
  325. {
  326. return 0;
  327. }
  328. else if (rightDist < radius)
  329. {
  330. all_in = FALSE;
  331. }
  332. leftDist = x * mLocalPlanes[PLANE_LEFT][VX] + y * mLocalPlanes[PLANE_LEFT][VY];
  333. if (leftDist < -radius)
  334. {
  335. return 0;
  336. }
  337. else if (leftDist < radius)
  338. {
  339. all_in = FALSE;
  340. }
  341. // Transform relative_center.y to camera frame
  342. z = mZAxis * rel_center;
  343. topDist = x * mLocalPlanes[PLANE_TOP][VX] + z * mLocalPlanes[PLANE_TOP][VZ];
  344. if (topDist < -radius)
  345. {
  346. return 0;
  347. }
  348. else if (topDist < radius)
  349. {
  350. all_in = FALSE;
  351. }
  352. bottomDist = x * mLocalPlanes[PLANE_BOTTOM][VX] + z * mLocalPlanes[PLANE_BOTTOM][VZ];
  353. if (bottomDist < -radius)
  354. {
  355. return 0;
  356. }
  357. else if (bottomDist < radius)
  358. {
  359. all_in = FALSE;
  360. }
  361. if (all_in)
  362. {
  363. return 2;
  364. }
  365. return 1;
  366. }
  367. // HACK: This (presumably faster) version only currently works if you set up the
  368. // frustum planes using GL.  At some point we should get those planes through another
  369. // mechanism, and then we can get rid of the "old" version above.
  370. // Return 1 if sphere is in frustum, 2 if fully in frustum, otherwise 0.
  371. // NOTE: 'center' is in absolute frame.
  372. int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius) const 
  373. {
  374. // Returns 1 if sphere is in frustum, 0 if not.
  375. int res = 2;
  376. for (int i = 0; i < 6; i++)
  377. {
  378. if (mAgentPlanes[i].mask == 0xff)
  379. {
  380. continue;
  381. }
  382. float d = mAgentPlanes[i].p.dist(sphere_center);
  383. if (d > radius) 
  384. {
  385. return 0;
  386. }
  387. if (d > -radius)
  388. {
  389. res = 1;
  390. }
  391. }
  392. return res;
  393. }
  394. // return height of a sphere of given radius, located at center, in pixels
  395. F32 LLCamera::heightInPixels(const LLVector3 &center, F32 radius ) const
  396. {
  397. if (radius == 0.f) return 0.f;
  398. // If height initialized
  399. if (mViewHeightInPixels > -1)
  400. {
  401. // Convert sphere to coord system with 0,0,0 at camera
  402. LLVector3 vec = center - mOrigin;
  403. // Compute distance to sphere
  404. F32 dist = vec.magVec();
  405. // Calculate angle of whole object
  406. F32 angle = 2.0f * (F32) atan2(radius, dist);
  407. // Calculate fraction of field of view
  408. F32 fraction_of_fov = angle / mView;
  409. // Compute number of pixels tall, based on vertical field of view
  410. return (fraction_of_fov * mViewHeightInPixels);
  411. }
  412. else
  413. {
  414. // return invalid height
  415. return -1.0f;
  416. }
  417. }
  418. // If pos is visible, return the distance from pos to the camera.
  419. // Use fudge distance to scale rad against top/bot/left/right planes
  420. // Otherwise, return -distance
  421. F32 LLCamera::visibleDistance(const LLVector3 &pos, F32 rad, F32 fudgedist, U32 planemask) const
  422. {
  423. if (mFixedDistance > 0)
  424. {
  425. return mFixedDistance;
  426. }
  427. LLVector3 dvec = pos - mOrigin;
  428. // Check visibility
  429. F32 dist = dvec.magVec();
  430. if (dist > rad)
  431. {
  432.   F32 dp,tdist;
  433.   dp = dvec * mXAxis;
  434.    if (dp < -rad)
  435.    return -dist;
  436. rad *= fudgedist;
  437. LLVector3 tvec(pos);
  438. for (int p=0; p<PLANE_NUM; p++)
  439. {
  440. if (!(planemask & (1<<p)))
  441. continue;
  442. tdist = -(mWorldPlanes[p].dist(tvec));
  443. if (tdist > rad)
  444. return -dist;
  445. }
  446. }
  447. return dist;
  448. }
  449. // Like visibleDistance, except uses mHorizPlanes[], which are left and right
  450. //  planes perpindicular to (0,0,1) in world space
  451. F32 LLCamera::visibleHorizDistance(const LLVector3 &pos, F32 rad, F32 fudgedist, U32 planemask) const
  452. {
  453. if (mFixedDistance > 0)
  454. {
  455. return mFixedDistance;
  456. }
  457. LLVector3 dvec = pos - mOrigin;
  458. // Check visibility
  459. F32 dist = dvec.magVec();
  460. if (dist > rad)
  461. {
  462. rad *= fudgedist;
  463. LLVector3 tvec(pos);
  464. for (int p=0; p<HORIZ_PLANE_NUM; p++)
  465. {
  466. if (!(planemask & (1<<p)))
  467. continue;
  468. F32 tdist = -(mHorizPlanes[p].dist(tvec));
  469. if (tdist > rad)
  470. return -dist;
  471. }
  472. }
  473. return dist;
  474. }
  475. // ---------------- friends and operators ----------------  
  476. std::ostream& operator<<(std::ostream &s, const LLCamera &C) 
  477. {
  478. s << "{ n";
  479. s << "  Center = " << C.getOrigin() << "n";
  480. s << "  AtAxis = " << C.getXAxis() << "n";
  481. s << "  LeftAxis = " << C.getYAxis() << "n";
  482. s << "  UpAxis = " << C.getZAxis() << "n";
  483. s << "  View = " << C.getView() << "n";
  484. s << "  Aspect = " << C.getAspect() << "n";
  485. s << "  NearPlane   = " << C.mNearPlane << "n";
  486. s << "  FarPlane    = " << C.mFarPlane << "n";
  487. s << "  TopPlane    = " << C.mLocalPlanes[LLCamera::PLANE_TOP][VX] << "  " 
  488. << C.mLocalPlanes[LLCamera::PLANE_TOP][VY] << "  " 
  489. << C.mLocalPlanes[LLCamera::PLANE_TOP][VZ] << "n";
  490. s << "  BottomPlane = " << C.mLocalPlanes[LLCamera::PLANE_BOTTOM][VX] << "  " 
  491. << C.mLocalPlanes[LLCamera::PLANE_BOTTOM][VY] << "  " 
  492. << C.mLocalPlanes[LLCamera::PLANE_BOTTOM][VZ] << "n";
  493. s << "  LeftPlane   = " << C.mLocalPlanes[LLCamera::PLANE_LEFT][VX] << "  " 
  494. << C.mLocalPlanes[LLCamera::PLANE_LEFT][VY] << "  " 
  495. << C.mLocalPlanes[LLCamera::PLANE_LEFT][VZ] << "n";
  496. s << "  RightPlane  = " << C.mLocalPlanes[LLCamera::PLANE_RIGHT][VX] << "  " 
  497. << C.mLocalPlanes[LLCamera::PLANE_RIGHT][VY] << "  " 
  498. << C.mLocalPlanes[LLCamera::PLANE_RIGHT][VZ] << "n";
  499. s << "}";
  500. return s;
  501. }
  502. // ----------------  private member functions ----------------
  503. void LLCamera::calculateFrustumPlanes() 
  504. {
  505. // The planes only change when any of the frustum descriptions change.
  506. // They are not affected by changes of the position of the Frustum
  507. // because they are known in the view frame and the position merely
  508. // provides information on how to get from the absolute frame to the 
  509. // view frame.
  510. F32 left,right,top,bottom;
  511. top = mFarPlane * (F32)tanf(0.5f * mView);
  512. bottom = -top;
  513. left = top * mAspect;
  514. right = -left;
  515. calculateFrustumPlanes(left, right, top, bottom);
  516. }
  517. LLPlane planeFromPoints(LLVector3 p1, LLVector3 p2, LLVector3 p3)
  518. {
  519. LLVector3 n = ((p2-p1)%(p3-p1));
  520. n.normVec();
  521. return LLPlane(p1, n);
  522. }
  523. U8 LLCamera::calcPlaneMask(const LLPlane& plane)
  524. {
  525. U8 mask = 0;
  526. if (plane.mV[0] >= 0)
  527. {
  528. mask |= 1;
  529. }
  530. if (plane.mV[1] >= 0)
  531. {
  532. mask |= 2;
  533. }
  534. if (plane.mV[2] >= 0)
  535. {
  536. mask |= 4;
  537. }
  538. return mask;
  539. }
  540. void LLCamera::ignoreAgentFrustumPlane(S32 idx)
  541. {
  542. if (idx < 0 || idx > (S32) mPlaneCount)
  543. {
  544. return;
  545. }
  546. mAgentPlanes[idx].mask = 0xff;
  547. mAgentPlanes[idx].p.clearVec();
  548. }
  549. void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
  550. {
  551. for (int i = 0; i < 8; i++)
  552. {
  553. mAgentFrustum[i] = frust[i];
  554. }
  555. mFrustumCornerDist = (frust[5] - getOrigin()).magVec();
  556. //frust contains the 8 points of the frustum, calculate 6 planes
  557. //order of planes is important, keep most likely to fail in the front of the list
  558. //near - frust[0], frust[1], frust[2]
  559. mAgentPlanes[2].p = planeFromPoints(frust[0], frust[1], frust[2]);
  560. //far  
  561. mAgentPlanes[5].p = planeFromPoints(frust[5], frust[4], frust[6]);
  562. //left  
  563. mAgentPlanes[0].p = planeFromPoints(frust[4], frust[0], frust[7]);
  564. //right  
  565. mAgentPlanes[1].p = planeFromPoints(frust[1], frust[5], frust[6]);
  566. //top  
  567. mAgentPlanes[4].p = planeFromPoints(frust[3], frust[2], frust[6]);
  568. //bottom  
  569. mAgentPlanes[3].p = planeFromPoints(frust[1], frust[0], frust[4]);
  570. //cache plane octant facing mask for use in AABBInFrustum
  571. for (U32 i = 0; i < mPlaneCount; i++)
  572. {
  573. mAgentPlanes[i].mask = calcPlaneMask(mAgentPlanes[i].p);
  574. }
  575. }
  576. void LLCamera::calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom)
  577. {
  578. LLVector3 a, b, c;
  579. // For each plane we need to define 3 points (LLVector3's) in camera view space.  
  580. // The order in which we pass the points to planeFromPoints() matters, because the 
  581. // plane normal has a degeneracy of 2; we want it pointing _into_ the frustum. 
  582. a.setVec(0.0f, 0.0f, 0.0f);
  583. b.setVec(mFarPlane, right, top);
  584. c.setVec(mFarPlane, right, bottom);
  585. mLocalPlanes[PLANE_RIGHT].setVec(a, b, c);
  586. c.setVec(mFarPlane, left, top);
  587. mLocalPlanes[PLANE_TOP].setVec(a, c, b);
  588. b.setVec(mFarPlane, left, bottom);
  589. mLocalPlanes[PLANE_LEFT].setVec(a, b, c);
  590. c.setVec(mFarPlane, right, bottom);
  591. mLocalPlanes[PLANE_BOTTOM].setVec( a, c, b); 
  592. //calculate center and radius squared of frustum in world absolute coordinates
  593. mFrustCenter = X_AXIS*mFarPlane*0.5f;
  594. mFrustCenter = transformToAbsolute(mFrustCenter);
  595. mFrustRadiusSquared = mFarPlane*0.5f;
  596. mFrustRadiusSquared *= mFrustRadiusSquared * 1.05f; //pad radius squared by 5%
  597. }
  598. // x and y are in WINDOW space, so x = Y-Axis (left/right), y= Z-Axis(Up/Down)
  599. void LLCamera::calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2)
  600. {
  601. F32 bottom, top, left, right;
  602. F32 view_height = (F32)tanf(0.5f * mView) * mFarPlane;
  603. F32 view_width = view_height * mAspect;
  604. left =   x1 * -2.f * view_width;
  605. right =  x2 * -2.f * view_width;
  606. bottom = y1 * 2.f * view_height; 
  607. top =   y2 * 2.f * view_height;
  608. calculateFrustumPlanes(left, right, top, bottom);
  609. }
  610. void LLCamera::calculateWorldFrustumPlanes() 
  611. {
  612. F32 d;
  613. LLVector3 center = mOrigin - mXAxis*mNearPlane;
  614. mWorldPlanePos = center;
  615. for (int p=0; p<4; p++)
  616. {
  617. LLVector3 pnorm = LLVector3(mLocalPlanes[p]);
  618. LLVector3 norm = rotateToAbsolute(pnorm);
  619. norm.normVec();
  620. d = -(center * norm);
  621. mWorldPlanes[p] = LLPlane(norm, d);
  622. }
  623. // horizontal planes, perpindicular to (0,0,1);
  624. LLVector3 zaxis(0, 0, 1.0f);
  625. F32 yaw = getYaw();
  626. {
  627. LLVector3 tnorm = LLVector3(mLocalPlanes[PLANE_LEFT]);
  628. tnorm.rotVec(yaw, zaxis);
  629. d = -(mOrigin * tnorm);
  630. mHorizPlanes[HORIZ_PLANE_LEFT] = LLPlane(tnorm, d);
  631. }
  632. {
  633. LLVector3 tnorm = LLVector3(mLocalPlanes[PLANE_RIGHT]);
  634. tnorm.rotVec(yaw, zaxis);
  635. d = -(mOrigin * tnorm);
  636. mHorizPlanes[HORIZ_PLANE_RIGHT] = LLPlane(tnorm, d);
  637. }
  638. }
  639. // NOTE: this is the OpenGL matrix that will transform the default OpenGL view 
  640. // (-Z=at, Y=up) to the default view of the LLCamera class (X=at, Z=up):
  641. // 
  642. // F32 cfr_transform =  {  0.f,  0.f, -1.f,  0.f,   // -Z becomes X
  643. //    -1.f,  0.f,  0.f,  0.f,   // -X becomes Y
  644. //      0.f,  1.f,  0.f,  0.f,   //  Y becomes Z
  645. //     0.f,  0.f,  0.f,  1.f };