llcamera.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /**
  2. * @file llcamera.h
  3. * @brief Header file for the LLCamera class.
  4. *
  5. * $LicenseInfo:firstyear=2000&license=viewergpl$
  6. *
  7. * Copyright (c) 2000-2009, 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. #ifndef LL_CAMERA_H
  33. #define LL_CAMERA_H
  34. #include "llcoordframe.h"
  35. #include "llmath.h"
  36. #include "llplane.h"
  37. constexpr F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD;
  38. constexpr F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f;
  39. constexpr F32 DEFAULT_NEAR_PLANE = 0.25f;
  40. // Far reaches across two horizontal, not diagonal, regions:
  41. constexpr F32 DEFAULT_FAR_PLANE = 64.f;
  42. constexpr F32 MAX_ASPECT_RATIO = 50.0f;
  43. // Clamp the near plane just before the skybox ends
  44. constexpr F32 MAX_NEAR_PLANE = 1023.9f;
  45. // Max allowed. Not good Z precision though:
  46. constexpr F32 MAX_FAR_PLANE = 100000.0f;
  47. constexpr F32 MAX_FAR_CLIP = 512.0f;
  48. constexpr F32 MIN_ASPECT_RATIO = 0.02f;
  49. constexpr F32 MIN_NEAR_PLANE = 0.1f;
  50. constexpr F32 MIN_FAR_PLANE = 0.2f;
  51. // Min/Max FOV values for square views. Call getMin/MaxView to get extremes
  52. // based on current aspect ratio.
  53. constexpr F32 MIN_FIELD_OF_VIEW = 5.f * DEG_TO_RAD;
  54. constexpr F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
  55. // An LLCamera is an LLCoorFrame with a view frustum. This means that it has
  56. // several methods for moving it around that are inherited from the
  57. // LLCoordFrame() class :
  58. //
  59. // setOrigin(), setAxes()
  60. // translate(), rotate()
  61. // roll(), pitch(), yaw()
  62. // etc...
  63. class alignas(16) LLCamera : public LLCoordFrame
  64. {
  65. public:
  66. LLCamera(const LLCamera& rhs)
  67. {
  68. *this = rhs;
  69. }
  70. enum
  71. {
  72. PLANE_LEFT = 0,
  73. PLANE_RIGHT = 1,
  74. PLANE_BOTTOM = 2,
  75. PLANE_TOP = 3,
  76. PLANE_NUM = 4,
  77. PLANE_MASK_NONE = 0xff // Disable this plane
  78. };
  79. enum
  80. {
  81. PLANE_LEFT_MASK = 1 << PLANE_LEFT,
  82. PLANE_RIGHT_MASK = 1 << PLANE_RIGHT,
  83. PLANE_BOTTOM_MASK = 1 << PLANE_BOTTOM,
  84. PLANE_TOP_MASK = 1 << PLANE_TOP,
  85. PLANE_ALL_MASK = 0xf
  86. };
  87. // Indexes to mAgentPlanes[] and mPlaneMask[]
  88. enum
  89. {
  90. AGENT_PLANE_LEFT = 0,
  91. AGENT_PLANE_RIGHT = 1,
  92. AGENT_PLANE_NEAR = 2,
  93. AGENT_PLANE_BOTTOM = 3,
  94. AGENT_PLANE_TOP = 4,
  95. AGENT_PLANE_FAR = 5,
  96. AGENT_PLANE_USER_CLIP = 6
  97. };
  98. // Sizes for mAgentPlanes[]. 7th entry is special case for user clip
  99. enum
  100. {
  101. AGENT_PLANE_NO_USER_CLIP_NUM = 6,
  102. AGENT_PLANE_USER_CLIP_NUM = 7,
  103. PLANE_MASK_NUM = 8 // 7 actually used, 8 is for alignment
  104. };
  105. enum
  106. {
  107. AGENT_FRUSTRUM_NUM = 8
  108. };
  109. enum
  110. {
  111. HORIZ_PLANE_LEFT = 0,
  112. HORIZ_PLANE_RIGHT = 1,
  113. HORIZ_PLANE_NUM = 2
  114. };
  115. enum
  116. {
  117. HORIZ_PLANE_LEFT_MASK = 1 << HORIZ_PLANE_LEFT,
  118. HORIZ_PLANE_RIGHT_MASK = 1 << HORIZ_PLANE_RIGHT,
  119. HORIZ_PLANE_ALL_MASK = 0x3
  120. };
  121. LLCamera();
  122. LLCamera(F32 vertical_fov_rads, F32 aspect_ratio,
  123. S32 view_height_in_pixels, F32 near_plane, F32 far_plane);
  124. bool isChanged(); // Checks if mAgentPlanes changed since last frame.
  125. LL_INLINE void setUserClipPlane(const LLPlane& plane)
  126. {
  127. mPlaneCount = AGENT_PLANE_USER_CLIP_NUM;
  128. mAgentPlanes[AGENT_PLANE_USER_CLIP] = plane;
  129. mPlaneMask[AGENT_PLANE_USER_CLIP] = plane.calcPlaneMask();
  130. }
  131. LL_INLINE void disableUserClipPlane()
  132. {
  133. mPlaneCount = AGENT_PLANE_NO_USER_CLIP_NUM;
  134. }
  135. LL_INLINE virtual void setView(F32 vert_fov_rads)
  136. {
  137. mView = llclamp(vert_fov_rads, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW);
  138. calculateFrustumPlanes();
  139. }
  140. LL_INLINE void setViewHeightInPixels(S32 height)
  141. {
  142. mViewHeightInPixels = height;
  143. // We do not really need to do this, but update the pixel meter ratio
  144. // with it.
  145. calculateFrustumPlanes();
  146. }
  147. LL_INLINE void setAspect(F32 new_aspect)
  148. {
  149. mAspect = llclamp(new_aspect, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO);
  150. calculateFrustumPlanes();
  151. }
  152. LL_INLINE void setNear(F32 new_near)
  153. {
  154. mNearPlane = llclamp(new_near, MIN_NEAR_PLANE, MAX_NEAR_PLANE);
  155. calculateFrustumPlanes();
  156. }
  157. LL_INLINE void setFar(F32 new_far)
  158. {
  159. mFarPlane = llclamp(new_far, MIN_FAR_PLANE, MAX_FAR_PLANE);
  160. calculateFrustumPlanes();
  161. }
  162. LL_INLINE const LLPlane& getAgentPlane(U32 idx) const
  163. {
  164. return mAgentPlanes[idx];
  165. }
  166. // Non-const version of the above (used only in llpipeline.cpp). HB
  167. LL_INLINE LLPlane& agentPlane(U32 idx) { return mAgentPlanes[idx]; }
  168. // Returns the vertical FOV in radians
  169. LL_INLINE F32 getView() const { return mView; }
  170. LL_INLINE S32 getViewHeightInPixels() const { return mViewHeightInPixels; }
  171. // Returns width / height
  172. LL_INLINE F32 getAspect() const { return mAspect; }
  173. // Distance in meters
  174. LL_INLINE F32 getNear() const { return mNearPlane; }
  175. // Distance in meters
  176. LL_INLINE F32 getFar() const { return mFarPlane; }
  177. // The values returned by the min/max view getters depend upon the aspect
  178. // ratio at the time they are called and therefore should not be cached.
  179. LL_INLINE F32 getMinView() const
  180. {
  181. // Minimum vertical FOV needs to be constrained in narrow windows.
  182. return mAspect > 1 ? MIN_FIELD_OF_VIEW // wide views
  183. // Clamps minimum width in narrow views
  184. : MIN_FIELD_OF_VIEW / mAspect;
  185. }
  186. LL_INLINE F32 getMaxView() const
  187. {
  188. // Maximum vertical fov needs to be constrained in wide windows.
  189. // Clamps maximum width in wide views
  190. return mAspect > 1 ? MAX_FIELD_OF_VIEW / mAspect
  191. : MAX_FIELD_OF_VIEW; // Narrow views
  192. }
  193. LL_INLINE F32 getYaw() const
  194. {
  195. return atan2f(mXAxis[VY], mXAxis[VX]);
  196. }
  197. LL_INLINE F32 getPitch() const
  198. {
  199. F32 xylen = sqrtf(mXAxis[VX] * mXAxis[VX] + mXAxis[VY] * mXAxis[VY]);
  200. return atan2f(mXAxis[VZ], xylen);
  201. }
  202. // Copy mView, mAspect, mNearPlane, and mFarPlane to buffer.
  203. // Return number of bytes copied.
  204. size_t writeFrustumToBuffer(char* buffer) const;
  205. // Copy mView, mAspect, mNearPlane, and mFarPlane from buffer.
  206. // Return number of bytes copied.
  207. size_t readFrustumFromBuffer(const char* buffer);
  208. void calcAgentFrustumPlanes(LLVector3* frust);
  209. // Calculate regional planes from mAgentPlanes:
  210. void calcRegionFrustumPlanes(const LLVector3& shift,
  211. F32 far_clip_distance);
  212. LL_INLINE void ignoreAgentFrustumPlane(S32 idx)
  213. {
  214. if (idx >= 0 && idx < (S32)mPlaneCount)
  215. {
  216. mPlaneMask[idx] = PLANE_MASK_NONE;
  217. mAgentPlanes[idx].clear();
  218. }
  219. }
  220. // Returns 1 if partly in, 2 if fully in; 'center' is in absolute frame.
  221. S32 sphereInFrustum(const LLVector3& center, F32 radius) const;
  222. LL_INLINE S32 pointInFrustum(const LLVector3& point) const
  223. {
  224. return sphereInFrustum(point, 0.0f);
  225. }
  226. LL_INLINE S32 sphereInFrustumFull(const LLVector3& center,
  227. F32 radius) const
  228. {
  229. return sphereInFrustum(center, radius);
  230. }
  231. S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius,
  232. const LLPlane* planes = NULL);
  233. // Exactly same method as AABBInFrustum(...) except it uses mRegionPlanes
  234. // instead of mAgentPlanes.
  235. LL_INLINE S32 AABBInRegionFrustum(const LLVector4a& center,
  236. const LLVector4a& radius)
  237. {
  238. return AABBInFrustum(center, radius, mRegionPlanes);
  239. }
  240. S32 AABBInFrustumNoFarClip(const LLVector4a& center,
  241. const LLVector4a& radius,
  242. const LLPlane* planes = NULL);
  243. // Exactly same method as AABBInFrustumNoFarClip(...) except it uses
  244. // mRegionPlanes instead of mAgentPlanes.
  245. LL_INLINE S32 AABBInRegionFrustumNoFarClip(const LLVector4a& center,
  246. const LLVector4a& radius)
  247. {
  248. return AABBInFrustumNoFarClip(center, radius, mRegionPlanes);
  249. }
  250. // Does a quick'n dirty sphere-sphere check
  251. S32 sphereInFrustumQuick(const LLVector3& sphere_center, F32 radius);
  252. // Returns height of object in pixels (must be height because field of view
  253. // is based on window height).
  254. F32 heightInPixels(const LLVector3& center, F32 radius) const;
  255. LL_INLINE void setFixedDistance(F32 d) { mFixedDistance = d; }
  256. friend std::ostream& operator<<(std::ostream& s, const LLCamera& c);
  257. protected:
  258. void calculateFrustumPlanes();
  259. void calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom);
  260. void calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2);
  261. private:
  262. // Frustum planes in agent space a la gluUnproject (I'm a bastard, I know)
  263. // - DaveP
  264. alignas(16) LLPlane mAgentPlanes[AGENT_PLANE_USER_CLIP_NUM];
  265. // Frustum planes in a local region space, derived from mAgentPlanes
  266. alignas(16) LLPlane mRegionPlanes[AGENT_PLANE_USER_CLIP_NUM];
  267. alignas(16) LLPlane mLastAgentPlanes[AGENT_PLANE_USER_CLIP_NUM];
  268. // Center of frustum and radius squared for ultra-quick exclusion test
  269. LLVector3 mFrustCenter;
  270. // Defaults to 6, if setUserClipPlane is called, uses user supplied clip
  271. // plane in
  272. U32 mPlaneCount;
  273. // Angle between top and bottom frustum planes in radians.
  274. F32 mView;
  275. F32 mAspect; // Width/height
  276. // For ViewHeightInPixels() only
  277. S32 mViewHeightInPixels;
  278. F32 mNearPlane;
  279. F32 mFarPlane;
  280. // Always return this distance, unless < 0
  281. F32 mFixedDistance;
  282. F32 mFrustRadiusSquared;
  283. U8 mPlaneMask[PLANE_MASK_NUM];
  284. public:
  285. // 8 corners of 6-plane frustum
  286. LLVector3 mAgentFrustum[AGENT_FRUSTRUM_NUM];
  287. // Distance to corner of frustum against far clip plane
  288. F32 mFrustumCornerDist;
  289. };
  290. #endif