PageRenderTime 17ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmath/llcamera.cpp

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