diff options
Diffstat (limited to 'linden/indra/newview/llwaterpatch.h')
-rw-r--r-- | linden/indra/newview/llwaterpatch.h | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/linden/indra/newview/llwaterpatch.h b/linden/indra/newview/llwaterpatch.h new file mode 100644 index 0000000..7779d60 --- /dev/null +++ b/linden/indra/newview/llwaterpatch.h | |||
@@ -0,0 +1,316 @@ | |||
1 | /** | ||
2 | * @file llwaterpatch.h | ||
3 | * @brief LLWaterTri class header file | ||
4 | * | ||
5 | * Copyright (c) 2001-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_WATER_PATCH_H | ||
29 | #define LL_WATER_PATCH_H | ||
30 | |||
31 | #include "llmath.h" | ||
32 | #include "v3math.h" | ||
33 | #include "llroam.h" | ||
34 | |||
35 | const U8 MAX_LEVEL = 10; | ||
36 | |||
37 | class LL2Coord | ||
38 | { | ||
39 | protected: | ||
40 | S32 mX; | ||
41 | S32 mY; | ||
42 | public: | ||
43 | LL2Coord() {} | ||
44 | //LL2Coord() : mX(0), mY(0) {} | ||
45 | LL2Coord (S32 i, S32 j) : mX(i), mY(j) {} | ||
46 | LL2Coord operator+ (const LL2Coord& c) const | ||
47 | { | ||
48 | return LL2Coord(mX + c.mX, mY + c.mY); | ||
49 | } | ||
50 | LL2Coord operator* (F32 c) const | ||
51 | { | ||
52 | return LL2Coord(llround(mX * c), llround(mY * c)); | ||
53 | } | ||
54 | S32 x() const { return mX; } | ||
55 | S32 y() const { return mY; } | ||
56 | |||
57 | S32& x() { return mX; } | ||
58 | S32& y() { return mY; } | ||
59 | |||
60 | LL2Coord middle(const LL2Coord& c2) const | ||
61 | { | ||
62 | return LL2Coord((x() + c2.x()) >> 1, (y() + c2.y()) >> 1); | ||
63 | } | ||
64 | |||
65 | S32 distance2(const LL2Coord& c2) const | ||
66 | { | ||
67 | S32 dx = x() - c2.x(); | ||
68 | S32 dy = y() - c2.y(); | ||
69 | |||
70 | return dx * dx + dy * dy; | ||
71 | } | ||
72 | |||
73 | F32 distance(const LL2Coord& c2) const | ||
74 | { | ||
75 | return (F32) sqrt((F32)distance2(c2)); | ||
76 | } | ||
77 | }; | ||
78 | |||
79 | |||
80 | |||
81 | |||
82 | |||
83 | |||
84 | class LLWaterGrid; | ||
85 | |||
86 | class LLWaterTri : public LLRoamTriNode | ||
87 | { | ||
88 | protected: | ||
89 | LL2Coord mLvtx; // Left vertex | ||
90 | LL2Coord mRvtx; // Right vertex | ||
91 | LL2Coord mTvtx; // Top vertex | ||
92 | LL2Coord mMiddle; // Top vertex | ||
93 | |||
94 | F32 mSize; | ||
95 | |||
96 | BOOL mCurr; | ||
97 | BOOL mRefine; | ||
98 | |||
99 | public: | ||
100 | static LL2Coord sCam; | ||
101 | static F32 sClipFar; | ||
102 | static U32 sMaxDivLevel; | ||
103 | static U32 sMinStep; | ||
104 | |||
105 | static BOOL sCurrRound; | ||
106 | |||
107 | |||
108 | public: | ||
109 | LLWaterTri (const LL2Coord& l, const LL2Coord& r, const LL2Coord& t): | ||
110 | LLRoamTriNode(0, 0, 0), mLvtx(l), mRvtx(r), mTvtx(t), mRefine(FALSE) | ||
111 | { | ||
112 | mSize = mLvtx.distance(mRvtx) * sMinStep; | ||
113 | mCurr = sCurrRound; | ||
114 | mMiddle = mLvtx.middle(mRvtx); | ||
115 | } | ||
116 | |||
117 | LLWaterTri (U8 level = 0, S8 type = 0, LLWaterTri* par = 0); | ||
118 | |||
119 | virtual LLRoamTriNode* newLChild() | ||
120 | { | ||
121 | return new LLWaterTri(mLevel+1, -1, this); | ||
122 | } | ||
123 | virtual LLRoamTriNode* newRChild() | ||
124 | { | ||
125 | return new LLWaterTri(mLevel+1, 1, this); | ||
126 | } | ||
127 | |||
128 | virtual ~LLWaterTri() {} | ||
129 | |||
130 | const LL2Coord& Lvtx() const { return mLvtx; } | ||
131 | const LL2Coord& Rvtx() const { return mRvtx; } | ||
132 | const LL2Coord& Tvtx() const { return mTvtx; } | ||
133 | |||
134 | F32 size() const { return mSize; } | ||
135 | |||
136 | LL2Coord middleSide() const { return mMiddle; }//middle(mLvtx, mRvtx); } | ||
137 | |||
138 | void setLvtx(const LL2Coord& c) { mLvtx = c; } | ||
139 | void setRvtx(const LL2Coord& c) { mRvtx = c; } | ||
140 | void setTvtx(const LL2Coord& c) { mTvtx = c; } | ||
141 | |||
142 | void updatePassive(); | ||
143 | BOOL refine(); | ||
144 | void initForcefulRefine() | ||
145 | { | ||
146 | setUpToDate(); | ||
147 | mRefine = TRUE; | ||
148 | } | ||
149 | void flushFromQueue() { setUpToDate(); } | ||
150 | |||
151 | BOOL upToDate() const { return mCurr == sCurrRound; } | ||
152 | void setUpToDate() { mCurr = sCurrRound; } | ||
153 | void setNotUpToDate() { mCurr = !sCurrRound; } | ||
154 | static void nextRound() { sCurrRound = !sCurrRound; } | ||
155 | |||
156 | BOOL checkUpToDate() const | ||
157 | { | ||
158 | BOOL ok = leaf() ? upToDate() : | ||
159 | upToDate() && ((LLWaterTri*)Lchild())->upToDate() && ((LLWaterTri*)Rchild())->upToDate(); | ||
160 | if (!ok) | ||
161 | return ok; | ||
162 | else | ||
163 | return ok; | ||
164 | } | ||
165 | |||
166 | }; | ||
167 | |||
168 | |||
169 | |||
170 | |||
171 | class LLWaterPatch : public LLRoamPatch | ||
172 | { | ||
173 | protected: | ||
174 | LL2Coord mOrig; // Bottom left vertex | ||
175 | U32 mSize; | ||
176 | U32 mRegionWidth; | ||
177 | LLVector3 mCenter; | ||
178 | BOOL mVis; | ||
179 | |||
180 | public: | ||
181 | LLWaterPatch() : | ||
182 | LLRoamPatch(MAX_LEVEL, TRUE), mOrig(0, 0), mSize(32), mRegionWidth(256) {} | ||
183 | |||
184 | LLWaterPatch(const LL2Coord o, U32 size, U32 width, const LLVector3& center, | ||
185 | U8 max_level = MAX_LEVEL, BOOL back_slash = TRUE) : | ||
186 | LLRoamPatch(back_slash, max_level), mOrig(o), mSize(size), mRegionWidth(width), mCenter(center) | ||
187 | { createTris(); } | ||
188 | |||
189 | LLWaterPatch(S32 o1, S32 o2, U32 size, U32 width, const LLVector3& center, | ||
190 | U8 max_level = MAX_LEVEL, BOOL back_slash = TRUE) : | ||
191 | LLRoamPatch(back_slash, max_level), mOrig(o1, o2), mSize(size), mRegionWidth(width), mCenter(center) | ||
192 | { createTris(); } | ||
193 | |||
194 | |||
195 | const LL2Coord& orig() const { return mOrig; } | ||
196 | void set (S32 o1, S32 o2, U32 size, U32 width, const LLVector3& center, | ||
197 | U8 max_level = MAX_LEVEL, BOOL back_slash = TRUE) | ||
198 | { | ||
199 | deleteTris(); | ||
200 | mBackSlash = back_slash; | ||
201 | mMaxLevel = max_level; | ||
202 | mOrig.x() = o1; | ||
203 | mOrig.y() = o2; | ||
204 | mSize = size; | ||
205 | mCenter = center; | ||
206 | mRegionWidth = width; | ||
207 | mNumTris = 0; | ||
208 | createTris(); | ||
209 | } | ||
210 | |||
211 | void setMaxLevel (U8 max_level) { mMaxLevel = max_level; } | ||
212 | |||
213 | void createTris() | ||
214 | { | ||
215 | if (mBackSlash) | ||
216 | { | ||
217 | mTri[0] = new LLWaterTri(LL2Coord(mOrig.x() + mSize, mOrig.y()), | ||
218 | LL2Coord(mOrig.x(), mOrig.y() + mSize), mOrig); | ||
219 | mTri[1] = new LLWaterTri(LL2Coord(mOrig.x(), mOrig.y() + mSize), | ||
220 | LL2Coord(mOrig.x() + mSize, mOrig.y()), | ||
221 | LL2Coord(mOrig.x() + mSize, mOrig.y() + mSize)); | ||
222 | } else { | ||
223 | mTri[0] = new LLWaterTri(mOrig, | ||
224 | LL2Coord(mOrig.x() + mSize, mOrig.y() + mSize), | ||
225 | LL2Coord(mOrig.x(), mOrig.y() + mSize)); | ||
226 | mTri[1] = new LLWaterTri(LL2Coord(mOrig.x() + mSize, mOrig.y() + mSize), | ||
227 | mOrig, | ||
228 | LL2Coord(mOrig.x() + mSize, mOrig.y())); | ||
229 | } | ||
230 | setTris(); | ||
231 | ((LLWaterTri*)mTri[0])->setUpToDate(); | ||
232 | ((LLWaterTri*)mTri[1])->setUpToDate(); | ||
233 | } | ||
234 | //virtual ~LLWaterPatch() {} | ||
235 | void setInvisible() { mVis = FALSE; } | ||
236 | void setVisible() { mVis = TRUE; } | ||
237 | |||
238 | BOOL visible() const { return mVis; } | ||
239 | |||
240 | BOOL updateTree(const LLVector3 &camera_pos, const LLVector3 &look_at, const LLVector3 ®_orig) | ||
241 | { | ||
242 | const static F32 patch_rad = mRegionWidth * F_SQRT2 * 0.5f; | ||
243 | |||
244 | LLVector3 to_patch = reg_orig + mCenter - camera_pos; | ||
245 | F32 to_patch_dist = to_patch.normVec(); | ||
246 | |||
247 | if ( to_patch_dist < patch_rad) | ||
248 | { | ||
249 | setVisible(); | ||
250 | update(); | ||
251 | } else { | ||
252 | const F32 sin_min_angle = patch_rad / to_patch_dist; | ||
253 | const F32 cos_min_angle = (F32)sqrt(1.f - sin_min_angle * sin_min_angle); | ||
254 | const F32 cos_max = OO_SQRT2 * (cos_min_angle - sin_min_angle); | ||
255 | |||
256 | if (to_patch * look_at > cos_max) | ||
257 | { | ||
258 | setVisible(); | ||
259 | update(); | ||
260 | } else { | ||
261 | setInvisible(); | ||
262 | updatePassive(); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | return mVis; | ||
267 | } | ||
268 | |||
269 | BOOL updateVisibility(const LLVector3 &camera_pos, const LLVector3 &look_at, const LLVector3 ®_orig) | ||
270 | { | ||
271 | const static F32 patch_rad = mRegionWidth * F_SQRT2 * 0.5f; | ||
272 | const static U32 reg_width_half = mRegionWidth / 2; | ||
273 | //const static F32 patch_rad2 = patch_rad * patch_rad; | ||
274 | |||
275 | LLVector3 to_patch = reg_orig + mCenter - camera_pos; | ||
276 | //const F32 to_patch_dist2D2 = to_patch.mV[VX] * to_patch.mV[VX] + to_patch.mV[VY] * to_patch.mV[VY]; | ||
277 | |||
278 | if (fabs(to_patch.mV[VX]) <= reg_width_half && fabs(to_patch.mV[VY]) <= reg_width_half) | ||
279 | //if ( to_patch_dist2D2 < patch_rad2) | ||
280 | { | ||
281 | setVisible(); | ||
282 | } else { | ||
283 | F32 to_patch_dist = to_patch.normVec(); | ||
284 | //const F32 to_patch_dist = sqrt(to_patch_dist2D2 + to_patch.mV[VZ] * to_patch.mV[VZ]); | ||
285 | const F32 sin_min_angle = patch_rad / to_patch_dist; | ||
286 | if (sin_min_angle >= 1) | ||
287 | { | ||
288 | setVisible(); | ||
289 | } else { | ||
290 | const F32 cos_min_angle = (F32)sqrt(1.f - sin_min_angle * sin_min_angle); | ||
291 | const F32 cos_max = OO_SQRT2 * (cos_min_angle - sin_min_angle); | ||
292 | |||
293 | if (to_patch * look_at > cos_max) | ||
294 | { | ||
295 | setVisible(); | ||
296 | } else { | ||
297 | setInvisible(); | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | |||
302 | return mVis; | ||
303 | } | ||
304 | void checkUpToDate() const | ||
305 | { | ||
306 | for (U8 h = 0; h < 2; h++) | ||
307 | { | ||
308 | ((LLWaterTri*)left())->checkUpToDate(); | ||
309 | ((LLWaterTri*)right())->checkUpToDate(); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | }; | ||
314 | |||
315 | |||
316 | #endif | ||