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/newview/llviewercamera.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 '')
-rw-r--r-- | linden/indra/newview/llviewercamera.cpp | 630 |
1 files changed, 630 insertions, 0 deletions
diff --git a/linden/indra/newview/llviewercamera.cpp b/linden/indra/newview/llviewercamera.cpp new file mode 100644 index 0000000..62fa0ef --- /dev/null +++ b/linden/indra/newview/llviewercamera.cpp | |||
@@ -0,0 +1,630 @@ | |||
1 | /** | ||
2 | * @file llviewercamera.cpp | ||
3 | * @brief LLViewerCamera class implementation | ||
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 | #include <iomanip> // for setprecision | ||
29 | #include "llviewerprecompiledheaders.h" | ||
30 | |||
31 | #include "llviewercamera.h" | ||
32 | |||
33 | #include "llquaternion.h" | ||
34 | |||
35 | #include "llagent.h" | ||
36 | #include "llviewercontrol.h" | ||
37 | #include "lldrawable.h" | ||
38 | #include "llface.h" | ||
39 | #include "llgl.h" | ||
40 | #include "llglheaders.h" | ||
41 | #include "llviewerobjectlist.h" | ||
42 | #include "llviewerregion.h" | ||
43 | #include "llviewerwindow.h" | ||
44 | #include "llvovolume.h" | ||
45 | #include "llworld.h" | ||
46 | |||
47 | BOOL LLViewerCamera::sDisableCameraConstraints = FALSE; | ||
48 | |||
49 | LLViewerCamera *gCamera = NULL; | ||
50 | |||
51 | LLViewerCamera::LLViewerCamera() : LLCamera() | ||
52 | { | ||
53 | calcProjection(getFar()); | ||
54 | S32 i; | ||
55 | for (i = 0; i < 16; i++) | ||
56 | { | ||
57 | mGLProjectionMatrix[i] = 0.f; | ||
58 | } | ||
59 | mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; | ||
60 | mPixelMeterRatio = 0.f; | ||
61 | mScreenPixelArea = 0; | ||
62 | mZoomFactor = 1.f; | ||
63 | mZoomSubregion = 1; | ||
64 | } | ||
65 | |||
66 | void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, | ||
67 | const LLVector3 &up_direction, | ||
68 | const LLVector3 &point_of_interest) | ||
69 | { | ||
70 | LLVector3 last_position; | ||
71 | LLVector3 last_axis; | ||
72 | last_position = getOrigin(); | ||
73 | last_axis = getAtAxis(); | ||
74 | |||
75 | mLastPointOfInterest = point_of_interest; | ||
76 | |||
77 | // constrain to max distance from avatar | ||
78 | LLVector3 camera_offset = center - gAgent.getPositionAgent(); | ||
79 | |||
80 | setOriginAndLookAt(center, up_direction, point_of_interest); | ||
81 | |||
82 | F32 dpos = (center - last_position).magVec(); | ||
83 | LLQuaternion rotation; | ||
84 | rotation.shortestArc(last_axis, getAtAxis()); | ||
85 | |||
86 | F32 x, y, z; | ||
87 | F32 drot; | ||
88 | rotation.getAngleAxis(&drot, &x, &y, &z); | ||
89 | mVelocityStat.addValue(dpos); | ||
90 | mAngularVelocityStat.addValue(drot); | ||
91 | // update pixel meter ratio using default fov, not modified one | ||
92 | mPixelMeterRatio = mViewHeightInPixels / (2.f*tanf(mCameraFOVDefault*0.5)); | ||
93 | // update screen pixel area | ||
94 | mScreenPixelArea =(S32)((F32)mViewHeightInPixels * ((F32)mViewHeightInPixels * mAspect)); | ||
95 | } | ||
96 | |||
97 | // Handy copies of last good GL matrices | ||
98 | F64 gGLModelView[16]; | ||
99 | S32 gGLViewport[4]; | ||
100 | |||
101 | const LLMatrix4 &LLViewerCamera::getProjection() const | ||
102 | { | ||
103 | calcProjection(getFar()); | ||
104 | return mProjectionMatrix; | ||
105 | |||
106 | } | ||
107 | |||
108 | const LLMatrix4 &LLViewerCamera::getModelview() const | ||
109 | { | ||
110 | LLMatrix4 cfr(OGL_TO_CFR_ROTATION); | ||
111 | getMatrixToLocal(mModelviewMatrix); | ||
112 | mModelviewMatrix *= cfr; | ||
113 | return mModelviewMatrix; | ||
114 | } | ||
115 | |||
116 | void LLViewerCamera::calcProjection(const F32 far_distance) const | ||
117 | { | ||
118 | F32 fov_y, z_far, z_near, aspect, f; | ||
119 | fov_y = getView(); | ||
120 | z_far = far_distance; | ||
121 | z_near = getNear(); | ||
122 | aspect = getAspect(); | ||
123 | |||
124 | f = 1/tan(fov_y*0.5f); | ||
125 | |||
126 | mProjectionMatrix.zero(); | ||
127 | mProjectionMatrix.mMatrix[0][0] = f/aspect; | ||
128 | mProjectionMatrix.mMatrix[1][1] = f; | ||
129 | mProjectionMatrix.mMatrix[2][2] = (z_far + z_near)/(z_near - z_far); | ||
130 | mProjectionMatrix.mMatrix[3][2] = (2*z_far*z_near)/(z_near - z_far); | ||
131 | mProjectionMatrix.mMatrix[2][3] = -1; | ||
132 | } | ||
133 | |||
134 | // Sets up opengl state for 3D drawing. If for selection, also | ||
135 | // sets up a pick matrix. x and y are ignored if for_selection is false. | ||
136 | // The picking region is centered on x,y and has the specified width and | ||
137 | // height. | ||
138 | |||
139 | LLMatrix4 gProjectionMat; | ||
140 | |||
141 | void LLViewerCamera::updateFrustumPlanes() | ||
142 | { | ||
143 | GLint viewport[4]; | ||
144 | GLdouble model[16]; | ||
145 | GLdouble proj[16]; | ||
146 | GLdouble objX,objY,objZ; | ||
147 | |||
148 | LLVector3 frust[8]; | ||
149 | |||
150 | glGetIntegerv(GL_VIEWPORT, viewport); | ||
151 | glGetDoublev(GL_MODELVIEW_MATRIX, model); | ||
152 | glGetDoublev(GL_PROJECTION_MATRIX,proj); | ||
153 | |||
154 | gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); | ||
155 | frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); | ||
156 | gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); | ||
157 | frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); | ||
158 | gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); | ||
159 | frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); | ||
160 | gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); | ||
161 | frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); | ||
162 | /*gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); | ||
163 | frust[4].setVec((F32)objX,(F32)objY,(F32)objZ); | ||
164 | gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); | ||
165 | frust[5].setVec((F32)objX,(F32)objY,(F32)objZ); | ||
166 | gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); | ||
167 | frust[6].setVec((F32)objX,(F32)objY,(F32)objZ); | ||
168 | gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); | ||
169 | frust[7].setVec((F32)objX,(F32)objY,(F32)objZ);*/ | ||
170 | |||
171 | for (U32 i = 0; i < 4; i++) | ||
172 | { | ||
173 | LLVector3 vec = frust[i] - getOrigin(); | ||
174 | vec.normVec(); | ||
175 | frust[i+4] = getOrigin() + vec*getFar()*2.0; | ||
176 | } | ||
177 | |||
178 | calcAgentFrustumPlanes(frust); | ||
179 | } | ||
180 | |||
181 | void LLViewerCamera::setPerspective(BOOL for_selection, | ||
182 | S32 x, S32 y_from_bot, S32 width, S32 height, | ||
183 | BOOL limit_select_distance, | ||
184 | F32 z_near, F32 z_far) | ||
185 | { | ||
186 | F32 fov_y, aspect; | ||
187 | fov_y = RAD_TO_DEG * getView(); | ||
188 | BOOL z_default_near, z_default_far = FALSE; | ||
189 | if (z_far <= 0) | ||
190 | { | ||
191 | z_default_far = TRUE; | ||
192 | z_far = getFar(); | ||
193 | } | ||
194 | if (z_near <= 0) | ||
195 | { | ||
196 | z_default_near = TRUE; | ||
197 | z_near = getNear(); | ||
198 | } | ||
199 | aspect = getAspect(); | ||
200 | |||
201 | // Load camera view matrix | ||
202 | glMatrixMode( GL_PROJECTION ); | ||
203 | glLoadIdentity(); | ||
204 | |||
205 | if (for_selection) | ||
206 | { | ||
207 | // make a tiny little viewport | ||
208 | // anything drawn into this viewport will be "selected" | ||
209 | const U8 VIEWPORT_VECTOR_LEN = 4; | ||
210 | GLint viewport[VIEWPORT_VECTOR_LEN]; | ||
211 | glGetIntegerv(GL_VIEWPORT, viewport); | ||
212 | gluPickMatrix(x + width / 2, y_from_bot + height / 2, width, height, viewport); | ||
213 | |||
214 | if (limit_select_distance) | ||
215 | { | ||
216 | // ...select distance from control | ||
217 | z_far = gSavedSettings.getF32("MaxSelectDistance"); | ||
218 | } | ||
219 | else | ||
220 | { | ||
221 | z_far = gAgent.mDrawDistance; | ||
222 | } | ||
223 | } | ||
224 | else | ||
225 | { | ||
226 | // Only override the far clip if it's not passed in explicitly. | ||
227 | if (z_default_far) | ||
228 | { | ||
229 | z_far = MAX_FAR_CLIP; | ||
230 | } | ||
231 | glViewport(x, y_from_bot, width, height); | ||
232 | } | ||
233 | |||
234 | if (mZoomFactor > 1.f) | ||
235 | { | ||
236 | float offset = mZoomFactor - 1.f; | ||
237 | int pos_y = mZoomSubregion / llceil(mZoomFactor); | ||
238 | int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor)); | ||
239 | glTranslatef(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f); | ||
240 | glScalef(mZoomFactor, mZoomFactor, 1.f); | ||
241 | } | ||
242 | |||
243 | calcProjection(z_far); // Update the projection matrix cache | ||
244 | |||
245 | gluPerspective(fov_y, | ||
246 | aspect, | ||
247 | z_near, | ||
248 | z_far); | ||
249 | glGetFloatv(GL_PROJECTION_MATRIX, (float*)&gProjectionMat); | ||
250 | |||
251 | glMatrixMode( GL_MODELVIEW ); | ||
252 | |||
253 | glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame | ||
254 | |||
255 | GLfloat ogl_matrix[16]; | ||
256 | getOpenGLTransform(ogl_matrix); | ||
257 | glMultMatrixf(ogl_matrix); | ||
258 | |||
259 | if (for_selection && (width > 1 || height > 1)) | ||
260 | { | ||
261 | calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f, | ||
262 | (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f, | ||
263 | (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f, | ||
264 | (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f); | ||
265 | |||
266 | } | ||
267 | |||
268 | // if not picking and not doing a snapshot, cache various GL matrices | ||
269 | if (!for_selection && mZoomFactor == 1.f) | ||
270 | { | ||
271 | // Save GL matrices for access elsewhere in code, especially project_world_to_screen | ||
272 | glGetDoublev(GL_PROJECTION_MATRIX, mGLProjectionMatrix); | ||
273 | glGetDoublev(GL_MODELVIEW_MATRIX, gGLModelView); | ||
274 | glGetIntegerv(GL_VIEWPORT, (GLint*)gGLViewport); | ||
275 | } | ||
276 | |||
277 | updateFrustumPlanes(); | ||
278 | |||
279 | if (gSavedSettings.getBOOL("CameraOffset")) | ||
280 | { | ||
281 | glMatrixMode(GL_PROJECTION); | ||
282 | glTranslatef(0,0,-50); | ||
283 | glRotatef(20.0,1,0,0); | ||
284 | glMatrixMode(GL_MODELVIEW); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | |||
289 | // Uses the last GL matrices set in set_perspective to project a point from | ||
290 | // screen coordinates to the agent's region. | ||
291 | void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 screen_y, LLVector3* pos_agent) const | ||
292 | { | ||
293 | |||
294 | GLdouble x, y, z; | ||
295 | gluUnProject( | ||
296 | GLdouble(screen_x), GLdouble(screen_y), 0.0, | ||
297 | gGLModelView, mGLProjectionMatrix, (GLint*)gGLViewport, | ||
298 | &x, | ||
299 | &y, | ||
300 | &z ); | ||
301 | pos_agent->setVec( (F32)x, (F32)y, (F32)z ); | ||
302 | } | ||
303 | |||
304 | // Uses the last GL matrices set in set_perspective to project a point from | ||
305 | // the agent's region space to screen coordinates. Returns TRUE if point in within | ||
306 | // the current window. | ||
307 | BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp) const | ||
308 | { | ||
309 | BOOL in_front = TRUE; | ||
310 | GLdouble x, y, z; // object's window coords, GL-style | ||
311 | |||
312 | LLVector3 dir_to_point = pos_agent - getOrigin(); | ||
313 | dir_to_point /= dir_to_point.magVec(); | ||
314 | |||
315 | if (dir_to_point * getAtAxis() < 0.f) | ||
316 | { | ||
317 | if (clamp) | ||
318 | { | ||
319 | return FALSE; | ||
320 | } | ||
321 | else | ||
322 | { | ||
323 | in_front = FALSE; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], | ||
328 | gGLModelView, mGLProjectionMatrix, (GLint*)gGLViewport, | ||
329 | &x, &y, &z)) | ||
330 | { | ||
331 | // convert screen coordinates to virtual UI coordinates | ||
332 | x /= gViewerWindow->getDisplayScale().mV[VX]; | ||
333 | y /= gViewerWindow->getDisplayScale().mV[VY]; | ||
334 | |||
335 | // should now have the x,y coords of grab_point in screen space | ||
336 | const LLRect& window_rect = gViewerWindow->getWindowRect(); | ||
337 | |||
338 | // ...sanity check | ||
339 | S32 int_x = lltrunc(x); | ||
340 | S32 int_y = lltrunc(y); | ||
341 | |||
342 | BOOL valid = TRUE; | ||
343 | |||
344 | if (clamp) | ||
345 | { | ||
346 | if (int_x < window_rect.mLeft) | ||
347 | { | ||
348 | out_point.mX = window_rect.mLeft; | ||
349 | valid = FALSE; | ||
350 | } | ||
351 | else if (int_x > window_rect.mRight) | ||
352 | { | ||
353 | out_point.mX = window_rect.mRight; | ||
354 | valid = FALSE; | ||
355 | } | ||
356 | else | ||
357 | { | ||
358 | out_point.mX = int_x; | ||
359 | } | ||
360 | |||
361 | if (int_y < window_rect.mBottom) | ||
362 | { | ||
363 | out_point.mY = window_rect.mBottom; | ||
364 | valid = FALSE; | ||
365 | } | ||
366 | else if (int_y > window_rect.mTop) | ||
367 | { | ||
368 | out_point.mY = window_rect.mTop; | ||
369 | valid = FALSE; | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | out_point.mY = int_y; | ||
374 | } | ||
375 | return valid; | ||
376 | } | ||
377 | else | ||
378 | { | ||
379 | out_point.mX = int_x; | ||
380 | out_point.mY = int_y; | ||
381 | |||
382 | if (int_x < window_rect.mLeft) | ||
383 | { | ||
384 | valid = FALSE; | ||
385 | } | ||
386 | else if (int_x > window_rect.mRight) | ||
387 | { | ||
388 | valid = FALSE; | ||
389 | } | ||
390 | if (int_y < window_rect.mBottom) | ||
391 | { | ||
392 | valid = FALSE; | ||
393 | } | ||
394 | else if (int_y > window_rect.mTop) | ||
395 | { | ||
396 | valid = FALSE; | ||
397 | } | ||
398 | |||
399 | return in_front && valid; | ||
400 | } | ||
401 | } | ||
402 | else | ||
403 | { | ||
404 | return FALSE; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | // Uses the last GL matrices set in set_perspective to project a point from | ||
409 | // the agent's region space to the nearest edge in screen coordinates. | ||
410 | // Returns TRUE if projection succeeds. | ||
411 | BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, | ||
412 | LLCoordGL &out_point) const | ||
413 | { | ||
414 | LLVector3 dir_to_point = pos_agent - getOrigin(); | ||
415 | dir_to_point /= dir_to_point.magVec(); | ||
416 | |||
417 | BOOL in_front = TRUE; | ||
418 | if (dir_to_point * getAtAxis() < 0.f) | ||
419 | { | ||
420 | in_front = FALSE; | ||
421 | } | ||
422 | |||
423 | GLdouble x, y, z; // object's window coords, GL-style | ||
424 | if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], | ||
425 | pos_agent.mV[VZ], gGLModelView, | ||
426 | mGLProjectionMatrix, (GLint*)gGLViewport, | ||
427 | &x, &y, &z)) | ||
428 | { | ||
429 | x /= gViewerWindow->getDisplayScale().mV[VX]; | ||
430 | y /= gViewerWindow->getDisplayScale().mV[VY]; | ||
431 | // should now have the x,y coords of grab_point in screen space | ||
432 | const LLRect& window_rect = gViewerWindow->getVirtualWindowRect(); | ||
433 | |||
434 | // ...sanity check | ||
435 | S32 int_x = lltrunc(x); | ||
436 | S32 int_y = lltrunc(y); | ||
437 | |||
438 | // find the center | ||
439 | GLdouble center_x = (GLdouble)(0.5f * (window_rect.mLeft + window_rect.mRight)); | ||
440 | GLdouble center_y = (GLdouble)(0.5f * (window_rect.mBottom + window_rect.mTop)); | ||
441 | |||
442 | if (x == center_x && y == center_y) | ||
443 | { | ||
444 | // can't project to edge from exact center | ||
445 | return FALSE; | ||
446 | } | ||
447 | |||
448 | // find the line from center to local | ||
449 | GLdouble line_x = x - center_x; | ||
450 | GLdouble line_y = y - center_y; | ||
451 | |||
452 | int_x = lltrunc(center_x); | ||
453 | int_y = lltrunc(center_y); | ||
454 | |||
455 | |||
456 | if (0.f == line_x) | ||
457 | { | ||
458 | // the slope of the line is undefined | ||
459 | if (line_y > 0.f) | ||
460 | { | ||
461 | int_y = window_rect.mTop; | ||
462 | } | ||
463 | else | ||
464 | { | ||
465 | int_y = window_rect.mBottom; | ||
466 | } | ||
467 | } | ||
468 | else if (0 == window_rect.getWidth()) | ||
469 | { | ||
470 | // the diagonal slope of the view is undefined | ||
471 | if (y < window_rect.mBottom) | ||
472 | { | ||
473 | int_y = window_rect.mBottom; | ||
474 | } | ||
475 | else if ( y > window_rect.mTop) | ||
476 | { | ||
477 | int_y = window_rect.mTop; | ||
478 | } | ||
479 | } | ||
480 | else | ||
481 | { | ||
482 | F32 line_slope = (F32)(line_y / line_x); | ||
483 | F32 rect_slope = ((F32)window_rect.getHeight()) / ((F32)window_rect.getWidth()); | ||
484 | |||
485 | if (fabs(line_slope) > rect_slope) | ||
486 | { | ||
487 | if (line_y < 0.f) | ||
488 | { | ||
489 | // bottom | ||
490 | int_y = window_rect.mBottom; | ||
491 | } | ||
492 | else | ||
493 | { | ||
494 | // top | ||
495 | int_y = window_rect.mTop; | ||
496 | } | ||
497 | int_x = lltrunc(((GLdouble)int_y - center_y) / line_slope + center_x); | ||
498 | } | ||
499 | else if (fabs(line_slope) < rect_slope) | ||
500 | { | ||
501 | if (line_x < 0.f) | ||
502 | { | ||
503 | // left | ||
504 | int_x = window_rect.mLeft; | ||
505 | } | ||
506 | else | ||
507 | { | ||
508 | // right | ||
509 | int_x = window_rect.mRight; | ||
510 | } | ||
511 | int_y = lltrunc(((GLdouble)int_x - center_x) * line_slope + center_y); | ||
512 | } | ||
513 | else | ||
514 | { | ||
515 | // exactly parallel ==> push to the corners | ||
516 | if (line_x > 0.f) | ||
517 | { | ||
518 | int_x = window_rect.mRight; | ||
519 | } | ||
520 | else | ||
521 | { | ||
522 | int_x = window_rect.mLeft; | ||
523 | } | ||
524 | if (line_y > 0.0f) | ||
525 | { | ||
526 | int_y = window_rect.mTop; | ||
527 | } | ||
528 | else | ||
529 | { | ||
530 | int_y = window_rect.mBottom; | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | if (!in_front) | ||
535 | { | ||
536 | int_x = window_rect.mLeft + window_rect.mRight - int_x; | ||
537 | int_y = window_rect.mBottom + window_rect.mTop - int_y; | ||
538 | } | ||
539 | out_point.mX = int_x; | ||
540 | out_point.mY = int_y; | ||
541 | return TRUE; | ||
542 | } | ||
543 | return FALSE; | ||
544 | } | ||
545 | |||
546 | |||
547 | void LLViewerCamera::getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right) | ||
548 | { | ||
549 | LLVector3 to_vec = pos_agent - getOrigin(); | ||
550 | |||
551 | F32 at_dist = to_vec * getAtAxis(); | ||
552 | |||
553 | F32 height_meters = at_dist* (F32)tan(getView()/2.f); | ||
554 | F32 height_pixels = getViewHeightInPixels()/2.f; | ||
555 | |||
556 | F32 pixel_aspect = gViewerWindow->getWindow()->getPixelAspectRatio(); | ||
557 | |||
558 | F32 meters_per_pixel = height_meters / height_pixels; | ||
559 | up = getUpAxis() * meters_per_pixel * gViewerWindow->getDisplayScale().mV[VY]; | ||
560 | right = -1.f * pixel_aspect * meters_per_pixel * getLeftAxis() * gViewerWindow->getDisplayScale().mV[VX]; | ||
561 | } | ||
562 | |||
563 | LLVector3 LLViewerCamera::roundToPixel(const LLVector3 &pos_agent) | ||
564 | { | ||
565 | F32 dist = (pos_agent - getOrigin()).magVec(); | ||
566 | // Convert to screen space and back, preserving the depth. | ||
567 | LLCoordGL screen_point; | ||
568 | if (!projectPosAgentToScreen(pos_agent, screen_point, FALSE)) | ||
569 | { | ||
570 | // Off the screen, just return the original position. | ||
571 | return pos_agent; | ||
572 | } | ||
573 | |||
574 | LLVector3 ray_dir; | ||
575 | |||
576 | projectScreenToPosAgent(screen_point.mX, screen_point.mY, &ray_dir); | ||
577 | ray_dir -= getOrigin(); | ||
578 | ray_dir.normVec(); | ||
579 | |||
580 | LLVector3 pos_agent_rounded = getOrigin() + ray_dir*dist; | ||
581 | |||
582 | /* | ||
583 | LLVector3 pixel_x, pixel_y; | ||
584 | getPixelVectors(pos_agent_rounded, pixel_y, pixel_x); | ||
585 | pos_agent_rounded += 0.5f*pixel_x, 0.5f*pixel_y; | ||
586 | */ | ||
587 | return pos_agent_rounded; | ||
588 | } | ||
589 | |||
590 | BOOL LLViewerCamera::cameraUnderWater() const | ||
591 | { | ||
592 | return getOrigin().mV[VZ] < gAgent.getRegion()->getWaterHeight(); | ||
593 | } | ||
594 | |||
595 | BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) | ||
596 | { | ||
597 | S32 i, num_faces; | ||
598 | LLDrawable* drawablep = volumep->mDrawable; | ||
599 | |||
600 | if (!drawablep) | ||
601 | { | ||
602 | return FALSE; | ||
603 | } | ||
604 | |||
605 | num_faces = drawablep->getNumFaces(); | ||
606 | for (i = 0; i < num_faces; i++) | ||
607 | { | ||
608 | LLStrider<LLVector3> vertices; | ||
609 | LLFace* face = drawablep->getFace(i); | ||
610 | face->getVertices(vertices); | ||
611 | |||
612 | for (S32 v = 0; v < (S32)drawablep->getFace(i)->getGeomCount(); v++) | ||
613 | { | ||
614 | LLVector3 vec = vertices[v]; | ||
615 | if (!face->isState(LLFace::GLOBAL)) | ||
616 | { | ||
617 | vec = vec*face->getRenderMatrix(); | ||
618 | } | ||
619 | |||
620 | BOOL in_frustum = pointInFrustum(vec) > 0; | ||
621 | |||
622 | if ( !in_frustum && all_verts || | ||
623 | in_frustum && !all_verts) | ||
624 | { | ||
625 | return !all_verts; | ||
626 | } | ||
627 | } | ||
628 | } | ||
629 | return all_verts; | ||
630 | } | ||