diff options
Diffstat (limited to 'linden/indra/llmath/llcamera.cpp')
-rw-r--r-- | linden/indra/llmath/llcamera.cpp | 155 |
1 files changed, 110 insertions, 45 deletions
diff --git a/linden/indra/llmath/llcamera.cpp b/linden/indra/llmath/llcamera.cpp index cb9fae6..0f343bc 100644 --- a/linden/indra/llmath/llcamera.cpp +++ b/linden/indra/llmath/llcamera.cpp | |||
@@ -17,7 +17,8 @@ | |||
17 | * There are special exceptions to the terms and conditions of the GPL as | 17 | * There are special exceptions to the terms and conditions of the GPL as |
18 | * it is applied to this Source Code. View the full text of the exception | 18 | * it is applied to this Source Code. View the full text of the exception |
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 19 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
20 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | 20 | * online at |
21 | * http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | 22 | * |
22 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
23 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
@@ -50,33 +51,38 @@ LLCamera::LLCamera() : | |||
50 | } | 51 | } |
51 | 52 | ||
52 | 53 | ||
53 | LLCamera::LLCamera(F32 z_field_of_view, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) : | 54 | LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_pixels, F32 near_plane, F32 far_plane) : |
54 | LLCoordFrame(), | 55 | LLCoordFrame(), |
55 | mView(z_field_of_view), | ||
56 | mAspect(aspect_ratio), | ||
57 | mViewHeightInPixels(view_height_in_pixels), | 56 | mViewHeightInPixels(view_height_in_pixels), |
58 | mNearPlane(near_plane), | ||
59 | mFarPlane(far_plane), | ||
60 | mFixedDistance(-1.f), | 57 | mFixedDistance(-1.f), |
61 | mPlaneCount(6) | 58 | mPlaneCount(6) |
62 | { | 59 | { |
63 | if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; } | 60 | mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); |
64 | else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; } | 61 | mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); |
62 | if(far_plane < 0) far_plane = DEFAULT_FAR_PLANE; | ||
63 | mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE); | ||
65 | 64 | ||
66 | if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; } | 65 | setView(vertical_fov_rads); |
67 | else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; } | 66 | } |
68 | |||
69 | if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; } | ||
70 | else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; } | ||
71 | 67 | ||
72 | if (mFarPlane < 0) { mFarPlane = DEFAULT_FAR_PLANE; } | ||
73 | else if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; } | ||
74 | else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; } | ||
75 | 68 | ||
76 | calculateFrustumPlanes(); | 69 | // ---------------- LLCamera::getFoo() member functions ---------------- |
77 | } | ||
78 | 70 | ||
71 | F32 LLCamera::getMinView() const | ||
72 | { | ||
73 | // minimum vertical fov needs to be constrained in narrow windows. | ||
74 | return mAspect > 1 | ||
75 | ? MIN_FIELD_OF_VIEW // wide views | ||
76 | : MIN_FIELD_OF_VIEW * 1/mAspect; // clamps minimum width in narrow views | ||
77 | } | ||
79 | 78 | ||
79 | F32 LLCamera::getMaxView() const | ||
80 | { | ||
81 | // maximum vertical fov needs to be constrained in wide windows. | ||
82 | return mAspect > 1 | ||
83 | ? MAX_FIELD_OF_VIEW / mAspect // clamps maximum width in wide views | ||
84 | : MAX_FIELD_OF_VIEW; // narrow views | ||
85 | } | ||
80 | 86 | ||
81 | // ---------------- LLCamera::setFoo() member functions ---------------- | 87 | // ---------------- LLCamera::setFoo() member functions ---------------- |
82 | 88 | ||
@@ -92,11 +98,9 @@ void LLCamera::disableUserClipPlane() | |||
92 | mPlaneCount = 6; | 98 | mPlaneCount = 6; |
93 | } | 99 | } |
94 | 100 | ||
95 | void LLCamera::setView(F32 field_of_view) | 101 | void LLCamera::setView(F32 vertical_fov_rads) |
96 | { | 102 | { |
97 | mView = field_of_view; | 103 | mView = llclamp(vertical_fov_rads, MIN_FIELD_OF_VIEW, MAX_FIELD_OF_VIEW); |
98 | if (mView < MIN_FIELD_OF_VIEW) { mView = MIN_FIELD_OF_VIEW; } | ||
99 | else if (mView > MAX_FIELD_OF_VIEW) { mView = MAX_FIELD_OF_VIEW; } | ||
100 | calculateFrustumPlanes(); | 104 | calculateFrustumPlanes(); |
101 | } | 105 | } |
102 | 106 | ||
@@ -110,27 +114,21 @@ void LLCamera::setViewHeightInPixels(S32 height) | |||
110 | 114 | ||
111 | void LLCamera::setAspect(F32 aspect_ratio) | 115 | void LLCamera::setAspect(F32 aspect_ratio) |
112 | { | 116 | { |
113 | mAspect = aspect_ratio; | 117 | mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); |
114 | if (mAspect < MIN_ASPECT_RATIO) { mAspect = MIN_ASPECT_RATIO; } | ||
115 | else if (mAspect > MAX_ASPECT_RATIO) { mAspect = MAX_ASPECT_RATIO; } | ||
116 | calculateFrustumPlanes(); | 118 | calculateFrustumPlanes(); |
117 | } | 119 | } |
118 | 120 | ||
119 | 121 | ||
120 | void LLCamera::setNear(F32 near_plane) | 122 | void LLCamera::setNear(F32 near_plane) |
121 | { | 123 | { |
122 | mNearPlane = near_plane; | 124 | mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); |
123 | if (mNearPlane < MIN_NEAR_PLANE) { mNearPlane = MIN_NEAR_PLANE; } | ||
124 | else if (mNearPlane > MAX_NEAR_PLANE) { mNearPlane = MAX_NEAR_PLANE; } | ||
125 | calculateFrustumPlanes(); | 125 | calculateFrustumPlanes(); |
126 | } | 126 | } |
127 | 127 | ||
128 | 128 | ||
129 | void LLCamera::setFar(F32 far_plane) | 129 | void LLCamera::setFar(F32 far_plane) |
130 | { | 130 | { |
131 | mFarPlane = far_plane; | 131 | mFarPlane = llclamp(far_plane, MIN_FAR_PLANE, MAX_FAR_PLANE); |
132 | if (mFarPlane < MIN_FAR_PLANE) { mFarPlane = MIN_FAR_PLANE; } | ||
133 | else if (mFarPlane > MAX_FAR_PLANE) { mFarPlane = MAX_FAR_PLANE; } | ||
134 | calculateFrustumPlanes(); | 132 | calculateFrustumPlanes(); |
135 | } | 133 | } |
136 | 134 | ||
@@ -180,28 +178,95 @@ S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius) | |||
180 | U8 mask = 0; | 178 | U8 mask = 0; |
181 | S32 result = 2; | 179 | S32 result = 2; |
182 | 180 | ||
183 | for (U32 i = 0; i < mPlaneCount; i++) | 181 | if (radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist) |
184 | { | 182 | { //box is larger than frustum, check frustum quads against box planes |
185 | mask = mAgentPlanes[i].mask; | ||
186 | LLPlane p = mAgentPlanes[i].p; | ||
187 | LLVector3 n = LLVector3(p); | ||
188 | float d = p.mV[3]; | ||
189 | LLVector3 rscale = radius.scaledVec(scaler[mask]); | ||
190 | |||
191 | LLVector3 minp = center - rscale; | ||
192 | LLVector3 maxp = center + rscale; | ||
193 | 183 | ||
194 | if (n * minp > -d) | 184 | static const LLVector3 dir[] = |
195 | { | 185 | { |
196 | return 0; | 186 | LLVector3(1, 0, 0), |
187 | LLVector3(-1, 0, 0), | ||
188 | LLVector3(0, 1, 0), | ||
189 | LLVector3(0, -1, 0), | ||
190 | LLVector3(0, 0, 1), | ||
191 | LLVector3(0, 0, -1) | ||
192 | }; | ||
193 | |||
194 | U32 quads[] = | ||
195 | { | ||
196 | 0, 1, 2, 3, | ||
197 | 0, 1, 5, 4, | ||
198 | 2, 3, 7, 6, | ||
199 | 3, 0, 7, 4, | ||
200 | 1, 2, 6, 4, | ||
201 | 4, 5, 6, 7 | ||
202 | }; | ||
203 | |||
204 | result = 0; | ||
205 | |||
206 | BOOL total_inside = TRUE; | ||
207 | for (U32 i = 0; i < 6; i++) | ||
208 | { | ||
209 | LLVector3 p = center + radius.scaledVec(dir[i]); | ||
210 | F32 d = -p*dir[i]; | ||
211 | |||
212 | for (U32 j = 0; j < 6; j++) | ||
213 | { //for each quad | ||
214 | F32 dist = mAgentFrustum[quads[j*4+0]]*dir[i] + d; | ||
215 | if (dist > 0) | ||
216 | { //at least one frustum point is outside the AABB | ||
217 | total_inside = FALSE; | ||
218 | for (U32 k = 1; k < 4; k++) | ||
219 | { //for each other point on quad | ||
220 | if ( mAgentFrustum[quads[j*4+k]]*dir[i]+d <= 0.f) | ||
221 | { //quad is straddling some plane of AABB | ||
222 | return 1; | ||
223 | } | ||
224 | } | ||
225 | } | ||
226 | else | ||
227 | { | ||
228 | for (U32 k = 1; k < 4; k++) | ||
229 | { | ||
230 | if (mAgentFrustum[quads[j*4+k]]*dir[i]+d > 0.f) | ||
231 | { | ||
232 | return 1; | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | } | ||
197 | } | 237 | } |
198 | 238 | ||
199 | if (n * maxp > -d) | 239 | if (total_inside) |
200 | { | 240 | { |
201 | result = 1; | 241 | result = 1; |
202 | } | 242 | } |
203 | } | 243 | } |
244 | else | ||
245 | { | ||
246 | for (U32 i = 0; i < mPlaneCount; i++) | ||
247 | { | ||
248 | mask = mAgentPlanes[i].mask; | ||
249 | LLPlane p = mAgentPlanes[i].p; | ||
250 | LLVector3 n = LLVector3(p); | ||
251 | float d = p.mV[3]; | ||
252 | LLVector3 rscale = radius.scaledVec(scaler[mask]); | ||
253 | |||
254 | LLVector3 minp = center - rscale; | ||
255 | LLVector3 maxp = center + rscale; | ||
256 | |||
257 | if (n * minp > -d) | ||
258 | { | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | if (n * maxp > -d) | ||
263 | { | ||
264 | result = 1; | ||
265 | } | ||
266 | } | ||
267 | } | ||
204 | 268 | ||
269 | |||
205 | return result; | 270 | return result; |
206 | } | 271 | } |
207 | 272 | ||