llvector3.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /**
  2. * @file llvector3.cpp
  3. * @brief LLVector3 class implementation.
  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. #include "linden_common.h"
  33. #include "llvector3.h"
  34. #include "llvector2.h"
  35. #include "llvector4.h"
  36. #include "llmatrix4.h"
  37. #include "llmatrix3.h"
  38. #include "llquaternion.h"
  39. #include "llquantize.h"
  40. #include "llvector3d.h"
  41. // LLVector3
  42. // WARNING: Do not use these for global const definitions !
  43. // For example:
  44. // const LLQuaternion(0.5f * F_PI, LLVector3::zero);
  45. // at the top of a *.cpp file might not give you what you think.
  46. const LLVector3 LLVector3::zero(0.f, 0.f, 0.f);
  47. const LLVector3 LLVector3::x_axis(1.f, 0.f, 0.f);
  48. const LLVector3 LLVector3::y_axis(0.f, 1.f, 0.f);
  49. const LLVector3 LLVector3::z_axis(0.f, 0.f, 1.f);
  50. const LLVector3 LLVector3::x_axis_neg(-1.f, 0.f, 0.f);
  51. const LLVector3 LLVector3::y_axis_neg(0.f, -1.f, 0.f);
  52. const LLVector3 LLVector3::z_axis_neg(0.f, 0.f, -1.f);
  53. const LLVector3 LLVector3::all_one(1.f, 1.f, 1.f);
  54. LLVector3::LLVector3(const LLVector2& vec) noexcept
  55. {
  56. mV[VX] = (F32)vec.mV[VX];
  57. mV[VY] = (F32)vec.mV[VY];
  58. mV[VZ] = 0.f;
  59. }
  60. LLVector3::LLVector3(const LLVector3d& vec) noexcept
  61. {
  62. mV[VX] = (F32)vec.mdV[VX];
  63. mV[VY] = (F32)vec.mdV[VY];
  64. mV[VZ] = (F32)vec.mdV[VZ];
  65. }
  66. LLVector3::LLVector3(const LLVector4& vec) noexcept
  67. {
  68. mV[VX] = (F32)vec.mV[VX];
  69. mV[VY] = (F32)vec.mV[VY];
  70. mV[VZ] = (F32)vec.mV[VZ];
  71. }
  72. const LLVector3& LLVector3::set(const LLVector3d& vec)
  73. {
  74. mV[0] = (F32)vec.mdV[0];
  75. mV[1] = (F32)vec.mdV[1];
  76. mV[2] = (F32)vec.mdV[2];
  77. return *this;
  78. }
  79. const LLVector3& LLVector3::set(const LLVector4& vec)
  80. {
  81. mV[0] = vec.mV[0];
  82. mV[1] = vec.mV[1];
  83. mV[2] = vec.mV[2];
  84. return *this;
  85. }
  86. // Clamps each values to range (min,max). Returns true if data changed.
  87. bool LLVector3::clamp(F32 min, F32 max)
  88. {
  89. bool ret = false;
  90. if (mV[0] < min) { mV[0] = min; ret = true; }
  91. if (mV[1] < min) { mV[1] = min; ret = true; }
  92. if (mV[2] < min) { mV[2] = min; ret = true; }
  93. if (mV[0] > max) { mV[0] = max; ret = true; }
  94. if (mV[1] > max) { mV[1] = max; ret = true; }
  95. if (mV[2] > max) { mV[2] = max; ret = true; }
  96. return ret;
  97. }
  98. // Clamps length to an upper limit. Returns true if the data changed.
  99. bool LLVector3::clampLength(F32 length_limit)
  100. {
  101. bool changed = false;
  102. F32 len = length();
  103. if (llfinite(len))
  104. {
  105. if (len > length_limit)
  106. {
  107. normalize();
  108. if (length_limit < 0.f)
  109. {
  110. length_limit = 0.f;
  111. }
  112. mV[0] *= length_limit;
  113. mV[1] *= length_limit;
  114. mV[2] *= length_limit;
  115. changed = true;
  116. }
  117. }
  118. else
  119. { // this vector may still be salvagable
  120. F32 max_abs_component = 0.f;
  121. for (S32 i = 0; i < 3; ++i)
  122. {
  123. F32 abs_component = fabs(mV[i]);
  124. if (llfinite(abs_component))
  125. {
  126. if (abs_component > max_abs_component)
  127. {
  128. max_abs_component = abs_component;
  129. }
  130. }
  131. else
  132. {
  133. // no it can't be salvaged --> clear it
  134. clear();
  135. changed = true;
  136. break;
  137. }
  138. }
  139. if (!changed)
  140. {
  141. // yes it can be salvaged -->
  142. // bring the components down before we normalize
  143. mV[0] /= max_abs_component;
  144. mV[1] /= max_abs_component;
  145. mV[2] /= max_abs_component;
  146. normalize();
  147. if (length_limit < 0.f)
  148. {
  149. length_limit = 0.f;
  150. }
  151. mV[0] *= length_limit;
  152. mV[1] *= length_limit;
  153. mV[2] *= length_limit;
  154. }
  155. }
  156. return changed;
  157. }
  158. bool LLVector3::clamp(const LLVector3& min_vec, const LLVector3& max_vec)
  159. {
  160. bool ret = false;
  161. if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = true; }
  162. if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = true; }
  163. if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = true; }
  164. if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = true; }
  165. if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = true; }
  166. if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = true; }
  167. return ret;
  168. }
  169. // Sets all values to absolute value of their original values
  170. // Returns true if data changed
  171. bool LLVector3::abs()
  172. {
  173. bool ret = false;
  174. if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; }
  175. if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; }
  176. if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; }
  177. return ret;
  178. }
  179. // Quatizations
  180. void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
  181. {
  182. F32 x = mV[VX];
  183. F32 y = mV[VY];
  184. F32 z = mV[VZ];
  185. x = U16_to_F32(F32_to_U16(x, lowerxy, upperxy), lowerxy, upperxy);
  186. y = U16_to_F32(F32_to_U16(y, lowerxy, upperxy), lowerxy, upperxy);
  187. z = U16_to_F32(F32_to_U16(z, lowerz, upperz), lowerz, upperz);
  188. mV[VX] = x;
  189. mV[VY] = y;
  190. mV[VZ] = z;
  191. }
  192. void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
  193. {
  194. mV[VX] = U8_to_F32(F32_to_U8(mV[VX], lowerxy, upperxy), lowerxy, upperxy);;
  195. mV[VY] = U8_to_F32(F32_to_U8(mV[VY], lowerxy, upperxy), lowerxy, upperxy);
  196. mV[VZ] = U8_to_F32(F32_to_U8(mV[VZ], lowerz, upperz), lowerz, upperz);
  197. }
  198. void LLVector3::snap(S32 sig_digits)
  199. {
  200. mV[VX] = snap_to_sig_figs(mV[VX], sig_digits);
  201. mV[VY] = snap_to_sig_figs(mV[VY], sig_digits);
  202. mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits);
  203. }
  204. const LLVector3& LLVector3::rotVec(const LLMatrix3& mat)
  205. {
  206. *this = *this * mat;
  207. return *this;
  208. }
  209. const LLVector3& LLVector3::rotVec(const LLQuaternion& q)
  210. {
  211. *this = *this * q;
  212. return *this;
  213. }
  214. const LLVector3& LLVector3::transVec(const LLMatrix4& mat)
  215. {
  216. set(mV[VX] * mat.mMatrix[VX][VX] + mV[VY] * mat.mMatrix[VX][VY] +
  217. mV[VZ] * mat.mMatrix[VX][VZ] + mat.mMatrix[VX][VW],
  218. mV[VX] * mat.mMatrix[VY][VX] + mV[VY] * mat.mMatrix[VY][VY] +
  219. mV[VZ] * mat.mMatrix[VY][VZ] + mat.mMatrix[VY][VW],
  220. mV[VX] * mat.mMatrix[VZ][VX] + mV[VY] * mat.mMatrix[VZ][VY] +
  221. mV[VZ] * mat.mMatrix[VZ][VZ] + mat.mMatrix[VZ][VW]);
  222. return *this;
  223. }
  224. const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3& vec)
  225. {
  226. if (angle && !vec.isExactlyZero())
  227. {
  228. *this = *this * LLQuaternion(angle, vec);
  229. }
  230. return *this;
  231. }
  232. const LLVector3& LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z)
  233. {
  234. LLVector3 vec(x, y, z);
  235. if (angle && !vec.isExactlyZero())
  236. {
  237. *this = *this * LLQuaternion(angle, vec);
  238. }
  239. return *this;
  240. }
  241. const LLVector3& LLVector3::scaleVec(const LLVector3& vec)
  242. {
  243. mV[VX] *= vec.mV[VX];
  244. mV[VY] *= vec.mV[VY];
  245. mV[VZ] *= vec.mV[VZ];
  246. return *this;
  247. }
  248. LLVector3 LLVector3::scaledVec(const LLVector3& vec) const
  249. {
  250. LLVector3 ret = LLVector3(*this);
  251. ret.scaleVec(vec);
  252. return ret;
  253. }
  254. const LLVector3& operator*=(LLVector3& a, const LLQuaternion& rot)
  255. {
  256. const F32 rw = -rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] -
  257. rot.mQ[VZ] * a.mV[VZ];
  258. const F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] -
  259. rot.mQ[VZ] * a.mV[VY];
  260. const F32 ry = rot.mQ[VW] * a.mV[VY] + rot.mQ[VZ] * a.mV[VX] -
  261. rot.mQ[VX] * a.mV[VZ];
  262. const F32 rz = rot.mQ[VW] * a.mV[VZ] + rot.mQ[VX] * a.mV[VY] -
  263. rot.mQ[VY] * a.mV[VX];
  264. a.mV[VX] = -rw * rot.mQ[VX] + rx * rot.mQ[VW] - ry * rot.mQ[VZ] +
  265. rz * rot.mQ[VY];
  266. a.mV[VY] = -rw * rot.mQ[VY] + ry * rot.mQ[VW] - rz * rot.mQ[VX] +
  267. rx * rot.mQ[VZ];
  268. a.mV[VZ] = -rw * rot.mQ[VZ] + rz * rot.mQ[VW] - rx * rot.mQ[VY] +
  269. ry * rot.mQ[VX];
  270. return a;
  271. }
  272. //static
  273. bool LLVector3::parseVector3(const std::string& buf, LLVector3* value)
  274. {
  275. if (!value || buf.empty())
  276. {
  277. return false;
  278. }
  279. LLVector3 v;
  280. S32 count = sscanf(buf.c_str(), "%f %f %f", v.mV, v.mV + 1, v.mV + 2);
  281. if (count != 3)
  282. {
  283. count = sscanf(buf.c_str(), "%f, %f, %f", v.mV, v.mV + 1, v.mV + 2);
  284. }
  285. if (count == 3)
  286. {
  287. value->set(v);
  288. return true;
  289. }
  290. return false;
  291. }
  292. //static
  293. LLVector3 LLVector3::pointToBoxOffset(const LLVector3& pos,
  294. const LLVector3* box)
  295. {
  296. LLVector3 offset;
  297. for (S32 i = 0; i < 3; ++i)
  298. {
  299. if (pos[i] < box[0][i])
  300. {
  301. offset[i] = pos[i] - box[0][i];
  302. }
  303. else if (pos[i] > box[1][i])
  304. {
  305. offset[i] = pos[i] - box[1][i];
  306. }
  307. else
  308. {
  309. offset[i] = 0.f;
  310. }
  311. }
  312. return offset;
  313. }
  314. //static
  315. bool LLVector3::boxValidAndNonZero(const LLVector3* box)
  316. {
  317. return box[0].isFinite() && box[1].isFinite() &&
  318. box[0] != LLVector3::zero && box[1] != LLVector3::zero;
  319. }