PageRenderTime 174ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/llmath/llvolume.h

https://bitbucket.org/lindenlab/viewer-beta/
C Header | 1111 lines | 843 code | 187 blank | 81 comment | 66 complexity | 7662167199e69f00a002207ee3ce4bcf MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llvolume.h
  3. * @brief LLVolume base class.
  4. *
  5. * $LicenseInfo:firstyear=2002&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. #ifndef LL_LLVOLUME_H
  27. #define LL_LLVOLUME_H
  28. #include <iostream>
  29. class LLProfileParams;
  30. class LLPathParams;
  31. class LLVolumeParams;
  32. class LLProfile;
  33. class LLPath;
  34. template <class T> class LLOctreeNode;
  35. class LLVector4a;
  36. class LLVolumeFace;
  37. class LLVolume;
  38. class LLVolumeTriangle;
  39. #include "lldarray.h"
  40. #include "lluuid.h"
  41. #include "v4color.h"
  42. //#include "vmath.h"
  43. #include "v2math.h"
  44. #include "v3math.h"
  45. #include "v3dmath.h"
  46. #include "v4math.h"
  47. #include "llquaternion.h"
  48. #include "llstrider.h"
  49. #include "v4coloru.h"
  50. #include "llrefcount.h"
  51. #include "llfile.h"
  52. //============================================================================
  53. const S32 MIN_DETAIL_FACES = 6;
  54. const S32 MIN_LOD = 0;
  55. const S32 MAX_LOD = 3;
  56. // These are defined here but are not enforced at this level,
  57. // rather they are here for the convenience of code that uses
  58. // the LLVolume class.
  59. const F32 MIN_VOLUME_PROFILE_WIDTH = 0.05f;
  60. const F32 MIN_VOLUME_PATH_WIDTH = 0.05f;
  61. const F32 CUT_QUANTA = 0.00002f;
  62. const F32 SCALE_QUANTA = 0.01f;
  63. const F32 SHEAR_QUANTA = 0.01f;
  64. const F32 TAPER_QUANTA = 0.01f;
  65. const F32 REV_QUANTA = 0.015f;
  66. const F32 HOLLOW_QUANTA = 0.00002f;
  67. const S32 MAX_VOLUME_TRIANGLE_INDICES = 10000;
  68. //============================================================================
  69. // useful masks
  70. const LLPCode LL_PCODE_HOLLOW_MASK = 0x80; // has a thickness
  71. const LLPCode LL_PCODE_SEGMENT_MASK = 0x40; // segments (1 angle)
  72. const LLPCode LL_PCODE_PATCH_MASK = 0x20; // segmented segments (2 angles)
  73. const LLPCode LL_PCODE_HEMI_MASK = 0x10; // half-primitives get their own type per PR's dictum
  74. const LLPCode LL_PCODE_BASE_MASK = 0x0F;
  75. // primitive shapes
  76. const LLPCode LL_PCODE_CUBE = 1;
  77. const LLPCode LL_PCODE_PRISM = 2;
  78. const LLPCode LL_PCODE_TETRAHEDRON = 3;
  79. const LLPCode LL_PCODE_PYRAMID = 4;
  80. const LLPCode LL_PCODE_CYLINDER = 5;
  81. const LLPCode LL_PCODE_CONE = 6;
  82. const LLPCode LL_PCODE_SPHERE = 7;
  83. const LLPCode LL_PCODE_TORUS = 8;
  84. const LLPCode LL_PCODE_VOLUME = 9;
  85. // surfaces
  86. //const LLPCode LL_PCODE_SURFACE_TRIANGLE = 10;
  87. //const LLPCode LL_PCODE_SURFACE_SQUARE = 11;
  88. //const LLPCode LL_PCODE_SURFACE_DISC = 12;
  89. const LLPCode LL_PCODE_APP = 14; // App specific pcode (for viewer/sim side only objects)
  90. const LLPCode LL_PCODE_LEGACY = 15;
  91. // Pcodes for legacy objects
  92. //const LLPCode LL_PCODE_LEGACY_ATOR = 0x10 | LL_PCODE_LEGACY; // ATOR
  93. const LLPCode LL_PCODE_LEGACY_AVATAR = 0x20 | LL_PCODE_LEGACY; // PLAYER
  94. //const LLPCode LL_PCODE_LEGACY_BIRD = 0x30 | LL_PCODE_LEGACY; // BIRD
  95. //const LLPCode LL_PCODE_LEGACY_DEMON = 0x40 | LL_PCODE_LEGACY; // DEMON
  96. const LLPCode LL_PCODE_LEGACY_GRASS = 0x50 | LL_PCODE_LEGACY; // GRASS
  97. const LLPCode LL_PCODE_TREE_NEW = 0x60 | LL_PCODE_LEGACY; // new trees
  98. //const LLPCode LL_PCODE_LEGACY_ORACLE = 0x70 | LL_PCODE_LEGACY; // ORACLE
  99. const LLPCode LL_PCODE_LEGACY_PART_SYS = 0x80 | LL_PCODE_LEGACY; // PART_SYS
  100. const LLPCode LL_PCODE_LEGACY_ROCK = 0x90 | LL_PCODE_LEGACY; // ROCK
  101. //const LLPCode LL_PCODE_LEGACY_SHOT = 0xA0 | LL_PCODE_LEGACY; // BASIC_SHOT
  102. //const LLPCode LL_PCODE_LEGACY_SHOT_BIG = 0xB0 | LL_PCODE_LEGACY;
  103. //const LLPCode LL_PCODE_LEGACY_SMOKE = 0xC0 | LL_PCODE_LEGACY; // SMOKE
  104. //const LLPCode LL_PCODE_LEGACY_SPARK = 0xD0 | LL_PCODE_LEGACY;// SPARK
  105. const LLPCode LL_PCODE_LEGACY_TEXT_BUBBLE = 0xE0 | LL_PCODE_LEGACY; // TEXTBUBBLE
  106. const LLPCode LL_PCODE_LEGACY_TREE = 0xF0 | LL_PCODE_LEGACY; // TREE
  107. // hemis
  108. const LLPCode LL_PCODE_CYLINDER_HEMI = LL_PCODE_CYLINDER | LL_PCODE_HEMI_MASK;
  109. const LLPCode LL_PCODE_CONE_HEMI = LL_PCODE_CONE | LL_PCODE_HEMI_MASK;
  110. const LLPCode LL_PCODE_SPHERE_HEMI = LL_PCODE_SPHERE | LL_PCODE_HEMI_MASK;
  111. const LLPCode LL_PCODE_TORUS_HEMI = LL_PCODE_TORUS | LL_PCODE_HEMI_MASK;
  112. // Volumes consist of a profile at the base that is swept around
  113. // a path to make a volume.
  114. // The profile code
  115. const U8 LL_PCODE_PROFILE_MASK = 0x0f;
  116. const U8 LL_PCODE_PROFILE_MIN = 0x00;
  117. const U8 LL_PCODE_PROFILE_CIRCLE = 0x00;
  118. const U8 LL_PCODE_PROFILE_SQUARE = 0x01;
  119. const U8 LL_PCODE_PROFILE_ISOTRI = 0x02;
  120. const U8 LL_PCODE_PROFILE_EQUALTRI = 0x03;
  121. const U8 LL_PCODE_PROFILE_RIGHTTRI = 0x04;
  122. const U8 LL_PCODE_PROFILE_CIRCLE_HALF = 0x05;
  123. const U8 LL_PCODE_PROFILE_MAX = 0x05;
  124. // Stored in the profile byte
  125. const U8 LL_PCODE_HOLE_MASK = 0xf0;
  126. const U8 LL_PCODE_HOLE_MIN = 0x00;
  127. const U8 LL_PCODE_HOLE_SAME = 0x00; // same as outside profile
  128. const U8 LL_PCODE_HOLE_CIRCLE = 0x10;
  129. const U8 LL_PCODE_HOLE_SQUARE = 0x20;
  130. const U8 LL_PCODE_HOLE_TRIANGLE = 0x30;
  131. const U8 LL_PCODE_HOLE_MAX = 0x03; // min/max needs to be >> 4 of real min/max
  132. const U8 LL_PCODE_PATH_IGNORE = 0x00;
  133. const U8 LL_PCODE_PATH_MIN = 0x01; // min/max needs to be >> 4 of real min/max
  134. const U8 LL_PCODE_PATH_LINE = 0x10;
  135. const U8 LL_PCODE_PATH_CIRCLE = 0x20;
  136. const U8 LL_PCODE_PATH_CIRCLE2 = 0x30;
  137. const U8 LL_PCODE_PATH_TEST = 0x40;
  138. const U8 LL_PCODE_PATH_FLEXIBLE = 0x80;
  139. const U8 LL_PCODE_PATH_MAX = 0x08;
  140. //============================================================================
  141. // face identifiers
  142. typedef U16 LLFaceID;
  143. const LLFaceID LL_FACE_PATH_BEGIN = 0x1 << 0;
  144. const LLFaceID LL_FACE_PATH_END = 0x1 << 1;
  145. const LLFaceID LL_FACE_INNER_SIDE = 0x1 << 2;
  146. const LLFaceID LL_FACE_PROFILE_BEGIN = 0x1 << 3;
  147. const LLFaceID LL_FACE_PROFILE_END = 0x1 << 4;
  148. const LLFaceID LL_FACE_OUTER_SIDE_0 = 0x1 << 5;
  149. const LLFaceID LL_FACE_OUTER_SIDE_1 = 0x1 << 6;
  150. const LLFaceID LL_FACE_OUTER_SIDE_2 = 0x1 << 7;
  151. const LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8;
  152. //============================================================================
  153. // sculpt types + flags
  154. const U8 LL_SCULPT_TYPE_NONE = 0;
  155. const U8 LL_SCULPT_TYPE_SPHERE = 1;
  156. const U8 LL_SCULPT_TYPE_TORUS = 2;
  157. const U8 LL_SCULPT_TYPE_PLANE = 3;
  158. const U8 LL_SCULPT_TYPE_CYLINDER = 4;
  159. const U8 LL_SCULPT_TYPE_MESH = 5;
  160. const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
  161. LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH;
  162. const U8 LL_SCULPT_FLAG_INVERT = 64;
  163. const U8 LL_SCULPT_FLAG_MIRROR = 128;
  164. const S32 LL_SCULPT_MESH_MAX_FACES = 8;
  165. class LLProfileParams
  166. {
  167. public:
  168. LLProfileParams()
  169. : mCurveType(LL_PCODE_PROFILE_SQUARE),
  170. mBegin(0.f),
  171. mEnd(1.f),
  172. mHollow(0.f),
  173. mCRC(0)
  174. {
  175. }
  176. LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow)
  177. : mCurveType(curve),
  178. mBegin(begin),
  179. mEnd(end),
  180. mHollow(hollow),
  181. mCRC(0)
  182. {
  183. }
  184. LLProfileParams(U8 curve, U16 begin, U16 end, U16 hollow)
  185. {
  186. mCurveType = curve;
  187. F32 temp_f32 = begin * CUT_QUANTA;
  188. if (temp_f32 > 1.f)
  189. {
  190. temp_f32 = 1.f;
  191. }
  192. mBegin = temp_f32;
  193. temp_f32 = end * CUT_QUANTA;
  194. if (temp_f32 > 1.f)
  195. {
  196. temp_f32 = 1.f;
  197. }
  198. mEnd = 1.f - temp_f32;
  199. temp_f32 = hollow * HOLLOW_QUANTA;
  200. if (temp_f32 > 1.f)
  201. {
  202. temp_f32 = 1.f;
  203. }
  204. mHollow = temp_f32;
  205. mCRC = 0;
  206. }
  207. bool operator==(const LLProfileParams &params) const;
  208. bool operator!=(const LLProfileParams &params) const;
  209. bool operator<(const LLProfileParams &params) const;
  210. void copyParams(const LLProfileParams &params);
  211. BOOL importFile(LLFILE *fp);
  212. BOOL exportFile(LLFILE *fp) const;
  213. BOOL importLegacyStream(std::istream& input_stream);
  214. BOOL exportLegacyStream(std::ostream& output_stream) const;
  215. LLSD asLLSD() const;
  216. operator LLSD() const { return asLLSD(); }
  217. bool fromLLSD(LLSD& sd);
  218. const F32& getBegin () const { return mBegin; }
  219. const F32& getEnd () const { return mEnd; }
  220. const F32& getHollow() const { return mHollow; }
  221. const U8& getCurveType () const { return mCurveType; }
  222. void setCurveType(const U32 type) { mCurveType = type;}
  223. void setBegin(const F32 begin) { mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 100000))/100000.0f;}
  224. void setEnd(const F32 end) { mEnd = (end <= 0.0f) ? 1.0f : ((int) (end * 100000))/100000.0f;}
  225. void setHollow(const F32 hollow) { mHollow = ((int) (hollow * 100000))/100000.0f;}
  226. friend std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params);
  227. protected:
  228. // Profile params
  229. U8 mCurveType;
  230. F32 mBegin;
  231. F32 mEnd;
  232. F32 mHollow;
  233. U32 mCRC;
  234. };
  235. inline bool LLProfileParams::operator==(const LLProfileParams &params) const
  236. {
  237. return
  238. (getCurveType() == params.getCurveType()) &&
  239. (getBegin() == params.getBegin()) &&
  240. (getEnd() == params.getEnd()) &&
  241. (getHollow() == params.getHollow());
  242. }
  243. inline bool LLProfileParams::operator!=(const LLProfileParams &params) const
  244. {
  245. return
  246. (getCurveType() != params.getCurveType()) ||
  247. (getBegin() != params.getBegin()) ||
  248. (getEnd() != params.getEnd()) ||
  249. (getHollow() != params.getHollow());
  250. }
  251. inline bool LLProfileParams::operator<(const LLProfileParams &params) const
  252. {
  253. if (getCurveType() != params.getCurveType())
  254. {
  255. return getCurveType() < params.getCurveType();
  256. }
  257. else
  258. if (getBegin() != params.getBegin())
  259. {
  260. return getBegin() < params.getBegin();
  261. }
  262. else
  263. if (getEnd() != params.getEnd())
  264. {
  265. return getEnd() < params.getEnd();
  266. }
  267. else
  268. {
  269. return getHollow() < params.getHollow();
  270. }
  271. }
  272. #define U8_TO_F32(x) (F32)(*((S8 *)&x))
  273. class LLPathParams
  274. {
  275. public:
  276. LLPathParams()
  277. :
  278. mCurveType(LL_PCODE_PATH_LINE),
  279. mBegin(0.f),
  280. mEnd(1.f),
  281. mScale(1.f,1.f),
  282. mShear(0.f,0.f),
  283. mTwistBegin(0.f),
  284. mTwistEnd(0.f),
  285. mRadiusOffset(0.f),
  286. mTaper(0.f,0.f),
  287. mRevolutions(1.f),
  288. mSkew(0.f),
  289. mCRC(0)
  290. {
  291. }
  292. LLPathParams(U8 curve, F32 begin, F32 end, F32 scx, F32 scy, F32 shx, F32 shy, F32 twistend, F32 twistbegin, F32 radiusoffset, F32 tx, F32 ty, F32 revolutions, F32 skew)
  293. : mCurveType(curve),
  294. mBegin(begin),
  295. mEnd(end),
  296. mScale(scx,scy),
  297. mShear(shx,shy),
  298. mTwistBegin(twistbegin),
  299. mTwistEnd(twistend),
  300. mRadiusOffset(radiusoffset),
  301. mTaper(tx,ty),
  302. mRevolutions(revolutions),
  303. mSkew(skew),
  304. mCRC(0)
  305. {
  306. }
  307. LLPathParams(U8 curve, U16 begin, U16 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew)
  308. {
  309. mCurveType = curve;
  310. mBegin = (F32)(begin * CUT_QUANTA);
  311. mEnd = (F32)(100.f - end) * CUT_QUANTA;
  312. if (mEnd > 1.f)
  313. mEnd = 1.f;
  314. mScale.setVec((F32) (200 - scx) * SCALE_QUANTA,(F32) (200 - scy) * SCALE_QUANTA);
  315. mShear.setVec(U8_TO_F32(shx) * SHEAR_QUANTA,U8_TO_F32(shy) * SHEAR_QUANTA);
  316. mTwistBegin = U8_TO_F32(twistbegin) * SCALE_QUANTA;
  317. mTwistEnd = U8_TO_F32(twistend) * SCALE_QUANTA;
  318. mRadiusOffset = U8_TO_F32(radiusoffset) * SCALE_QUANTA;
  319. mTaper.setVec(U8_TO_F32(tx) * TAPER_QUANTA,U8_TO_F32(ty) * TAPER_QUANTA);
  320. mRevolutions = ((F32)revolutions) * REV_QUANTA + 1.0f;
  321. mSkew = U8_TO_F32(skew) * SCALE_QUANTA;
  322. mCRC = 0;
  323. }
  324. bool operator==(const LLPathParams &params) const;
  325. bool operator!=(const LLPathParams &params) const;
  326. bool operator<(const LLPathParams &params) const;
  327. void copyParams(const LLPathParams &params);
  328. BOOL importFile(LLFILE *fp);
  329. BOOL exportFile(LLFILE *fp) const;
  330. BOOL importLegacyStream(std::istream& input_stream);
  331. BOOL exportLegacyStream(std::ostream& output_stream) const;
  332. LLSD asLLSD() const;
  333. operator LLSD() const { return asLLSD(); }
  334. bool fromLLSD(LLSD& sd);
  335. const F32& getBegin() const { return mBegin; }
  336. const F32& getEnd() const { return mEnd; }
  337. const LLVector2 &getScale() const { return mScale; }
  338. const F32& getScaleX() const { return mScale.mV[0]; }
  339. const F32& getScaleY() const { return mScale.mV[1]; }
  340. const LLVector2 getBeginScale() const;
  341. const LLVector2 getEndScale() const;
  342. const LLVector2 &getShear() const { return mShear; }
  343. const F32& getShearX() const { return mShear.mV[0]; }
  344. const F32& getShearY() const { return mShear.mV[1]; }
  345. const U8& getCurveType () const { return mCurveType; }
  346. const F32& getTwistBegin() const { return mTwistBegin; }
  347. const F32& getTwistEnd() const { return mTwistEnd; }
  348. const F32& getTwist() const { return mTwistEnd; } // deprecated
  349. const F32& getRadiusOffset() const { return mRadiusOffset; }
  350. const LLVector2 &getTaper() const { return mTaper; }
  351. const F32& getTaperX() const { return mTaper.mV[0]; }
  352. const F32& getTaperY() const { return mTaper.mV[1]; }
  353. const F32& getRevolutions() const { return mRevolutions; }
  354. const F32& getSkew() const { return mSkew; }
  355. void setCurveType(const U8 type) { mCurveType = type; }
  356. void setBegin(const F32 begin) { mBegin = begin; }
  357. void setEnd(const F32 end) { mEnd = end; }
  358. void setScale(const F32 x, const F32 y) { mScale.setVec(x,y); }
  359. void setScaleX(const F32 v) { mScale.mV[VX] = v; }
  360. void setScaleY(const F32 v) { mScale.mV[VY] = v; }
  361. void setShear(const F32 x, const F32 y) { mShear.setVec(x,y); }
  362. void setShearX(const F32 v) { mShear.mV[VX] = v; }
  363. void setShearY(const F32 v) { mShear.mV[VY] = v; }
  364. void setTwistBegin(const F32 twist_begin) { mTwistBegin = twist_begin; }
  365. void setTwistEnd(const F32 twist_end) { mTwistEnd = twist_end; }
  366. void setTwist(const F32 twist) { setTwistEnd(twist); } // deprecated
  367. void setRadiusOffset(const F32 radius_offset){ mRadiusOffset = radius_offset; }
  368. void setTaper(const F32 x, const F32 y) { mTaper.setVec(x,y); }
  369. void setTaperX(const F32 v) { mTaper.mV[VX] = v; }
  370. void setTaperY(const F32 v) { mTaper.mV[VY] = v; }
  371. void setRevolutions(const F32 revolutions) { mRevolutions = revolutions; }
  372. void setSkew(const F32 skew) { mSkew = skew; }
  373. friend std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params);
  374. protected:
  375. // Path params
  376. U8 mCurveType;
  377. F32 mBegin;
  378. F32 mEnd;
  379. LLVector2 mScale;
  380. LLVector2 mShear;
  381. F32 mTwistBegin;
  382. F32 mTwistEnd;
  383. F32 mRadiusOffset;
  384. LLVector2 mTaper;
  385. F32 mRevolutions;
  386. F32 mSkew;
  387. U32 mCRC;
  388. };
  389. inline bool LLPathParams::operator==(const LLPathParams &params) const
  390. {
  391. return
  392. (getCurveType() == params.getCurveType()) &&
  393. (getScale() == params.getScale()) &&
  394. (getBegin() == params.getBegin()) &&
  395. (getEnd() == params.getEnd()) &&
  396. (getShear() == params.getShear()) &&
  397. (getTwist() == params.getTwist()) &&
  398. (getTwistBegin() == params.getTwistBegin()) &&
  399. (getRadiusOffset() == params.getRadiusOffset()) &&
  400. (getTaper() == params.getTaper()) &&
  401. (getRevolutions() == params.getRevolutions()) &&
  402. (getSkew() == params.getSkew());
  403. }
  404. inline bool LLPathParams::operator!=(const LLPathParams &params) const
  405. {
  406. return
  407. (getCurveType() != params.getCurveType()) ||
  408. (getScale() != params.getScale()) ||
  409. (getBegin() != params.getBegin()) ||
  410. (getEnd() != params.getEnd()) ||
  411. (getShear() != params.getShear()) ||
  412. (getTwist() != params.getTwist()) ||
  413. (getTwistBegin() !=params.getTwistBegin()) ||
  414. (getRadiusOffset() != params.getRadiusOffset()) ||
  415. (getTaper() != params.getTaper()) ||
  416. (getRevolutions() != params.getRevolutions()) ||
  417. (getSkew() != params.getSkew());
  418. }
  419. inline bool LLPathParams::operator<(const LLPathParams &params) const
  420. {
  421. if( getCurveType() != params.getCurveType())
  422. {
  423. return getCurveType() < params.getCurveType();
  424. }
  425. else
  426. if( getScale() != params.getScale())
  427. {
  428. return getScale() < params.getScale();
  429. }
  430. else
  431. if( getBegin() != params.getBegin())
  432. {
  433. return getBegin() < params.getBegin();
  434. }
  435. else
  436. if( getEnd() != params.getEnd())
  437. {
  438. return getEnd() < params.getEnd();
  439. }
  440. else
  441. if( getShear() != params.getShear())
  442. {
  443. return getShear() < params.getShear();
  444. }
  445. else
  446. if( getTwist() != params.getTwist())
  447. {
  448. return getTwist() < params.getTwist();
  449. }
  450. else
  451. if( getTwistBegin() != params.getTwistBegin())
  452. {
  453. return getTwistBegin() < params.getTwistBegin();
  454. }
  455. else
  456. if( getRadiusOffset() != params.getRadiusOffset())
  457. {
  458. return getRadiusOffset() < params.getRadiusOffset();
  459. }
  460. else
  461. if( getTaper() != params.getTaper())
  462. {
  463. return getTaper() < params.getTaper();
  464. }
  465. else
  466. if( getRevolutions() != params.getRevolutions())
  467. {
  468. return getRevolutions() < params.getRevolutions();
  469. }
  470. else
  471. {
  472. return getSkew() < params.getSkew();
  473. }
  474. }
  475. typedef LLVolumeParams* LLVolumeParamsPtr;
  476. typedef const LLVolumeParams* const_LLVolumeParamsPtr;
  477. class LLVolumeParams
  478. {
  479. public:
  480. LLVolumeParams()
  481. : mSculptType(LL_SCULPT_TYPE_NONE)
  482. {
  483. }
  484. LLVolumeParams(LLProfileParams &profile, LLPathParams &path,
  485. LLUUID sculpt_id = LLUUID::null, U8 sculpt_type = LL_SCULPT_TYPE_NONE)
  486. : mProfileParams(profile), mPathParams(path), mSculptID(sculpt_id), mSculptType(sculpt_type)
  487. {
  488. }
  489. bool operator==(const LLVolumeParams &params) const;
  490. bool operator!=(const LLVolumeParams &params) const;
  491. bool operator<(const LLVolumeParams &params) const;
  492. void copyParams(const LLVolumeParams &params);
  493. const LLProfileParams &getProfileParams() const {return mProfileParams;}
  494. LLProfileParams &getProfileParams() {return mProfileParams;}
  495. const LLPathParams &getPathParams() const {return mPathParams;}
  496. LLPathParams &getPathParams() {return mPathParams;}
  497. BOOL importFile(LLFILE *fp);
  498. BOOL exportFile(LLFILE *fp) const;
  499. BOOL importLegacyStream(std::istream& input_stream);
  500. BOOL exportLegacyStream(std::ostream& output_stream) const;
  501. LLSD sculptAsLLSD() const;
  502. bool sculptFromLLSD(LLSD& sd);
  503. LLSD asLLSD() const;
  504. operator LLSD() const { return asLLSD(); }
  505. bool fromLLSD(LLSD& sd);
  506. bool setType(U8 profile, U8 path);
  507. //void setBeginS(const F32 beginS) { mProfileParams.setBegin(beginS); } // range 0 to 1
  508. //void setBeginT(const F32 beginT) { mPathParams.setBegin(beginT); } // range 0 to 1
  509. //void setEndS(const F32 endS) { mProfileParams.setEnd(endS); } // range 0 to 1, must be greater than begin
  510. //void setEndT(const F32 endT) { mPathParams.setEnd(endT); } // range 0 to 1, must be greater than begin
  511. bool setBeginAndEndS(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end
  512. bool setBeginAndEndT(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end
  513. bool setHollow(const F32 hollow); // range 0 to 1
  514. bool setRatio(const F32 x) { return setRatio(x,x); } // 0 = point, 1 = same as base
  515. bool setShear(const F32 x) { return setShear(x,x); } // 0 = no movement,
  516. bool setRatio(const F32 x, const F32 y); // 0 = point, 1 = same as base
  517. bool setShear(const F32 x, const F32 y); // 0 = no movement
  518. bool setTwistBegin(const F32 twist_begin); // range -1 to 1
  519. bool setTwistEnd(const F32 twist_end); // range -1 to 1
  520. bool setTwist(const F32 twist) { return setTwistEnd(twist); } // deprecated
  521. bool setTaper(const F32 x, const F32 y) { bool pass_x = setTaperX(x); bool pass_y = setTaperY(y); return pass_x && pass_y; }
  522. bool setTaperX(const F32 v); // -1 to 1
  523. bool setTaperY(const F32 v); // -1 to 1
  524. bool setRevolutions(const F32 revolutions); // 1 to 4
  525. bool setRadiusOffset(const F32 radius_offset);
  526. bool setSkew(const F32 skew);
  527. bool setSculptID(const LLUUID sculpt_id, U8 sculpt_type);
  528. static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow,
  529. U8 path_curve, F32 path_begin, F32 path_end,
  530. F32 scx, F32 scy, F32 shx, F32 shy,
  531. F32 twistend, F32 twistbegin, F32 radiusoffset,
  532. F32 tx, F32 ty, F32 revolutions, F32 skew);
  533. const F32& getBeginS() const { return mProfileParams.getBegin(); }
  534. const F32& getBeginT() const { return mPathParams.getBegin(); }
  535. const F32& getEndS() const { return mProfileParams.getEnd(); }
  536. const F32& getEndT() const { return mPathParams.getEnd(); }
  537. const F32& getHollow() const { return mProfileParams.getHollow(); }
  538. const F32& getTwist() const { return mPathParams.getTwist(); }
  539. const F32& getRatio() const { return mPathParams.getScaleX(); }
  540. const F32& getRatioX() const { return mPathParams.getScaleX(); }
  541. const F32& getRatioY() const { return mPathParams.getScaleY(); }
  542. const F32& getShearX() const { return mPathParams.getShearX(); }
  543. const F32& getShearY() const { return mPathParams.getShearY(); }
  544. const F32& getTwistBegin()const { return mPathParams.getTwistBegin(); }
  545. const F32& getRadiusOffset() const { return mPathParams.getRadiusOffset(); }
  546. const F32& getTaper() const { return mPathParams.getTaperX(); }
  547. const F32& getTaperX() const { return mPathParams.getTaperX(); }
  548. const F32& getTaperY() const { return mPathParams.getTaperY(); }
  549. const F32& getRevolutions() const { return mPathParams.getRevolutions(); }
  550. const F32& getSkew() const { return mPathParams.getSkew(); }
  551. const LLUUID& getSculptID() const { return mSculptID; }
  552. const U8& getSculptType() const { return mSculptType; }
  553. bool isSculpt() const;
  554. bool isMeshSculpt() const;
  555. BOOL isConvex() const;
  556. // 'begin' and 'end' should be in range [0, 1] (they will be clamped)
  557. // (begin, end) = (0, 1) will not change the volume
  558. // (begin, end) = (0, 0.5) will reduce the volume to the first half of its profile/path (S/T)
  559. void reduceS(F32 begin, F32 end);
  560. void reduceT(F32 begin, F32 end);
  561. struct compare
  562. {
  563. bool operator()( const const_LLVolumeParamsPtr& first, const const_LLVolumeParamsPtr& second) const
  564. {
  565. return (*first < *second);
  566. }
  567. };
  568. friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
  569. // debug helper functions
  570. void setCube();
  571. protected:
  572. LLProfileParams mProfileParams;
  573. LLPathParams mPathParams;
  574. LLUUID mSculptID;
  575. U8 mSculptType;
  576. };
  577. class LLProfile
  578. {
  579. public:
  580. LLProfile()
  581. : mOpen(FALSE),
  582. mConcave(FALSE),
  583. mDirty(TRUE),
  584. mTotalOut(0),
  585. mTotal(2)
  586. {
  587. }
  588. ~LLProfile();
  589. S32 getTotal() const { return mTotal; }
  590. S32 getTotalOut() const { return mTotalOut; } // Total number of outside points
  591. BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); }
  592. BOOL isOpen() const { return mOpen; }
  593. void setDirty() { mDirty = TRUE; }
  594. static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
  595. BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
  596. BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
  597. BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
  598. BOOL isConcave() const { return mConcave; }
  599. public:
  600. struct Face
  601. {
  602. S32 mIndex;
  603. S32 mCount;
  604. F32 mScaleU;
  605. BOOL mCap;
  606. BOOL mFlat;
  607. LLFaceID mFaceID;
  608. };
  609. std::vector<LLVector3> mProfile;
  610. std::vector<LLVector2> mNormals;
  611. std::vector<Face> mFaces;
  612. std::vector<LLVector3> mEdgeNormals;
  613. std::vector<LLVector3> mEdgeCenters;
  614. friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile);
  615. protected:
  616. void genNormals(const LLProfileParams& params);
  617. static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
  618. void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
  619. Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
  620. Face* addCap (S16 faceID);
  621. Face* addFace(S32 index, S32 count, F32 scaleU, S16 faceID, BOOL flat);
  622. protected:
  623. BOOL mOpen;
  624. BOOL mConcave;
  625. BOOL mDirty;
  626. S32 mTotalOut;
  627. S32 mTotal;
  628. };
  629. //-------------------------------------------------------------------
  630. // SWEEP/EXTRUDE PATHS
  631. //-------------------------------------------------------------------
  632. class LLPath
  633. {
  634. public:
  635. struct PathPt
  636. {
  637. LLVector3 mPos;
  638. LLVector2 mScale;
  639. LLQuaternion mRot;
  640. F32 mTexT;
  641. PathPt() { mPos.setVec(0,0,0); mTexT = 0; mScale.setVec(0,0); mRot.loadIdentity(); }
  642. };
  643. public:
  644. LLPath()
  645. : mOpen(FALSE),
  646. mTotal(0),
  647. mDirty(TRUE),
  648. mStep(1)
  649. {
  650. }
  651. virtual ~LLPath();
  652. static S32 getNumPoints(const LLPathParams& params, F32 detail);
  653. static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
  654. void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
  655. virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
  656. BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
  657. BOOL isOpen() const { return mOpen; }
  658. F32 getStep() const { return mStep; }
  659. void setDirty() { mDirty = TRUE; }
  660. S32 getPathLength() const { return (S32)mPath.size(); }
  661. void resizePath(S32 length) { mPath.resize(length); }
  662. friend std::ostream& operator<<(std::ostream &s, const LLPath &path);
  663. public:
  664. std::vector<PathPt> mPath;
  665. protected:
  666. BOOL mOpen;
  667. S32 mTotal;
  668. BOOL mDirty;
  669. F32 mStep;
  670. };
  671. class LLDynamicPath : public LLPath
  672. {
  673. public:
  674. LLDynamicPath() : LLPath() { }
  675. /*virtual*/ BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
  676. BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
  677. };
  678. // Yet another "face" class - caches volume-specific, but not instance-specific data for faces)
  679. class LLVolumeFace
  680. {
  681. public:
  682. class VertexData
  683. {
  684. enum
  685. {
  686. POSITION = 0,
  687. NORMAL = 1
  688. };
  689. private:
  690. void init();
  691. public:
  692. VertexData();
  693. VertexData(const VertexData& rhs);
  694. const VertexData& operator=(const VertexData& rhs);
  695. ~VertexData();
  696. LLVector4a& getPosition();
  697. LLVector4a& getNormal();
  698. const LLVector4a& getPosition() const;
  699. const LLVector4a& getNormal() const;
  700. void setPosition(const LLVector4a& pos);
  701. void setNormal(const LLVector4a& norm);
  702. LLVector2 mTexCoord;
  703. bool operator<(const VertexData& rhs) const;
  704. bool operator==(const VertexData& rhs) const;
  705. bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const;
  706. private:
  707. LLVector4a* mData;
  708. };
  709. LLVolumeFace();
  710. LLVolumeFace(const LLVolumeFace& src);
  711. LLVolumeFace& operator=(const LLVolumeFace& rhs);
  712. ~LLVolumeFace();
  713. private:
  714. void freeData();
  715. public:
  716. BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
  717. void createBinormals();
  718. void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform);
  719. void resizeVertices(S32 num_verts);
  720. void allocateBinormals(S32 num_verts);
  721. void allocateWeights(S32 num_verts);
  722. void resizeIndices(S32 num_indices);
  723. void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
  724. void pushVertex(const VertexData& cv);
  725. void pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc);
  726. void pushIndex(const U16& idx);
  727. void swapData(LLVolumeFace& rhs);
  728. void getVertexData(U16 indx, LLVolumeFace::VertexData& cv);
  729. class VertexMapData : public LLVolumeFace::VertexData
  730. {
  731. public:
  732. U16 mIndex;
  733. bool operator==(const LLVolumeFace::VertexData& rhs) const;
  734. struct ComparePosition
  735. {
  736. bool operator()(const LLVector3& a, const LLVector3& b) const;
  737. };
  738. typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap;
  739. };
  740. void optimize(F32 angle_cutoff = 2.f);
  741. void cacheOptimize();
  742. void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
  743. enum
  744. {
  745. SINGLE_MASK = 0x0001,
  746. CAP_MASK = 0x0002,
  747. END_MASK = 0x0004,
  748. SIDE_MASK = 0x0008,
  749. INNER_MASK = 0x0010,
  750. OUTER_MASK = 0x0020,
  751. HOLLOW_MASK = 0x0040,
  752. OPEN_MASK = 0x0080,
  753. FLAT_MASK = 0x0100,
  754. TOP_MASK = 0x0200,
  755. BOTTOM_MASK = 0x0400
  756. };
  757. public:
  758. S32 mID;
  759. U32 mTypeMask;
  760. // Only used for INNER/OUTER faces
  761. S32 mBeginS;
  762. S32 mBeginT;
  763. S32 mNumS;
  764. S32 mNumT;
  765. LLVector4a* mExtents; //minimum and maximum point of face
  766. LLVector4a* mCenter;
  767. LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.
  768. S32 mNumVertices;
  769. S32 mNumIndices;
  770. LLVector4a* mPositions;
  771. LLVector4a* mNormals;
  772. LLVector4a* mBinormals;
  773. LLVector2* mTexCoords;
  774. U16* mIndices;
  775. std::vector<S32> mEdge;
  776. //list of skin weights for rigged volumes
  777. // format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight>
  778. // mWeights.size() should be empty or match mVertices.size()
  779. LLVector4a* mWeights;
  780. LLOctreeNode<LLVolumeTriangle>* mOctree;
  781. private:
  782. BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
  783. BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
  784. BOOL createSide(LLVolume* volume, BOOL partial_build = FALSE);
  785. };
  786. class LLVolume : public LLRefCount
  787. {
  788. friend class LLVolumeLODGroup;
  789. protected:
  790. ~LLVolume(); // use unref
  791. public:
  792. struct Point
  793. {
  794. LLVector3 mPos;
  795. };
  796. struct FaceParams
  797. {
  798. LLFaceID mFaceID;
  799. S32 mBeginS;
  800. S32 mCountS;
  801. S32 mBeginT;
  802. S32 mCountT;
  803. };
  804. LLVolume(const LLVolumeParams &params, const F32 detail, const BOOL generate_single_face = FALSE, const BOOL is_unique = FALSE);
  805. U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); }
  806. U8 getPathType() const { return mParams.getPathParams().getCurveType(); }
  807. S32 getNumFaces() const;
  808. S32 getNumVolumeFaces() const { return mVolumeFaces.size(); }
  809. F32 getDetail() const { return mDetail; }
  810. const LLVolumeParams& getParams() const { return mParams; }
  811. LLVolumeParams getCopyOfParams() const { return mParams; }
  812. const LLProfile& getProfile() const { return *mProfilep; }
  813. LLPath& getPath() const { return *mPathp; }
  814. void resizePath(S32 length);
  815. const std::vector<Point>& getMesh() const { return mMesh; }
  816. const LLVector3& getMeshPt(const U32 i) const { return mMesh[i].mPos; }
  817. void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); }
  818. void regen();
  819. void genBinormals(S32 face);
  820. BOOL isConvex() const;
  821. BOOL isCap(S32 face);
  822. BOOL isFlat(S32 face);
  823. BOOL isUnique() const { return mUnique; }
  824. S32 getSculptLevel() const { return mSculptLevel; }
  825. void setSculptLevel(S32 level) { mSculptLevel = level; }
  826. S32 *getTriangleIndices(U32 &num_indices) const;
  827. // returns number of triangle indeces required for path/profile mesh
  828. S32 getNumTriangleIndices() const;
  829. static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
  830. S32 getNumTriangles(S32* vcount = NULL) const;
  831. void generateSilhouetteVertices(std::vector<LLVector3> &vertices,
  832. std::vector<LLVector3> &normals,
  833. const LLVector3& view_vec,
  834. const LLMatrix4& mat,
  835. const LLMatrix3& norm_mat,
  836. S32 face_index);
  837. //get the face index of the face that intersects with the given line segment at the point
  838. //closest to start. Moves end to the point of intersection. Returns -1 if no intersection.
  839. //Line segment must be in volume space.
  840. S32 lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
  841. S32 face = -1, // which face to check, -1 = ALL_SIDES
  842. LLVector3* intersection = NULL, // return the intersection point
  843. LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
  844. LLVector3* normal = NULL, // return the surface normal at the intersection point
  845. LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point
  846. );
  847. S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end,
  848. S32 face = 1,
  849. LLVector3* intersection = NULL,
  850. LLVector2* tex_coord = NULL,
  851. LLVector3* normal = NULL,
  852. LLVector3* bi_normal = NULL);
  853. // The following cleans up vertices and triangles,
  854. // getting rid of degenerate triangles and duplicate vertices,
  855. // and allocates new arrays with the clean data.
  856. static BOOL cleanupTriangleData( const S32 num_input_vertices,
  857. const std::vector<Point> &input_vertices,
  858. const S32 num_input_triangles,
  859. S32 *input_triangles,
  860. S32 &num_output_vertices,
  861. LLVector3 **output_vertices,
  862. S32 &num_output_triangles,
  863. S32 **output_triangles);
  864. LLFaceID generateFaceMask();
  865. BOOL isFaceMaskValid(LLFaceID face_mask);
  866. static S32 sNumMeshPoints;
  867. friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume);
  868. friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep); // HACK to bypass Windoze confusion over
  869. // conversion if *(LLVolume*) to LLVolume&
  870. const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
  871. U32 mFaceMask; // bit array of which faces exist in this volume
  872. LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
  873. void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
  874. void copyVolumeFaces(const LLVolume* volume);
  875. void cacheOptimize();
  876. private:
  877. void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
  878. F32 sculptGetSurfaceArea();
  879. void sculptGeneratePlaceholder();
  880. void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t);
  881. protected:
  882. BOOL generate();
  883. void createVolumeFaces();
  884. public:
  885. virtual bool unpackVolumeFaces(std::istream& is, S32 size);
  886. virtual void setMeshAssetLoaded(BOOL loaded);
  887. virtual BOOL isMeshAssetLoaded();
  888. protected:
  889. BOOL mUnique;
  890. F32 mDetail;
  891. S32 mSculptLevel;
  892. BOOL mIsMeshAssetLoaded;
  893. LLVolumeParams mParams;
  894. LLPath *mPathp;
  895. LLProfile *mProfilep;
  896. std::vector<Point> mMesh;
  897. BOOL mGenerateSingleFace;
  898. typedef std::vector<LLVolumeFace> face_list_t;
  899. face_list_t mVolumeFaces;
  900. public:
  901. LLVector4a* mHullPoints;
  902. U16* mHullIndices;
  903. S32 mNumHullPoints;
  904. S32 mNumHullIndices;
  905. };
  906. std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
  907. void calc_binormal_from_triangle(
  908. LLVector4a& binormal,
  909. const LLVector4a& pos0,
  910. const LLVector2& tex0,
  911. const LLVector4a& pos1,
  912. const LLVector2& tex1,
  913. const LLVector4a& pos2,
  914. const LLVector2& tex2);
  915. BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);
  916. BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size);
  917. BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size);
  918. BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir,
  919. F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided);
  920. BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,
  921. F32& intersection_a, F32& intersection_b, F32& intersection_t);
  922. BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir,
  923. F32& intersection_a, F32& intersection_b, F32& intersection_t);
  924. #endif