diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llmath/llcamera.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llmath/llcamera.cpp')
-rw-r--r-- | linden/indra/llmath/llcamera.cpp | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/linden/indra/llmath/llcamera.cpp b/linden/indra/llmath/llcamera.cpp new file mode 100644 index 0000000..13666ba --- /dev/null +++ b/linden/indra/llmath/llcamera.cpp | |||
@@ -0,0 +1,610 @@ | |||
1 | /** | ||
2 | * @file llcamera.cpp | ||
3 | * @brief Implementation of the LLCamera class. | ||
4 | * | ||
5 | * Copyright (c) 2000-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 | #include "linden_common.h" | ||
29 | |||
30 | #include "llmath.h" | ||
31 | #include "llcamera.h" | ||
32 | |||
33 | // ---------------- Constructors and destructors ---------------- | ||
34 | |||
35 | LLCamera::LLCamera() : | ||
36 | LLCoordFrame(), | ||
37 | mView(DEFAULT_FIELD_OF_VIEW), | ||
38 | mAspect(DEFAULT_ASPECT_RATIO), | ||
39 | mViewHeightInPixels( -1 ), // invalid height | ||
40 | mNearPlane(DEFAULT_NEAR_PLANE), | ||
41 | mFarPlane(DEFAULT_FAR_PLANE), | ||
42 | mFixedDistance(-1.f) | ||
43 | { | ||
44 | calculateFrustumPlanes(); | ||
45 | } | ||
46 | |||
47 | |||
48 | LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) : | ||
49 | LLCoordFrame(), | ||
50 | mView(z_field_of_view), | ||
51 | mAspect(aspect_ratio), | ||
52 | mViewHeightInPixels(view_height_in_pixels), | ||
53 | mNearPlane(near_plane), | ||
54 | mFarPlane(far_plane), | ||
55 | mFixedDistance(-1.f) | ||
56 | { | ||
57 | if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; } | ||
58 | else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; } | ||
59 | |||
60 | if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; } | ||
61 | else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; } | ||
62 | |||
63 | if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; } | ||
64 | else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; } | ||
65 | |||
66 | if (mFarPlane < 0) { mFarPlane = DEFAULT_FAR_PLANE; } | ||
67 | else if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; } | ||
68 | else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; } | ||
69 | |||
70 | calculateFrustumPlanes(); | ||
71 | } | ||
72 | |||
73 | |||
74 | |||
75 | // ---------------- LLCamera::setFoo() member functions ---------------- | ||
76 | |||
77 | void LLCamera::setView(F32 field_of_view) | ||
78 | { | ||
79 | mView = field_of_view; | ||
80 | if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; } | ||
81 | else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; } | ||
82 | calculateFrustumPlanes(); | ||
83 | } | ||
84 | |||
85 | void LLCamera::setViewHeightInPixels(S32 height) | ||
86 | { | ||
87 | mViewHeightInPixels = height; | ||
88 | |||
89 | // Don't really need to do this, but update the pixel meter ratio with it. | ||
90 | calculateFrustumPlanes(); | ||
91 | } | ||
92 | |||
93 | void LLCamera::setAspect(F32 aspect_ratio) | ||
94 | { | ||
95 | mAspect = aspect_ratio; | ||
96 | if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; } | ||
97 | else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; } | ||
98 | calculateFrustumPlanes(); | ||
99 | } | ||
100 | |||
101 | |||
102 | void LLCamera::setNear(F32 near_plane) | ||
103 | { | ||
104 | mNearPlane = near_plane; | ||
105 | if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; } | ||
106 | else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; } | ||
107 | calculateFrustumPlanes(); | ||
108 | } | ||
109 | |||
110 | |||
111 | void LLCamera::setFar(F32 far_plane) | ||
112 | { | ||
113 | mFarPlane = far_plane; | ||
114 | if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; } | ||
115 | else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; } | ||
116 | calculateFrustumPlanes(); | ||
117 | } | ||
118 | |||
119 | |||
120 | // ---------------- read/write to buffer ---------------- | ||
121 | |||
122 | size_t LLCamera::writeFrustumToBuffer(char *buffer) const | ||
123 | { | ||
124 | memcpy(buffer, &mView, sizeof(F32)); | ||
125 | buffer += sizeof(F32); | ||
126 | memcpy(buffer, &mAspect, sizeof(F32)); | ||
127 | buffer += sizeof(F32); | ||
128 | memcpy(buffer, &mNearPlane, sizeof(F32)); | ||
129 | buffer += sizeof(F32); | ||
130 | memcpy(buffer, &mFarPlane, sizeof(F32)); | ||
131 | return 4*sizeof(F32); | ||
132 | } | ||
133 | |||
134 | size_t LLCamera::readFrustumFromBuffer(const char *buffer) | ||
135 | { | ||
136 | memcpy(&mView, buffer, sizeof(F32)); | ||
137 | buffer += sizeof(F32); | ||
138 | memcpy(&mAspect, buffer, sizeof(F32)); | ||
139 | buffer += sizeof(F32); | ||
140 | memcpy(&mNearPlane, buffer, sizeof(F32)); | ||
141 | buffer += sizeof(F32); | ||
142 | memcpy(&mFarPlane, buffer, sizeof(F32)); | ||
143 | return 4*sizeof(F32); | ||
144 | } | ||
145 | |||
146 | |||
147 | // ---------------- test methods ---------------- | ||
148 | |||
149 | int LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius) | ||
150 | { | ||
151 | static const LLVector3 scaler[] = { | ||
152 | LLVector3(-1,-1,-1), | ||
153 | LLVector3( 1,-1,-1), | ||
154 | LLVector3(-1, 1,-1), | ||
155 | LLVector3( 1, 1,-1), | ||
156 | LLVector3(-1,-1, 1), | ||
157 | LLVector3( 1,-1, 1), | ||
158 | LLVector3(-1, 1, 1), | ||
159 | LLVector3( 1, 1, 1) | ||
160 | }; | ||
161 | |||
162 | U8 mask = 0; | ||
163 | S32 result = 2; | ||
164 | |||
165 | for (int i = 0; i < 6; i++) | ||
166 | { | ||
167 | mask = mAgentPlaneMask[i]; | ||
168 | LLPlane p = mAgentPlanes[i]; | ||
169 | LLVector3 n = LLVector3(p); | ||
170 | float d = p.mV[3]; | ||
171 | LLVector3 rscale = radius.scaledVec(scaler[mask]); | ||
172 | |||
173 | LLVector3 minp = center - rscale; | ||
174 | LLVector3 maxp = center + rscale; | ||
175 | |||
176 | if (n * minp > -d) | ||
177 | { | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | if (n * maxp > -d) | ||
182 | { | ||
183 | result = 1; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return result; | ||
188 | } | ||
189 | |||
190 | int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius) | ||
191 | { | ||
192 | LLVector3 dist = sphere_center-mFrustCenter; | ||
193 | float dsq = dist * dist; | ||
194 | float rsq = mFarPlane*0.5f + radius; | ||
195 | rsq *= rsq; | ||
196 | |||
197 | if (dsq < rsq) | ||
198 | { | ||
199 | return 1; | ||
200 | } | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | // HACK: This version is still around because the version below doesn't work | ||
206 | // unless the agent planes are initialized. | ||
207 | // Return 1 if sphere is in frustum, 2 if fully in frustum, otherwise 0. | ||
208 | // NOTE: 'center' is in absolute frame. | ||
209 | int LLCamera::sphereInFrustumOld(const LLVector3 &sphere_center, const F32 radius) const | ||
210 | { | ||
211 | // Returns 1 if sphere is in frustum, 0 if not. | ||
212 | // modified so that default view frust is along X with Z vertical | ||
213 | F32 x, y, z, rightDist, leftDist, topDist, bottomDist; | ||
214 | |||
215 | // Subtract the view position | ||
216 | //LLVector3 relative_center; | ||
217 | //relative_center = sphere_center - getOrigin(); | ||
218 | LLVector3 rel_center(sphere_center); | ||
219 | rel_center -= mOrigin; | ||
220 | |||
221 | bool all_in = TRUE; | ||
222 | |||
223 | // Transform relative_center.x to camera frame | ||
224 | x = mXAxis * rel_center; | ||
225 | if (x < MIN_NEAR_PLANE - radius) | ||
226 | { | ||
227 | return 0; | ||
228 | } | ||
229 | else if (x < MIN_NEAR_PLANE + radius) | ||
230 | { | ||
231 | all_in = FALSE; | ||
232 | } | ||
233 | |||
234 | if (x > mFarPlane + radius) | ||
235 | { | ||
236 | return 0; | ||
237 | } | ||
238 | else if (x > mFarPlane - radius) | ||
239 | { | ||
240 | all_in = FALSE; | ||
241 | } | ||
242 | |||
243 | // Transform relative_center.y to camera frame | ||
244 | y = mYAxis * rel_center; | ||
245 | |||
246 | // distance to plane is the dot product of (x, y, 0) * plane_normal | ||
247 | rightDist = x * mLocalPlanes[PLANE_RIGHT][VX] + y * mLocalPlanes[PLANE_RIGHT][VY]; | ||
248 | if (rightDist < -radius) | ||
249 | { | ||
250 | return 0; | ||
251 | } | ||
252 | else if (rightDist < radius) | ||
253 | { | ||
254 | all_in = FALSE; | ||
255 | } | ||
256 | |||
257 | leftDist = x * mLocalPlanes[PLANE_LEFT][VX] + y * mLocalPlanes[PLANE_LEFT][VY]; | ||
258 | if (leftDist < -radius) | ||
259 | { | ||
260 | return 0; | ||
261 | } | ||
262 | else if (leftDist < radius) | ||
263 | { | ||
264 | all_in = FALSE; | ||
265 | } | ||
266 | |||
267 | // Transform relative_center.y to camera frame | ||
268 | z = mZAxis * rel_center; | ||
269 | |||
270 | topDist = x * mLocalPlanes[PLANE_TOP][VX] + z * mLocalPlanes[PLANE_TOP][VZ]; | ||
271 | if (topDist < -radius) | ||
272 | { | ||
273 | return 0; | ||
274 | } | ||
275 | else if (topDist < radius) | ||
276 | { | ||
277 | all_in = FALSE; | ||
278 | } | ||
279 | |||
280 | bottomDist = x * mLocalPlanes[PLANE_BOTTOM][VX] + z * mLocalPlanes[PLANE_BOTTOM][VZ]; | ||
281 | if (bottomDist < -radius) | ||
282 | { | ||
283 | return 0; | ||
284 | } | ||
285 | else if (bottomDist < radius) | ||
286 | { | ||
287 | all_in = FALSE; | ||
288 | } | ||
289 | |||
290 | if (all_in) | ||
291 | { | ||
292 | return 2; | ||
293 | } | ||
294 | |||
295 | return 1; | ||
296 | } | ||
297 | |||
298 | |||
299 | // HACK: This (presumably faster) version only currently works if you set up the | ||
300 | // frustum planes using GL. At some point we should get those planes through another | ||
301 | // mechanism, and then we can get rid of the "old" version above. | ||
302 | |||
303 | // Return 1 if sphere is in frustum, 2 if fully in frustum, otherwise 0. | ||
304 | // NOTE: 'center' is in absolute frame. | ||
305 | int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius) const | ||
306 | { | ||
307 | // Returns 1 if sphere is in frustum, 0 if not. | ||
308 | int res = 2; | ||
309 | for (int i = 0; i < 6; i++) | ||
310 | { | ||
311 | float d = mAgentPlanes[i].dist(sphere_center); | ||
312 | |||
313 | if (d > radius) | ||
314 | { | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | if (d > -radius) | ||
319 | { | ||
320 | res = 1; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | return res; | ||
325 | } | ||
326 | |||
327 | |||
328 | // return height of a sphere of given radius, located at center, in pixels | ||
329 | F32 LLCamera::heightInPixels(const LLVector3 ¢er, F32 radius ) const | ||
330 | { | ||
331 | if (radius == 0.f) return 0.f; | ||
332 | |||
333 | // If height initialized | ||
334 | if (mViewHeightInPixels > -1) | ||
335 | { | ||
336 | // Convert sphere to coord system with 0,0,0 at camera | ||
337 | LLVector3 vec = center - mOrigin; | ||
338 | |||
339 | // Compute distance to sphere | ||
340 | F32 dist = vec.magVec(); | ||
341 | |||
342 | // Calculate angle of whole object | ||
343 | F32 angle = 2.0f * (F32) atan2(radius, dist); | ||
344 | |||
345 | // Calculate fraction of field of view | ||
346 | F32 fraction_of_fov = angle / mView; | ||
347 | |||
348 | // Compute number of pixels tall, based on vertical field of view | ||
349 | return (fraction_of_fov * mViewHeightInPixels); | ||
350 | } | ||
351 | else | ||
352 | { | ||
353 | // return invalid height | ||
354 | return -1.0f; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | // If pos is visible, return the distance from pos to the camera. | ||
359 | // Use fudge distance to scale rad against top/bot/left/right planes | ||
360 | // Otherwise, return -distance | ||
361 | F32 LLCamera::visibleDistance(const LLVector3 &pos, F32 rad, F32 fudgedist, U32 planemask) const | ||
362 | { | ||
363 | if (mFixedDistance > 0) | ||
364 | { | ||
365 | return mFixedDistance; | ||
366 | } | ||
367 | LLVector3 dvec = pos - mOrigin; | ||
368 | // Check visibility | ||
369 | F32 dist = dvec.magVec(); | ||
370 | if (dist > rad) | ||
371 | { | ||
372 | F32 dp,tdist; | ||
373 | dp = dvec * mXAxis; | ||
374 | if (dp < -rad) | ||
375 | return -dist; | ||
376 | |||
377 | rad *= fudgedist; | ||
378 | LLVector3 tvec(pos); | ||
379 | for (int p=0; p<PLANE_NUM; p++) | ||
380 | { | ||
381 | if (!(planemask & (1<<p))) | ||
382 | continue; | ||
383 | tdist = -(mWorldPlanes[p].dist(tvec)); | ||
384 | if (tdist > rad) | ||
385 | return -dist; | ||
386 | } | ||
387 | } | ||
388 | return dist; | ||
389 | } | ||
390 | |||
391 | // Like visibleDistance, except uses mHorizPlanes[], which are left and right | ||
392 | // planes perpindicular to (0,0,1) in world space | ||
393 | F32 LLCamera::visibleHorizDistance(const LLVector3 &pos, F32 rad, F32 fudgedist, U32 planemask) const | ||
394 | { | ||
395 | if (mFixedDistance > 0) | ||
396 | { | ||
397 | return mFixedDistance; | ||
398 | } | ||
399 | LLVector3 dvec = pos - mOrigin; | ||
400 | // Check visibility | ||
401 | F32 dist = dvec.magVec(); | ||
402 | if (dist > rad) | ||
403 | { | ||
404 | rad *= fudgedist; | ||
405 | LLVector3 tvec(pos); | ||
406 | for (int p=0; p<HORIZ_PLANE_NUM; p++) | ||
407 | { | ||
408 | if (!(planemask & (1<<p))) | ||
409 | continue; | ||
410 | F32 tdist = -(mHorizPlanes[p].dist(tvec)); | ||
411 | if (tdist > rad) | ||
412 | return -dist; | ||
413 | } | ||
414 | } | ||
415 | return dist; | ||
416 | } | ||
417 | |||
418 | // ---------------- friends and operators ---------------- | ||
419 | |||
420 | std::ostream& operator<<(std::ostream &s, const LLCamera &C) | ||
421 | { | ||
422 | s << "{ \n"; | ||
423 | s << " Center = " << C.getOrigin() << "\n"; | ||
424 | s << " AtAxis = " << C.getXAxis() << "\n"; | ||
425 | s << " LeftAxis = " << C.getYAxis() << "\n"; | ||
426 | s << " UpAxis = " << C.getZAxis() << "\n"; | ||
427 | s << " View = " << C.getView() << "\n"; | ||
428 | s << " Aspect = " << C.getAspect() << "\n"; | ||
429 | s << " NearPlane = " << C.mNearPlane << "\n"; | ||
430 | s << " FarPlane = " << C.mFarPlane << "\n"; | ||
431 | s << " TopPlane = " << C.mLocalPlanes[LLCamera::PLANE_TOP][VX] << " " | ||
432 | << C.mLocalPlanes[LLCamera::PLANE_TOP][VY] << " " | ||
433 | << C.mLocalPlanes[LLCamera::PLANE_TOP][VZ] << "\n"; | ||
434 | s << " BottomPlane = " << C.mLocalPlanes[LLCamera::PLANE_BOTTOM][VX] << " " | ||
435 | << C.mLocalPlanes[LLCamera::PLANE_BOTTOM][VY] << " " | ||
436 | << C.mLocalPlanes[LLCamera::PLANE_BOTTOM][VZ] << "\n"; | ||
437 | s << " LeftPlane = " << C.mLocalPlanes[LLCamera::PLANE_LEFT][VX] << " " | ||
438 | << C.mLocalPlanes[LLCamera::PLANE_LEFT][VY] << " " | ||
439 | << C.mLocalPlanes[LLCamera::PLANE_LEFT][VZ] << "\n"; | ||
440 | s << " RightPlane = " << C.mLocalPlanes[LLCamera::PLANE_RIGHT][VX] << " " | ||
441 | << C.mLocalPlanes[LLCamera::PLANE_RIGHT][VY] << " " | ||
442 | << C.mLocalPlanes[LLCamera::PLANE_RIGHT][VZ] << "\n"; | ||
443 | s << "}"; | ||
444 | return s; | ||
445 | } | ||
446 | |||
447 | |||
448 | |||
449 | // ---------------- private member functions ---------------- | ||
450 | |||
451 | void LLCamera::calculateFrustumPlanes() | ||
452 | { | ||
453 | // The planes only change when any of the frustum descriptions change. | ||
454 | // They are not affected by changes of the position of the Frustum | ||
455 | // because they are known in the view frame and the position merely | ||
456 | // provides information on how to get from the absolute frame to the | ||
457 | // view frame. | ||
458 | |||
459 | F32 left,right,top,bottom; | ||
460 | top = mFarPlane * (F32)tanf(0.5f * mView); | ||
461 | bottom = -top; | ||
462 | left = top * mAspect; | ||
463 | right = -left; | ||
464 | |||
465 | calculateFrustumPlanes(left, right, top, bottom); | ||
466 | } | ||
467 | |||
468 | LLPlane planeFromPoints(LLVector3 p1, LLVector3 p2, LLVector3 p3) | ||
469 | { | ||
470 | LLVector3 n = ((p2-p1)%(p3-p1)); | ||
471 | n.normVec(); | ||
472 | |||
473 | return LLPlane(p1, n); | ||
474 | } | ||
475 | |||
476 | |||
477 | void LLCamera::calcAgentFrustumPlanes(LLVector3* frust) | ||
478 | { | ||
479 | |||
480 | for (int i = 0; i < 8; i++) | ||
481 | { | ||
482 | mAgentFrustum[i] = frust[i]; | ||
483 | } | ||
484 | |||
485 | //frust contains the 8 points of the frustum, calculate 6 planes | ||
486 | |||
487 | //order of planes is important, keep most likely to fail in the front of the list | ||
488 | |||
489 | //near - frust[0], frust[1], frust[2] | ||
490 | mAgentPlanes[2] = planeFromPoints(frust[0], frust[1], frust[2]); | ||
491 | |||
492 | //far | ||
493 | mAgentPlanes[5] = planeFromPoints(frust[5], frust[4], frust[6]); | ||
494 | |||
495 | //left | ||
496 | mAgentPlanes[0] = planeFromPoints(frust[4], frust[0], frust[7]); | ||
497 | |||
498 | //right | ||
499 | mAgentPlanes[1] = planeFromPoints(frust[1], frust[5], frust[6]); | ||
500 | |||
501 | //top | ||
502 | mAgentPlanes[4] = planeFromPoints(frust[3], frust[2], frust[6]); | ||
503 | |||
504 | //bottom | ||
505 | mAgentPlanes[3] = planeFromPoints(frust[1], frust[0], frust[4]); | ||
506 | |||
507 | //cache plane octant facing mask for use in AABBInFrustum | ||
508 | for (int i = 0; i < 8; i++) | ||
509 | { | ||
510 | U8 mask = 0; | ||
511 | LLPlane p = mAgentPlanes[i]; | ||
512 | LLVector3 n = LLVector3(p); | ||
513 | |||
514 | if (n.mV[0] >= 0) | ||
515 | { | ||
516 | mask |= 1; | ||
517 | } | ||
518 | if (n.mV[1] >= 0) | ||
519 | { | ||
520 | mask |= 2; | ||
521 | } | ||
522 | if (n.mV[2] >= 0) | ||
523 | { | ||
524 | mask |= 4; | ||
525 | } | ||
526 | mAgentPlaneMask[i] = mask; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | void LLCamera::calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom) | ||
531 | { | ||
532 | LLVector3 a, b, c; | ||
533 | |||
534 | // For each plane we need to define 3 points (LLVector3's) in camera view space. | ||
535 | // The order in which we pass the points to planeFromPoints() matters, because the | ||
536 | // plane normal has a degeneracy of 2; we want it pointing _into_ the frustum. | ||
537 | |||
538 | a.setVec(0.0f, 0.0f, 0.0f); | ||
539 | b.setVec(mFarPlane, right, top); | ||
540 | c.setVec(mFarPlane, right, bottom); | ||
541 | mLocalPlanes[PLANE_RIGHT].setVec(a, b, c); | ||
542 | |||
543 | c.setVec(mFarPlane, left, top); | ||
544 | mLocalPlanes[PLANE_TOP].setVec(a, c, b); | ||
545 | |||
546 | b.setVec(mFarPlane, left, bottom); | ||
547 | mLocalPlanes[PLANE_LEFT].setVec(a, b, c); | ||
548 | |||
549 | c.setVec(mFarPlane, right, bottom); | ||
550 | mLocalPlanes[PLANE_BOTTOM].setVec( a, c, b); | ||
551 | |||
552 | //calculate center and radius squared of frustum in world absolute coordinates | ||
553 | mFrustCenter = X_AXIS*mFarPlane*0.5f; | ||
554 | mFrustCenter = transformToAbsolute(mFrustCenter); | ||
555 | mFrustRadiusSquared = mFarPlane*0.5f; | ||
556 | mFrustRadiusSquared *= mFrustRadiusSquared * 1.05f; //pad radius squared by 5% | ||
557 | } | ||
558 | |||
559 | // x and y are in WINDOW space, so x = Y-Axis (left/right), y= Z-Axis(Up/Down) | ||
560 | void LLCamera::calculateFrustumPlanesFromWindow(F32 x1, F32 y1, F32 x2, F32 y2) | ||
561 | { | ||
562 | F32 bottom, top, left, right; | ||
563 | F32 view_height = (F32)tanf(0.5f * mView) * mFarPlane; | ||
564 | F32 view_width = view_height * mAspect; | ||
565 | |||
566 | left = x1 * -2.f * view_width; | ||
567 | right = x2 * -2.f * view_width; | ||
568 | bottom = y1 * 2.f * view_height; | ||
569 | top = y2 * 2.f * view_height; | ||
570 | |||
571 | calculateFrustumPlanes(left, right, top, bottom); | ||
572 | } | ||
573 | |||
574 | void LLCamera::calculateWorldFrustumPlanes() | ||
575 | { | ||
576 | F32 d; | ||
577 | LLVector3 center = mOrigin - mXAxis*mNearPlane; | ||
578 | mWorldPlanePos = center; | ||
579 | for (int p=0; p<4; p++) | ||
580 | { | ||
581 | LLVector3 pnorm = LLVector3(mLocalPlanes[p]); | ||
582 | LLVector3 norm = rotateToAbsolute(pnorm); | ||
583 | norm.normVec(); | ||
584 | d = -(center * norm); | ||
585 | mWorldPlanes[p] = LLPlane(norm, d); | ||
586 | } | ||
587 | // horizontal planes, perpindicular to (0,0,1); | ||
588 | LLVector3 zaxis(0, 0, 1.0f); | ||
589 | F32 yaw = getYaw(); | ||
590 | { | ||
591 | LLVector3 tnorm = LLVector3(mLocalPlanes[PLANE_LEFT]); | ||
592 | tnorm.rotVec(yaw, zaxis); | ||
593 | d = -(mOrigin * tnorm); | ||
594 | mHorizPlanes[HORIZ_PLANE_LEFT] = LLPlane(tnorm, d); | ||
595 | } | ||
596 | { | ||
597 | LLVector3 tnorm = LLVector3(mLocalPlanes[PLANE_RIGHT]); | ||
598 | tnorm.rotVec(yaw, zaxis); | ||
599 | d = -(mOrigin * tnorm); | ||
600 | mHorizPlanes[HORIZ_PLANE_RIGHT] = LLPlane(tnorm, d); | ||
601 | } | ||
602 | } | ||
603 | |||
604 | // NOTE: this is the OpenGL matrix that will transform the default OpenGL view | ||
605 | // (-Z=at, Y=up) to the default view of the LLCamera class (X=at, Z=up): | ||
606 | // | ||
607 | // F32 cfr_transform = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X | ||
608 | // -1.f, 0.f, 0.f, 0.f, // -X becomes Y | ||
609 | // 0.f, 1.f, 0.f, 0.f, // Y becomes Z | ||
610 | // 0.f, 0.f, 0.f, 1.f }; | ||