diff options
Diffstat (limited to 'linden/indra/llmath/llvolume.h')
-rw-r--r-- | linden/indra/llmath/llvolume.h | 901 |
1 files changed, 901 insertions, 0 deletions
diff --git a/linden/indra/llmath/llvolume.h b/linden/indra/llmath/llvolume.h new file mode 100644 index 0000000..63981da --- /dev/null +++ b/linden/indra/llmath/llvolume.h | |||
@@ -0,0 +1,901 @@ | |||
1 | /** | ||
2 | * @file llvolume.h | ||
3 | * @brief LLVolume base class. | ||
4 | * | ||
5 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #ifndef LL_LLVOLUME_H | ||
29 | #define LL_LLVOLUME_H | ||
30 | |||
31 | #include <iostream> | ||
32 | |||
33 | class LLProfileParams; | ||
34 | class LLPathParams; | ||
35 | class LLVolumeParams; | ||
36 | class LLProfile; | ||
37 | class LLPath; | ||
38 | class LLVolumeFace; | ||
39 | class LLVolume; | ||
40 | |||
41 | #include "lldarray.h" | ||
42 | #include "lluuid.h" | ||
43 | #include "v4color.h" | ||
44 | //#include "vmath.h" | ||
45 | #include "v2math.h" | ||
46 | #include "v3math.h" | ||
47 | #include "llquaternion.h" | ||
48 | #include "llstrider.h" | ||
49 | #include "v4coloru.h" | ||
50 | #include "llmemory.h" | ||
51 | |||
52 | //============================================================================ | ||
53 | |||
54 | const S32 MIN_DETAIL_FACES = 6; | ||
55 | const S32 MIN_LOD = 0; | ||
56 | const S32 MAX_LOD = 3; | ||
57 | |||
58 | // These are defined here but are not enforced at this level, | ||
59 | // rather they are here for the convenience of code that uses | ||
60 | // the LLVolume class. | ||
61 | const F32 MIN_VOLUME_PROFILE_WIDTH = 0.05f; | ||
62 | const F32 MIN_VOLUME_PATH_WIDTH = 0.05f; | ||
63 | |||
64 | const F32 CUT_QUANTA = 0.005f; | ||
65 | const F32 SCALE_QUANTA = 0.01f; | ||
66 | const F32 SHEAR_QUANTA = 0.01f; | ||
67 | const F32 TAPER_QUANTA = 0.01f; | ||
68 | const F32 REV_QUANTA = 0.015f; | ||
69 | |||
70 | |||
71 | //============================================================================ | ||
72 | |||
73 | // useful masks | ||
74 | const LLPCode LL_PCODE_HOLLOW_MASK = 0x80; // has a thickness | ||
75 | const LLPCode LL_PCODE_SEGMENT_MASK = 0x40; // segments (1 angle) | ||
76 | const LLPCode LL_PCODE_PATCH_MASK = 0x20; // segmented segments (2 angles) | ||
77 | const LLPCode LL_PCODE_HEMI_MASK = 0x10; // half-primitives get their own type per PR's dictum | ||
78 | const LLPCode LL_PCODE_BASE_MASK = 0x0F; | ||
79 | |||
80 | // primitive shapes | ||
81 | const LLPCode LL_PCODE_CUBE = 1; | ||
82 | const LLPCode LL_PCODE_PRISM = 2; | ||
83 | const LLPCode LL_PCODE_TETRAHEDRON = 3; | ||
84 | const LLPCode LL_PCODE_PYRAMID = 4; | ||
85 | const LLPCode LL_PCODE_CYLINDER = 5; | ||
86 | const LLPCode LL_PCODE_CONE = 6; | ||
87 | const LLPCode LL_PCODE_SPHERE = 7; | ||
88 | const LLPCode LL_PCODE_TORUS = 8; | ||
89 | const LLPCode LL_PCODE_VOLUME = 9; | ||
90 | |||
91 | // surfaces | ||
92 | //const LLPCode LL_PCODE_SURFACE_TRIANGLE = 10; | ||
93 | //const LLPCode LL_PCODE_SURFACE_SQUARE = 11; | ||
94 | //const LLPCode LL_PCODE_SURFACE_DISC = 12; | ||
95 | |||
96 | const LLPCode LL_PCODE_APP = 14; // App specific pcode (for viewer/sim side only objects) | ||
97 | const LLPCode LL_PCODE_LEGACY = 15; | ||
98 | |||
99 | // Pcodes for legacy objects | ||
100 | //const LLPCode LL_PCODE_LEGACY_ATOR = 0x10 | LL_PCODE_LEGACY; // ATOR | ||
101 | const LLPCode LL_PCODE_LEGACY_AVATAR = 0x20 | LL_PCODE_LEGACY; // PLAYER | ||
102 | //const LLPCode LL_PCODE_LEGACY_BIRD = 0x30 | LL_PCODE_LEGACY; // BIRD | ||
103 | //const LLPCode LL_PCODE_LEGACY_DEMON = 0x40 | LL_PCODE_LEGACY; // DEMON | ||
104 | const LLPCode LL_PCODE_LEGACY_GRASS = 0x50 | LL_PCODE_LEGACY; // GRASS | ||
105 | const LLPCode LL_PCODE_TREE_NEW = 0x60 | LL_PCODE_LEGACY; // new trees | ||
106 | //const LLPCode LL_PCODE_LEGACY_ORACLE = 0x70 | LL_PCODE_LEGACY; // ORACLE | ||
107 | const LLPCode LL_PCODE_LEGACY_PART_SYS = 0x80 | LL_PCODE_LEGACY; // PART_SYS | ||
108 | const LLPCode LL_PCODE_LEGACY_ROCK = 0x90 | LL_PCODE_LEGACY; // ROCK | ||
109 | //const LLPCode LL_PCODE_LEGACY_SHOT = 0xA0 | LL_PCODE_LEGACY; // BASIC_SHOT | ||
110 | //const LLPCode LL_PCODE_LEGACY_SHOT_BIG = 0xB0 | LL_PCODE_LEGACY; | ||
111 | //const LLPCode LL_PCODE_LEGACY_SMOKE = 0xC0 | LL_PCODE_LEGACY; // SMOKE | ||
112 | //const LLPCode LL_PCODE_LEGACY_SPARK = 0xD0 | LL_PCODE_LEGACY;// SPARK | ||
113 | const LLPCode LL_PCODE_LEGACY_TEXT_BUBBLE = 0xE0 | LL_PCODE_LEGACY; // TEXTBUBBLE | ||
114 | const LLPCode LL_PCODE_LEGACY_TREE = 0xF0 | LL_PCODE_LEGACY; // TREE | ||
115 | |||
116 | // hemis | ||
117 | const LLPCode LL_PCODE_CYLINDER_HEMI = LL_PCODE_CYLINDER | LL_PCODE_HEMI_MASK; | ||
118 | const LLPCode LL_PCODE_CONE_HEMI = LL_PCODE_CONE | LL_PCODE_HEMI_MASK; | ||
119 | const LLPCode LL_PCODE_SPHERE_HEMI = LL_PCODE_SPHERE | LL_PCODE_HEMI_MASK; | ||
120 | const LLPCode LL_PCODE_TORUS_HEMI = LL_PCODE_TORUS | LL_PCODE_HEMI_MASK; | ||
121 | |||
122 | |||
123 | // Volumes consist of a profile at the base that is swept around | ||
124 | // a path to make a volume. | ||
125 | // The profile code | ||
126 | const U8 LL_PCODE_PROFILE_MASK = 0x0f; | ||
127 | const U8 LL_PCODE_PROFILE_MIN = 0x00; | ||
128 | const U8 LL_PCODE_PROFILE_CIRCLE = 0x00; | ||
129 | const U8 LL_PCODE_PROFILE_SQUARE = 0x01; | ||
130 | const U8 LL_PCODE_PROFILE_ISOTRI = 0x02; | ||
131 | const U8 LL_PCODE_PROFILE_EQUALTRI = 0x03; | ||
132 | const U8 LL_PCODE_PROFILE_RIGHTTRI = 0x04; | ||
133 | const U8 LL_PCODE_PROFILE_CIRCLE_HALF = 0x05; | ||
134 | const U8 LL_PCODE_PROFILE_MAX = 0x05; | ||
135 | |||
136 | // Stored in the profile byte | ||
137 | const U8 LL_PCODE_HOLE_MASK = 0xf0; | ||
138 | const U8 LL_PCODE_HOLE_MIN = 0x00; | ||
139 | const U8 LL_PCODE_HOLE_SAME = 0x00; // same as outside profile | ||
140 | const U8 LL_PCODE_HOLE_CIRCLE = 0x10; | ||
141 | const U8 LL_PCODE_HOLE_SQUARE = 0x20; | ||
142 | const U8 LL_PCODE_HOLE_TRIANGLE = 0x30; | ||
143 | const U8 LL_PCODE_HOLE_MAX = 0x03; // min/max needs to be >> 4 of real min/max | ||
144 | |||
145 | const U8 LL_PCODE_PATH_IGNORE = 0x00; | ||
146 | const U8 LL_PCODE_PATH_MIN = 0x01; // min/max needs to be >> 4 of real min/max | ||
147 | const U8 LL_PCODE_PATH_LINE = 0x10; | ||
148 | const U8 LL_PCODE_PATH_CIRCLE = 0x20; | ||
149 | const U8 LL_PCODE_PATH_CIRCLE2 = 0x30; | ||
150 | const U8 LL_PCODE_PATH_TEST = 0x40; | ||
151 | const U8 LL_PCODE_PATH_FLEXIBLE = 0x80; | ||
152 | const U8 LL_PCODE_PATH_MAX = 0x08; | ||
153 | |||
154 | //============================================================================ | ||
155 | |||
156 | // face identifiers | ||
157 | typedef U16 LLFaceID; | ||
158 | |||
159 | const LLFaceID LL_FACE_PATH_BEGIN = 0x1 << 0; | ||
160 | const LLFaceID LL_FACE_PATH_END = 0x1 << 1; | ||
161 | const LLFaceID LL_FACE_INNER_SIDE = 0x1 << 2; | ||
162 | const LLFaceID LL_FACE_PROFILE_BEGIN = 0x1 << 3; | ||
163 | const LLFaceID LL_FACE_PROFILE_END = 0x1 << 4; | ||
164 | const LLFaceID LL_FACE_OUTER_SIDE_0 = 0x1 << 5; | ||
165 | const LLFaceID LL_FACE_OUTER_SIDE_1 = 0x1 << 6; | ||
166 | const LLFaceID LL_FACE_OUTER_SIDE_2 = 0x1 << 7; | ||
167 | const LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8; | ||
168 | |||
169 | //============================================================================ | ||
170 | |||
171 | class LLProfileParams | ||
172 | { | ||
173 | public: | ||
174 | LLProfileParams() | ||
175 | { | ||
176 | mBegin = 0; | ||
177 | mEnd = 1; | ||
178 | mHollow = 0; | ||
179 | mCurveType = LL_PCODE_PROFILE_SQUARE; | ||
180 | } | ||
181 | |||
182 | LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow) | ||
183 | : mCurveType(curve), mBegin(begin), mEnd(end), mHollow(hollow) | ||
184 | { | ||
185 | } | ||
186 | |||
187 | LLProfileParams(U8 curve, U8 begin, U8 end, U8 hollow) | ||
188 | { | ||
189 | mCurveType = curve; | ||
190 | F32 temp_f32 = begin * CUT_QUANTA; | ||
191 | if (temp_f32 > 1.f) | ||
192 | { | ||
193 | temp_f32 = 1.f; | ||
194 | } | ||
195 | mBegin = temp_f32; | ||
196 | temp_f32 = end * CUT_QUANTA; | ||
197 | if (temp_f32 > 1.f) | ||
198 | { | ||
199 | temp_f32 = 1.f; | ||
200 | } | ||
201 | mEnd = 1.f - temp_f32; | ||
202 | temp_f32 = hollow * SCALE_QUANTA; | ||
203 | if (temp_f32 > 1.f) | ||
204 | { | ||
205 | temp_f32 = 1.f; | ||
206 | } | ||
207 | mHollow = temp_f32; | ||
208 | } | ||
209 | |||
210 | bool operator==(const LLProfileParams ¶ms) const; | ||
211 | bool operator!=(const LLProfileParams ¶ms) const; | ||
212 | bool operator<(const LLProfileParams ¶ms) const; | ||
213 | |||
214 | void copyParams(const LLProfileParams ¶ms); | ||
215 | |||
216 | BOOL importFile(FILE *fp); | ||
217 | BOOL exportFile(FILE *fp) const; | ||
218 | |||
219 | BOOL importLegacyStream(std::istream& input_stream); | ||
220 | BOOL exportLegacyStream(std::ostream& output_stream) const; | ||
221 | |||
222 | LLSD asLLSD() const; | ||
223 | operator LLSD() const { return asLLSD(); } | ||
224 | bool fromLLSD(LLSD& sd); | ||
225 | |||
226 | const F32& getBegin () const { return mBegin; } | ||
227 | const F32& getEnd () const { return mEnd; } | ||
228 | const F32& getHollow() const { return mHollow; } | ||
229 | const U8& getCurveType () const { return mCurveType; } | ||
230 | |||
231 | void setCurveType(const U32 type) { mCurveType = type;} | ||
232 | void setBegin(const F32 begin) { mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 1000))/1000.0f;} | ||
233 | void setEnd(const F32 end) { mEnd = (end <= 0.0f) ? 1.0f : ((int) (end * 1000))/1000.0f;} | ||
234 | void setHollow(const F32 hollow) { mHollow = ((int) (hollow * 1000))/1000.0f;} | ||
235 | |||
236 | friend std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params); | ||
237 | |||
238 | protected: | ||
239 | // Profile params | ||
240 | U8 mCurveType; | ||
241 | F32 mBegin; | ||
242 | F32 mEnd; | ||
243 | F32 mHollow; | ||
244 | |||
245 | U32 mCRC; | ||
246 | }; | ||
247 | |||
248 | inline bool LLProfileParams::operator==(const LLProfileParams ¶ms) const | ||
249 | { | ||
250 | return | ||
251 | (getCurveType() == params.getCurveType()) && | ||
252 | (getBegin() == params.getBegin()) && | ||
253 | (getEnd() == params.getEnd()) && | ||
254 | (getHollow() == params.getHollow()); | ||
255 | } | ||
256 | |||
257 | inline bool LLProfileParams::operator!=(const LLProfileParams ¶ms) const | ||
258 | { | ||
259 | return | ||
260 | (getCurveType() != params.getCurveType()) || | ||
261 | (getBegin() != params.getBegin()) || | ||
262 | (getEnd() != params.getEnd()) || | ||
263 | (getHollow() != params.getHollow()); | ||
264 | } | ||
265 | |||
266 | |||
267 | inline bool LLProfileParams::operator<(const LLProfileParams ¶ms) const | ||
268 | { | ||
269 | if (getCurveType() != params.getCurveType()) | ||
270 | { | ||
271 | return getCurveType() < params.getCurveType(); | ||
272 | } | ||
273 | else | ||
274 | if (getBegin() != params.getBegin()) | ||
275 | { | ||
276 | return getBegin() < params.getBegin(); | ||
277 | } | ||
278 | else | ||
279 | if (getEnd() != params.getEnd()) | ||
280 | { | ||
281 | return getEnd() < params.getEnd(); | ||
282 | } | ||
283 | else | ||
284 | { | ||
285 | return getHollow() < params.getHollow(); | ||
286 | } | ||
287 | } | ||
288 | |||
289 | #define U8_TO_F32(x) (F32)(*((S8 *)&x)) | ||
290 | |||
291 | class LLPathParams | ||
292 | { | ||
293 | public: | ||
294 | LLPathParams() | ||
295 | { | ||
296 | mBegin = 0; | ||
297 | mEnd = 1; | ||
298 | mScale.setVec(1,1); | ||
299 | mShear.setVec(0,0); | ||
300 | mCurveType = LL_PCODE_PATH_LINE; | ||
301 | mTwistBegin = 0; | ||
302 | mTwistEnd = 0; | ||
303 | mRadiusOffset = 0; | ||
304 | mTaper.setVec(0,0); | ||
305 | mRevolutions = 1; | ||
306 | mSkew = 0; | ||
307 | } | ||
308 | |||
309 | 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) | ||
310 | : mCurveType(curve), mBegin(begin), mEnd(end), mTwistBegin(twistbegin), mTwistEnd(twistend), | ||
311 | mRadiusOffset(radiusoffset), mRevolutions(revolutions), mSkew(skew) | ||
312 | { | ||
313 | mScale.setVec(scx,scy); | ||
314 | mShear.setVec(shx,shy); | ||
315 | mTaper.setVec(tx,ty); | ||
316 | } | ||
317 | |||
318 | LLPathParams(U8 curve, U8 begin, U8 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew) | ||
319 | { | ||
320 | mCurveType = curve; | ||
321 | mBegin = (F32)(begin * SCALE_QUANTA); | ||
322 | mEnd = (F32)(100.f - end) * SCALE_QUANTA; | ||
323 | if (mEnd > 1.f) | ||
324 | mEnd = 1.f; | ||
325 | mScale.setVec((F32) (200 - scx) * SCALE_QUANTA,(F32) (200 - scy) * SCALE_QUANTA); | ||
326 | mShear.setVec(U8_TO_F32(shx) * SHEAR_QUANTA,U8_TO_F32(shy) * SHEAR_QUANTA); | ||
327 | mTwistBegin = U8_TO_F32(twistbegin) * SCALE_QUANTA; | ||
328 | mTwistEnd = U8_TO_F32(twistend) * SCALE_QUANTA; | ||
329 | mRadiusOffset = U8_TO_F32(radiusoffset) * SCALE_QUANTA; | ||
330 | mTaper.setVec(U8_TO_F32(tx) * TAPER_QUANTA,U8_TO_F32(ty) * TAPER_QUANTA); | ||
331 | mRevolutions = ((F32)revolutions) * REV_QUANTA + 1.0f; | ||
332 | mSkew = U8_TO_F32(skew) * SCALE_QUANTA; | ||
333 | } | ||
334 | |||
335 | bool operator==(const LLPathParams ¶ms) const; | ||
336 | bool operator!=(const LLPathParams ¶ms) const; | ||
337 | bool operator<(const LLPathParams ¶ms) const; | ||
338 | |||
339 | void copyParams(const LLPathParams ¶ms); | ||
340 | |||
341 | BOOL importFile(FILE *fp); | ||
342 | BOOL exportFile(FILE *fp) const; | ||
343 | |||
344 | BOOL importLegacyStream(std::istream& input_stream); | ||
345 | BOOL exportLegacyStream(std::ostream& output_stream) const; | ||
346 | |||
347 | LLSD asLLSD() const; | ||
348 | operator LLSD() const { return asLLSD(); } | ||
349 | bool fromLLSD(LLSD& sd); | ||
350 | |||
351 | const F32& getBegin() const { return mBegin; } | ||
352 | const F32& getEnd() const { return mEnd; } | ||
353 | const LLVector2 &getScale() const { return mScale; } | ||
354 | const F32& getScaleX() const { return mScale.mV[0]; } | ||
355 | const F32& getScaleY() const { return mScale.mV[1]; } | ||
356 | const LLVector2 getBeginScale() const; | ||
357 | const LLVector2 getEndScale() const; | ||
358 | const LLVector2 &getShear() const { return mShear; } | ||
359 | const F32& getShearX() const { return mShear.mV[0]; } | ||
360 | const F32& getShearY() const { return mShear.mV[1]; } | ||
361 | const U8& getCurveType () const { return mCurveType; } | ||
362 | |||
363 | const F32& getTwistBegin() const { return mTwistBegin; } | ||
364 | const F32& getTwistEnd() const { return mTwistEnd; } | ||
365 | const F32& getTwist() const { return mTwistEnd; } // deprecated | ||
366 | const F32& getRadiusOffset() const { return mRadiusOffset; } | ||
367 | const LLVector2 &getTaper() const { return mTaper; } | ||
368 | const F32& getTaperX() const { return mTaper.mV[0]; } | ||
369 | const F32& getTaperY() const { return mTaper.mV[1]; } | ||
370 | const F32& getRevolutions() const { return mRevolutions; } | ||
371 | const F32& getSkew() const { return mSkew; } | ||
372 | |||
373 | void setCurveType(const U8 type) { mCurveType = type; } | ||
374 | void setBegin(const F32 begin) { mBegin = begin; } | ||
375 | void setEnd(const F32 end) { mEnd = end; } | ||
376 | |||
377 | void setScale(const F32 x, const F32 y) { mScale.setVec(x,y); } | ||
378 | void setScaleX(const F32 v) { mScale.mV[VX] = v; } | ||
379 | void setScaleY(const F32 v) { mScale.mV[VY] = v; } | ||
380 | void setShear(const F32 x, const F32 y) { mShear.setVec(x,y); } | ||
381 | void setShearX(const F32 v) { mShear.mV[VX] = v; } | ||
382 | void setShearY(const F32 v) { mShear.mV[VY] = v; } | ||
383 | |||
384 | void setTwistBegin(const F32 twist_begin) { mTwistBegin = twist_begin; } | ||
385 | void setTwistEnd(const F32 twist_end) { mTwistEnd = twist_end; } | ||
386 | void setTwist(const F32 twist) { setTwistEnd(twist); } // deprecated | ||
387 | void setRadiusOffset(const F32 radius_offset){ mRadiusOffset = radius_offset; } | ||
388 | void setTaper(const F32 x, const F32 y) { mTaper.setVec(x,y); } | ||
389 | void setTaperX(const F32 v) { mTaper.mV[VX] = v; } | ||
390 | void setTaperY(const F32 v) { mTaper.mV[VY] = v; } | ||
391 | void setRevolutions(const F32 revolutions) { mRevolutions = revolutions; } | ||
392 | void setSkew(const F32 skew) { mSkew = skew; } | ||
393 | |||
394 | friend std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params); | ||
395 | |||
396 | protected: | ||
397 | // Path params | ||
398 | U8 mCurveType; | ||
399 | F32 mBegin; | ||
400 | F32 mEnd; | ||
401 | LLVector2 mScale; | ||
402 | LLVector2 mShear; | ||
403 | |||
404 | F32 mTwistBegin; | ||
405 | F32 mTwistEnd; | ||
406 | F32 mRadiusOffset; | ||
407 | LLVector2 mTaper; | ||
408 | F32 mRevolutions; | ||
409 | F32 mSkew; | ||
410 | |||
411 | U32 mCRC; | ||
412 | }; | ||
413 | |||
414 | inline bool LLPathParams::operator==(const LLPathParams ¶ms) const | ||
415 | { | ||
416 | return | ||
417 | (getCurveType() == params.getCurveType()) && | ||
418 | (getScale() == params.getScale()) && | ||
419 | (getBegin() == params.getBegin()) && | ||
420 | (getEnd() == params.getEnd()) && | ||
421 | (getShear() == params.getShear()) && | ||
422 | (getTwist() == params.getTwist()) && | ||
423 | (getTwistBegin() == params.getTwistBegin()) && | ||
424 | (getRadiusOffset() == params.getRadiusOffset()) && | ||
425 | (getTaper() == params.getTaper()) && | ||
426 | (getRevolutions() == params.getRevolutions()) && | ||
427 | (getSkew() == params.getSkew()); | ||
428 | } | ||
429 | |||
430 | inline bool LLPathParams::operator!=(const LLPathParams ¶ms) const | ||
431 | { | ||
432 | return | ||
433 | (getCurveType() != params.getCurveType()) || | ||
434 | (getScale() != params.getScale()) || | ||
435 | (getBegin() != params.getBegin()) || | ||
436 | (getEnd() != params.getEnd()) || | ||
437 | (getShear() != params.getShear()) || | ||
438 | (getTwist() != params.getTwist()) || | ||
439 | (getTwistBegin() !=params.getTwistBegin()) || | ||
440 | (getRadiusOffset() != params.getRadiusOffset()) || | ||
441 | (getTaper() != params.getTaper()) || | ||
442 | (getRevolutions() != params.getRevolutions()) || | ||
443 | (getSkew() != params.getSkew()); | ||
444 | } | ||
445 | |||
446 | |||
447 | inline bool LLPathParams::operator<(const LLPathParams ¶ms) const | ||
448 | { | ||
449 | if( getCurveType() != params.getCurveType()) | ||
450 | { | ||
451 | return getCurveType() < params.getCurveType(); | ||
452 | } | ||
453 | else | ||
454 | if( getScale() != params.getScale()) | ||
455 | { | ||
456 | return getScale() < params.getScale(); | ||
457 | } | ||
458 | else | ||
459 | if( getBegin() != params.getBegin()) | ||
460 | { | ||
461 | return getBegin() < params.getBegin(); | ||
462 | } | ||
463 | else | ||
464 | if( getEnd() != params.getEnd()) | ||
465 | { | ||
466 | return getEnd() < params.getEnd(); | ||
467 | } | ||
468 | else | ||
469 | if( getShear() != params.getShear()) | ||
470 | { | ||
471 | return getShear() < params.getShear(); | ||
472 | } | ||
473 | else | ||
474 | if( getTwist() != params.getTwist()) | ||
475 | { | ||
476 | return getTwist() < params.getTwist(); | ||
477 | } | ||
478 | else | ||
479 | if( getTwistBegin() != params.getTwistBegin()) | ||
480 | { | ||
481 | return getTwistBegin() < params.getTwistBegin(); | ||
482 | } | ||
483 | else | ||
484 | if( getRadiusOffset() != params.getRadiusOffset()) | ||
485 | { | ||
486 | return getRadiusOffset() < params.getRadiusOffset(); | ||
487 | } | ||
488 | else | ||
489 | if( getTaper() != params.getTaper()) | ||
490 | { | ||
491 | return getTaper() < params.getTaper(); | ||
492 | } | ||
493 | else | ||
494 | if( getRevolutions() != params.getRevolutions()) | ||
495 | { | ||
496 | return getRevolutions() < params.getRevolutions(); | ||
497 | } | ||
498 | else | ||
499 | { | ||
500 | return getSkew() < params.getSkew(); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | typedef LLVolumeParams* LLVolumeParamsPtr; | ||
505 | typedef const LLVolumeParams* const_LLVolumeParamsPtr; | ||
506 | |||
507 | class LLVolumeParams | ||
508 | { | ||
509 | public: | ||
510 | LLVolumeParams() | ||
511 | { | ||
512 | } | ||
513 | |||
514 | LLVolumeParams(LLProfileParams &profile, LLPathParams &path) | ||
515 | : mProfileParams(profile), mPathParams(path) | ||
516 | { | ||
517 | } | ||
518 | |||
519 | bool operator==(const LLVolumeParams ¶ms) const; | ||
520 | bool operator!=(const LLVolumeParams ¶ms) const; | ||
521 | bool operator<(const LLVolumeParams ¶ms) const; | ||
522 | |||
523 | |||
524 | void copyParams(const LLVolumeParams ¶ms); | ||
525 | |||
526 | const LLProfileParams &getProfileParams() const {return mProfileParams;} | ||
527 | LLProfileParams &getProfileParams() {return mProfileParams;} | ||
528 | const LLPathParams &getPathParams() const {return mPathParams;} | ||
529 | LLPathParams &getPathParams() {return mPathParams;} | ||
530 | |||
531 | BOOL importFile(FILE *fp); | ||
532 | BOOL exportFile(FILE *fp) const; | ||
533 | |||
534 | BOOL importLegacyStream(std::istream& input_stream); | ||
535 | BOOL exportLegacyStream(std::ostream& output_stream) const; | ||
536 | |||
537 | LLSD asLLSD() const; | ||
538 | operator LLSD() const { return asLLSD(); } | ||
539 | bool fromLLSD(LLSD& sd); | ||
540 | |||
541 | bool setType(U8 profile, U8 path); | ||
542 | |||
543 | //void setBeginS(const F32 beginS) { mProfileParams.setBegin(beginS); } // range 0 to 1 | ||
544 | //void setBeginT(const F32 beginT) { mPathParams.setBegin(beginT); } // range 0 to 1 | ||
545 | //void setEndS(const F32 endS) { mProfileParams.setEnd(endS); } // range 0 to 1, must be greater than begin | ||
546 | //void setEndT(const F32 endT) { mPathParams.setEnd(endT); } // range 0 to 1, must be greater than begin | ||
547 | |||
548 | bool setBeginAndEndS(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end | ||
549 | bool setBeginAndEndT(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end | ||
550 | |||
551 | bool setHollow(const F32 hollow); // range 0 to 1 | ||
552 | bool setRatio(const F32 x) { return setRatio(x,x); } // 0 = point, 1 = same as base | ||
553 | bool setShear(const F32 x) { return setShear(x,x); } // 0 = no movement, | ||
554 | bool setRatio(const F32 x, const F32 y); // 0 = point, 1 = same as base | ||
555 | bool setShear(const F32 x, const F32 y); // 0 = no movement | ||
556 | |||
557 | bool setTwistBegin(const F32 twist_begin); // range -1 to 1 | ||
558 | bool setTwistEnd(const F32 twist_end); // range -1 to 1 | ||
559 | bool setTwist(const F32 twist) { return setTwistEnd(twist); } // deprecated | ||
560 | bool setTaper(const F32 x, const F32 y) { bool pass_x = setTaperX(x); bool pass_y = setTaperY(y); return pass_x && pass_y; } | ||
561 | bool setTaperX(const F32 v); // -1 to 1 | ||
562 | bool setTaperY(const F32 v); // -1 to 1 | ||
563 | bool setRevolutions(const F32 revolutions); // 1 to 4 | ||
564 | bool setRadiusOffset(const F32 radius_offset); | ||
565 | bool setSkew(const F32 skew); | ||
566 | |||
567 | static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, | ||
568 | U8 path_curve, F32 path_begin, F32 path_end, | ||
569 | F32 scx, F32 scy, F32 shx, F32 shy, | ||
570 | F32 twistend, F32 twistbegin, F32 radiusoffset, | ||
571 | F32 tx, F32 ty, F32 revolutions, F32 skew); | ||
572 | |||
573 | const F32& getBeginS() const { return mProfileParams.getBegin(); } | ||
574 | const F32& getBeginT() const { return mPathParams.getBegin(); } | ||
575 | const F32& getEndS() const { return mProfileParams.getEnd(); } | ||
576 | const F32& getEndT() const { return mPathParams.getEnd(); } | ||
577 | |||
578 | const F32& getHollow() const { return mProfileParams.getHollow(); } | ||
579 | const F32& getTwist() const { return mPathParams.getTwist(); } | ||
580 | const F32& getRatio() const { return mPathParams.getScaleX(); } | ||
581 | const F32& getRatioX() const { return mPathParams.getScaleX(); } | ||
582 | const F32& getRatioY() const { return mPathParams.getScaleY(); } | ||
583 | const F32& getShearX() const { return mPathParams.getShearX(); } | ||
584 | const F32& getShearY() const { return mPathParams.getShearY(); } | ||
585 | |||
586 | const F32& getTwistBegin()const { return mPathParams.getTwistBegin(); } | ||
587 | const F32& getRadiusOffset() const { return mPathParams.getRadiusOffset(); } | ||
588 | const F32& getTaper() const { return mPathParams.getTaperX(); } | ||
589 | const F32& getTaperX() const { return mPathParams.getTaperX(); } | ||
590 | const F32& getTaperY() const { return mPathParams.getTaperY(); } | ||
591 | const F32& getRevolutions() const { return mPathParams.getRevolutions(); } | ||
592 | const F32& getSkew() const { return mPathParams.getSkew(); } | ||
593 | |||
594 | BOOL isConvex() const; | ||
595 | |||
596 | // 'begin' and 'end' should be in range [0, 1] (they will be clamped) | ||
597 | // (begin, end) = (0, 1) will not change the volume | ||
598 | // (begin, end) = (0, 0.5) will reduce the volume to the first half of its profile/path (S/T) | ||
599 | void reduceS(F32 begin, F32 end); | ||
600 | void reduceT(F32 begin, F32 end); | ||
601 | |||
602 | struct compare | ||
603 | { | ||
604 | bool operator()( const const_LLVolumeParamsPtr& first, const const_LLVolumeParamsPtr& second) const | ||
605 | { | ||
606 | return (*first < *second); | ||
607 | } | ||
608 | }; | ||
609 | |||
610 | friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); | ||
611 | |||
612 | protected: | ||
613 | LLProfileParams mProfileParams; | ||
614 | LLPathParams mPathParams; | ||
615 | }; | ||
616 | |||
617 | |||
618 | class LLProfile | ||
619 | { | ||
620 | public: | ||
621 | LLProfile(const LLProfileParams ¶ms) : mParams(params) | ||
622 | { | ||
623 | mTotal = 2; | ||
624 | mTotalOut = 0; | ||
625 | mDirty = TRUE; | ||
626 | mConcave = FALSE; | ||
627 | } | ||
628 | |||
629 | ~LLProfile(); | ||
630 | |||
631 | S32 getTotal() const { return mTotal; } | ||
632 | S32 getTotalOut() const { return mTotalOut; } // Total number of outside points | ||
633 | BOOL isHollow() const { return (mParams.getHollow() > 0); } | ||
634 | BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); } | ||
635 | BOOL isOpen() const { return mOpen; } | ||
636 | void setDirty() { mDirty = TRUE; } | ||
637 | BOOL generate(BOOL path_open, F32 detail = 1.0f, S32 split = 0); | ||
638 | BOOL isConcave() const { return mConcave; } | ||
639 | public: | ||
640 | const LLProfileParams &mParams; | ||
641 | |||
642 | struct Face | ||
643 | { | ||
644 | S32 mIndex; | ||
645 | S32 mCount; | ||
646 | F32 mScaleU; | ||
647 | BOOL mCap; | ||
648 | BOOL mFlat; | ||
649 | LLFaceID mFaceID; | ||
650 | }; | ||
651 | |||
652 | std::vector<LLVector3> mProfile; | ||
653 | std::vector<LLVector2> mNormals; | ||
654 | std::vector<Face> mFaces; | ||
655 | std::vector<LLVector3> mEdgeNormals; | ||
656 | std::vector<LLVector3> mEdgeCenters; | ||
657 | F32 mMaxX; | ||
658 | F32 mMinX; | ||
659 | |||
660 | friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile); | ||
661 | |||
662 | protected: | ||
663 | void genNormals(); | ||
664 | void genNGon(S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); | ||
665 | |||
666 | Face* addHole(BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0); | ||
667 | Face* addCap (S16 faceID); | ||
668 | Face* addFace(S32 index, S32 count, F32 scaleU, S16 faceID, BOOL flat); | ||
669 | |||
670 | protected: | ||
671 | BOOL mOpen; | ||
672 | BOOL mConcave; | ||
673 | BOOL mDirty; | ||
674 | |||
675 | S32 mTotalOut; | ||
676 | S32 mTotal; | ||
677 | }; | ||
678 | |||
679 | //------------------------------------------------------------------- | ||
680 | // SWEEP/EXTRUDE PATHS | ||
681 | //------------------------------------------------------------------- | ||
682 | |||
683 | class LLPath | ||
684 | { | ||
685 | public: | ||
686 | struct PathPt | ||
687 | { | ||
688 | LLVector3 mPos; | ||
689 | LLVector2 mScale; | ||
690 | LLQuaternion mRot; | ||
691 | F32 mTexT; | ||
692 | PathPt() { mPos.setVec(0,0,0); mTexT = 0; mScale.setVec(0,0); mRot.loadIdentity(); } | ||
693 | }; | ||
694 | |||
695 | public: | ||
696 | LLPath(const LLPathParams ¶ms) : mParams(params) | ||
697 | { | ||
698 | mOpen = FALSE; | ||
699 | mDirty = TRUE; | ||
700 | mStep = 1; | ||
701 | } | ||
702 | |||
703 | virtual ~LLPath(); | ||
704 | |||
705 | void genNGon(S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); | ||
706 | virtual BOOL generate(F32 detail=1.0f, S32 split = 0); | ||
707 | |||
708 | BOOL isOpen() const { return mOpen; } | ||
709 | F32 getStep() const { return mStep; } | ||
710 | void setDirty() { mDirty = TRUE; } | ||
711 | |||
712 | S32 getPathLength() const { return (S32)mPath.size(); } | ||
713 | |||
714 | void resizePath(S32 length) { mPath.resize(length); } | ||
715 | |||
716 | friend std::ostream& operator<<(std::ostream &s, const LLPath &path); | ||
717 | |||
718 | public: | ||
719 | const LLPathParams &mParams; | ||
720 | std::vector<PathPt> mPath; | ||
721 | |||
722 | protected: | ||
723 | BOOL mOpen; | ||
724 | S32 mTotal; | ||
725 | BOOL mDirty; | ||
726 | F32 mStep; | ||
727 | }; | ||
728 | |||
729 | class LLDynamicPath : public LLPath | ||
730 | { | ||
731 | public: | ||
732 | LLDynamicPath(const LLPathParams ¶ms) : LLPath(params) { } | ||
733 | BOOL generate(F32 detail=1.0f, S32 split = 0); | ||
734 | }; | ||
735 | |||
736 | // Yet another "face" class - caches volume-specific, but not instance-specific data for faces) | ||
737 | class LLVolumeFace | ||
738 | { | ||
739 | public: | ||
740 | LLVolumeFace(); | ||
741 | BOOL create(); | ||
742 | |||
743 | class VertexData | ||
744 | { | ||
745 | public: | ||
746 | LLVector3 mPosition; | ||
747 | LLVector3 mNormal; | ||
748 | LLVector3 mBinormal; | ||
749 | LLVector2 mTexCoord; | ||
750 | }; | ||
751 | |||
752 | enum | ||
753 | { | ||
754 | SINGLE_MASK = 0x0001, | ||
755 | CAP_MASK = 0x0002, | ||
756 | END_MASK = 0x0004, | ||
757 | SIDE_MASK = 0x0008, | ||
758 | INNER_MASK = 0x0010, | ||
759 | OUTER_MASK = 0x0020, | ||
760 | HOLLOW_MASK = 0x0040, | ||
761 | OPEN_MASK = 0x0080, | ||
762 | FLAT_MASK = 0x0100, | ||
763 | TOP_MASK = 0x0200, | ||
764 | BOTTOM_MASK = 0x0400 | ||
765 | } TypeMask; | ||
766 | |||
767 | public: | ||
768 | S32 mID; | ||
769 | U32 mTypeMask; | ||
770 | LLVector3 mCenter; | ||
771 | |||
772 | // Only used for INNER/OUTER faces | ||
773 | S32 mBeginS; | ||
774 | S32 mBeginT; | ||
775 | S32 mNumS; | ||
776 | S32 mNumT; | ||
777 | |||
778 | std::vector<VertexData> mVertices; | ||
779 | std::vector<S32> mIndices; | ||
780 | std::vector<S32> mEdge; | ||
781 | LLVolume *mVolumep; // Deliberately NOT reference counted - djs 11/20/03 - otherwise would make an annoying circular reference | ||
782 | |||
783 | // Shouldn't need num_old and num_new, really - djs | ||
784 | static BOOL updateColors(LLColor4U *old_colors, const S32 num_old, const LLVolumeFace &old_face, | ||
785 | LLStrider<LLColor4U> &new_colors, const S32 num_new, const LLVolumeFace &new_face); | ||
786 | |||
787 | protected: | ||
788 | BOOL createUnCutCubeCap(); | ||
789 | BOOL createCap(); | ||
790 | BOOL createSide(); | ||
791 | }; | ||
792 | |||
793 | class LLVolume : public LLRefCount | ||
794 | { | ||
795 | friend class LLVolumeLODGroup; | ||
796 | |||
797 | private: | ||
798 | LLVolume(const LLVolume&); // Don't implement | ||
799 | ~LLVolume(); // use unref | ||
800 | |||
801 | public: | ||
802 | struct Point | ||
803 | { | ||
804 | LLVector3 mPos; | ||
805 | }; | ||
806 | |||
807 | struct FaceParams | ||
808 | { | ||
809 | LLFaceID mFaceID; | ||
810 | S32 mBeginS; | ||
811 | S32 mCountS; | ||
812 | S32 mBeginT; | ||
813 | S32 mCountT; | ||
814 | }; | ||
815 | |||
816 | LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face = FALSE, const BOOL is_unique = FALSE); | ||
817 | |||
818 | U8 getProfileType() const { return mProfilep->mParams.getCurveType(); } | ||
819 | U8 getPathType() const { return mPathp->mParams.getCurveType(); } | ||
820 | S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); } | ||
821 | |||
822 | const F32 getDetail() const { return mDetail; } | ||
823 | const LLVolumeParams & getParams() const { return mParams; } | ||
824 | LLVolumeParams getCopyOfParams() const { return mParams; } | ||
825 | const LLProfile& getProfile() const { return *mProfilep; } | ||
826 | LLPath& getPath() const { return *mPathp; } | ||
827 | const std::vector<Point>& getMesh() const { return mMesh; } | ||
828 | const LLVector3& getMeshPt(const U32 i) const { return mMesh[i].mPos; } | ||
829 | |||
830 | void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); } | ||
831 | |||
832 | void regen(); | ||
833 | |||
834 | BOOL isConvex() const; | ||
835 | BOOL isCap(S32 face); | ||
836 | BOOL isFlat(S32 face); | ||
837 | BOOL isUnique() const { return mUnique; } | ||
838 | |||
839 | S32 *getTriangleIndices(U32 &num_indices) const; | ||
840 | void generateSilhouetteVertices(std::vector<LLVector3> &vertices, std::vector<LLVector3> &normals, std::vector<S32> &segments, const LLVector3& view_vec, | ||
841 | const LLMatrix4& mat, | ||
842 | const LLMatrix3& norm_mat); | ||
843 | |||
844 | //get the face index of the face that intersects with the given line segment at the point | ||
845 | //closest to start. Moves end to the point of intersection. Returns -1 if no intersection. | ||
846 | //Line segment must be in volume space. | ||
847 | S32 lineSegmentIntersect(const LLVector3& start, LLVector3& end) const; | ||
848 | |||
849 | // The following cleans up vertices and triangles, | ||
850 | // getting rid of degenerate triangles and duplicate vertices, | ||
851 | // and allocates new arrays with the clean data. | ||
852 | static BOOL cleanupTriangleData( const S32 num_input_vertices, | ||
853 | const std::vector<Point> &input_vertices, | ||
854 | const S32 num_input_triangles, | ||
855 | S32 *input_triangles, | ||
856 | S32 &num_output_vertices, | ||
857 | LLVector3 **output_vertices, | ||
858 | S32 &num_output_triangles, | ||
859 | S32 **output_triangles); | ||
860 | LLFaceID generateFaceMask(); | ||
861 | |||
862 | BOOL isFaceMaskValid(LLFaceID face_mask); | ||
863 | static S32 mNumMeshPoints; | ||
864 | |||
865 | friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume); | ||
866 | friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep); // HACK to bypass Windoze confusion over | ||
867 | // conversion if *(LLVolume*) to LLVolume& | ||
868 | 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 | ||
869 | |||
870 | U32 mFaceMask; // bit array of which faces exist in this volume | ||
871 | LLVector3 mBounds[2]; // bounding box (center, half-height) | ||
872 | LLVector3 mLODScaleBias; // vector for biasing LOD based on scale | ||
873 | |||
874 | protected: | ||
875 | BOOL generate(); | ||
876 | void createVolumeFaces(); | ||
877 | |||
878 | protected: | ||
879 | BOOL mUnique; | ||
880 | F32 mDetail; | ||
881 | LLVolumeParams mParams; | ||
882 | LLPath *mPathp; | ||
883 | LLProfile *mProfilep; | ||
884 | std::vector<Point> mMesh; | ||
885 | |||
886 | BOOL mGenerateSingleFace; | ||
887 | S32 mNumVolumeFaces; | ||
888 | LLVolumeFace *mVolumeFaces; | ||
889 | }; | ||
890 | |||
891 | std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); | ||
892 | |||
893 | LLVector3 calc_binormal_from_triangle( | ||
894 | const LLVector3& pos0, | ||
895 | const LLVector2& tex0, | ||
896 | const LLVector3& pos1, | ||
897 | const LLVector2& tex1, | ||
898 | const LLVector3& pos2, | ||
899 | const LLVector2& tex2); | ||
900 | |||
901 | #endif | ||