llxform.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /**
  2. * @file llxform.h
  3. *
  4. * $LicenseInfo:firstyear=2001&license=viewergpl$
  5. *
  6. * Copyright (c) 2001-2009, Linden Research, Inc.
  7. *
  8. * Second Life Viewer Source Code
  9. * The source code in this file ("Source Code") is provided by Linden Lab
  10. * to you under the terms of the GNU General Public License, version 2.0
  11. * ("GPL"), unless you have obtained a separate licensing agreement
  12. * ("Other License"), formally executed by you and Linden Lab. Terms of
  13. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15. *
  16. * There are special exceptions to the terms and conditions of the GPL as
  17. * it is applied to this Source Code. View the full text of the exception
  18. * in the file doc/FLOSS-exception.txt in this software distribution, or
  19. * online at
  20. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21. *
  22. * By copying, modifying or distributing this software, you acknowledge
  23. * that you have read and understood your obligations described above,
  24. * and agree to abide by those obligations.
  25. *
  26. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28. * COMPLETENESS OR PERFORMANCE.
  29. * $/LicenseInfo$
  30. */
  31. #ifndef LL_XFORM_H
  32. #define LL_XFORM_H
  33. #include "llvector3.h"
  34. #include "llmatrix4.h"
  35. #include "llvolume.h" // For LL_VOLUME_AREANA_NEW_DELETE
  36. // MAX_OBJECT_Z should match REGION_HEIGHT_METERS:
  37. constexpr F32 MAX_OBJECT_Z = 4096.f;
  38. constexpr F32 MIN_OBJECT_Z = -256.f;
  39. constexpr F32 DEFAULT_MAX_PRIM_SCALE = 64.f;
  40. constexpr F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = 10.f;
  41. constexpr F32 DEFAULT_MIN_PRIM_SCALE = 0.01f;
  42. class LLXform
  43. {
  44. protected:
  45. LOG_CLASS(LLXform);
  46. public:
  47. #if LL_JEMALLOC
  48. // LLXform does not need to be 16-byte aligned but benefits from arenas
  49. LL_VOLUME_AREANA_NEW_DELETE
  50. #endif
  51. typedef enum e_changed_flags
  52. {
  53. UNCHANGED = 0x00,
  54. TRANSLATED = 0x01,
  55. ROTATED = 0x02,
  56. SCALED = 0x04,
  57. SHIFTED = 0x08,
  58. GEOMETRY = 0x10,
  59. TEXTURE = 0x20,
  60. MOVED = TRANSLATED | ROTATED | SCALED,
  61. SILHOUETTE = 0x40,
  62. ALL_CHANGED = 0x7f
  63. } EChangedFlags;
  64. void init();
  65. LLXform() noexcept;
  66. virtual ~LLXform() = default;
  67. LL_INLINE void getLocalMat4(LLMatrix4& mat) const
  68. {
  69. mat.initAll(mScale, mRotation, mPosition);
  70. }
  71. LL_INLINE bool setParent(LLXform* parent);
  72. LL_INLINE void setPosition(const LLVector3& pos);
  73. LL_INLINE void setPosition(F32 x, F32 y, F32 z);
  74. LL_INLINE void setPositionX(F32 x);
  75. LL_INLINE void setPositionY(F32 y);
  76. LL_INLINE void setPositionZ(F32 z);
  77. LL_INLINE void addPosition(const LLVector3& pos);
  78. LL_INLINE void setScale(const LLVector3& scale);
  79. LL_INLINE void setScale(F32 x, F32 y, F32 z);
  80. LL_INLINE void setRotation(const LLQuaternion& rot);
  81. LL_INLINE void setRotation(F32 x, F32 y, F32 z);
  82. LL_INLINE void setRotation(F32 x, F32 y, F32 z, F32 s);
  83. // Above functions must be inline for speed, but also need to emit
  84. // warnings. llwarns causes inline LLError::CallSite static objects that
  85. // make more work for the linker, and duplicating the warning string
  86. // everywhere is costly. Avoid inline llwarns by calling this function. HB
  87. LL_NO_INLINE void warn(U32 idx);
  88. LL_INLINE void setChanged(U32 bits) { mChanged |= bits; }
  89. LL_INLINE bool isChanged() const { return mChanged != 0; }
  90. LL_INLINE bool isChanged(U32 bits) const { return (mChanged & bits) != 0; }
  91. LL_INLINE void clearChanged() { mChanged = 0; }
  92. LL_INLINE void clearChanged(U32 bits) { mChanged &= ~bits; }
  93. LL_INLINE void setScaleChildOffset(bool scale) { mScaleChildOffset = scale; }
  94. LL_INLINE bool getScaleChildOffset() { return mScaleChildOffset; }
  95. LL_INLINE LLXform* getParent() const { return mParent; }
  96. LLXform* getRoot() const;
  97. LL_INLINE virtual bool isRoot() const { return !mParent; }
  98. LL_INLINE virtual bool isRootEdit() const { return !mParent; }
  99. LL_INLINE const LLVector3& getPosition() const { return mPosition; }
  100. LL_INLINE const LLVector3& getScale() const { return mScale; }
  101. LL_INLINE const LLQuaternion& getRotation() const { return mRotation; }
  102. LL_INLINE const LLVector3& getPositionW() const { return mWorldPosition; }
  103. LL_INLINE const LLQuaternion& getWorldRotation() const { return mWorldRotation; }
  104. LL_INLINE const LLVector3& getWorldPosition() const { return mWorldPosition; }
  105. LL_INLINE bool isAvatar() const { return mIsAvatar; }
  106. protected:
  107. LL_INLINE void setAvatar(bool b) { mIsAvatar = b; }
  108. protected:
  109. LLQuaternion mRotation;
  110. LLVector3 mPosition;
  111. LLVector3 mScale;
  112. // *TODO: move these world transform members to LLXformMatrix as they are
  113. // *never* updated or accessed in the base class.
  114. LLVector3 mWorldPosition;
  115. LLQuaternion mWorldRotation;
  116. LLXform* mParent;
  117. U32 mChanged;
  118. bool mIsAvatar;
  119. bool mScaleChildOffset;
  120. };
  121. class LLXformMatrix : public LLXform
  122. {
  123. public:
  124. LLXformMatrix();
  125. LL_INLINE const LLMatrix4& getWorldMatrix() const { return mWorldMatrix; }
  126. LL_INLINE void setWorldMatrix(const LLMatrix4& mat) { mWorldMatrix = mat; }
  127. void init();
  128. void update();
  129. void updateMatrix(bool update_bounds = true);
  130. LL_INLINE void getMinMax(LLVector3& min, LLVector3& max) const
  131. {
  132. min = mMin;
  133. max = mMax;
  134. }
  135. protected:
  136. LLMatrix4 mWorldMatrix;
  137. LLVector3 mMin;
  138. LLVector3 mMax;
  139. };
  140. LL_INLINE bool LLXform::setParent(LLXform* parent)
  141. {
  142. // Validate and make sure we are not creating a loop
  143. if (parent == mParent)
  144. {
  145. return true;
  146. }
  147. if (parent)
  148. {
  149. LLXform* cur_par = parent->mParent;
  150. while (cur_par)
  151. {
  152. if (cur_par == this)
  153. {
  154. return false;
  155. }
  156. cur_par = cur_par->mParent;
  157. }
  158. }
  159. mParent = parent;
  160. return true;
  161. }
  162. LL_INLINE void LLXform::setPosition(const LLVector3& pos)
  163. {
  164. mChanged |= TRANSLATED;
  165. if (pos.isFinite())
  166. {
  167. mPosition = pos;
  168. }
  169. else
  170. {
  171. mPosition.clear();
  172. warn(0);
  173. }
  174. }
  175. LL_INLINE void LLXform::setPosition(F32 x, F32 y, F32 z)
  176. {
  177. mChanged |= TRANSLATED;
  178. if (llfinite(x) && llfinite(y) && llfinite(z))
  179. {
  180. mPosition.set(x, y, z);
  181. }
  182. else
  183. {
  184. mPosition.clear();
  185. warn(1);
  186. }
  187. }
  188. LL_INLINE void LLXform::setPositionX(F32 x)
  189. {
  190. mChanged |= TRANSLATED;
  191. if (llfinite(x))
  192. {
  193. mPosition.mV[VX] = x;
  194. }
  195. else
  196. {
  197. mPosition.mV[VX] = 0.f;
  198. warn(2);
  199. }
  200. }
  201. LL_INLINE void LLXform::setPositionY(F32 y)
  202. {
  203. mChanged |= TRANSLATED;
  204. if (llfinite(y))
  205. {
  206. mPosition.mV[VY] = y;
  207. }
  208. else
  209. {
  210. mPosition.mV[VY] = 0.f;
  211. warn(3);
  212. }
  213. }
  214. LL_INLINE void LLXform::setPositionZ(F32 z)
  215. {
  216. mChanged |= TRANSLATED;
  217. if (llfinite(z))
  218. {
  219. mPosition.mV[VZ] = z;
  220. }
  221. else
  222. {
  223. mPosition.mV[VZ] = 0.f;
  224. warn(4);
  225. }
  226. }
  227. LL_INLINE void LLXform::addPosition(const LLVector3& pos)
  228. {
  229. if (pos.isFinite())
  230. {
  231. mChanged |= TRANSLATED;
  232. mPosition += pos;
  233. }
  234. else
  235. {
  236. warn(5);
  237. }
  238. }
  239. LL_INLINE void LLXform::setScale(const LLVector3& scale)
  240. {
  241. mChanged |= SCALED;
  242. if (scale.isFinite())
  243. {
  244. mScale = scale;
  245. }
  246. else
  247. {
  248. mScale.set(1.f, 1.f, 1.f);
  249. warn(6);
  250. }
  251. }
  252. LL_INLINE void LLXform::setScale(F32 x, F32 y, F32 z)
  253. {
  254. mChanged |= SCALED;
  255. if (llfinite(x) && llfinite(y) && llfinite(z))
  256. {
  257. mScale.set(x, y, z);
  258. }
  259. else
  260. {
  261. mScale.set(1.f, 1.f, 1.f);
  262. warn(7);
  263. }
  264. }
  265. LL_INLINE void LLXform::setRotation(const LLQuaternion& rot)
  266. {
  267. mChanged |= ROTATED;
  268. if (rot.isFinite())
  269. {
  270. mRotation = rot;
  271. }
  272. else
  273. {
  274. mRotation.loadIdentity();
  275. warn(8);
  276. }
  277. }
  278. LL_INLINE void LLXform::setRotation(F32 x, F32 y, F32 z)
  279. {
  280. mChanged |= ROTATED;
  281. if (llfinite(x) && llfinite(y) && llfinite(z))
  282. {
  283. mRotation.setEulerAngles(x, y, z);
  284. }
  285. else
  286. {
  287. mRotation.loadIdentity();
  288. warn(9);
  289. }
  290. }
  291. LL_INLINE void LLXform::setRotation(F32 x, F32 y, F32 z, F32 s)
  292. {
  293. mChanged |= ROTATED;
  294. if (llfinite(x) && llfinite(y) && llfinite(z) && llfinite(s))
  295. {
  296. mRotation.mQ[VX] = x;
  297. mRotation.mQ[VY] = y;
  298. mRotation.mQ[VZ] = z;
  299. mRotation.mQ[VS] = s;
  300. }
  301. else
  302. {
  303. mRotation.loadIdentity();
  304. warn(10);
  305. }
  306. }
  307. #endif