aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewercamera.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:34 -0500
committerJacek Antonelli2008-08-15 23:45:34 -0500
commitcd17687f01420952712a500107e0f93e7ab8d5f8 (patch)
treece48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/newview/llviewercamera.cpp
parentSecond Life viewer sources 1.19.0.5 (diff)
downloadmeta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz
Second Life viewer sources 1.19.1.0
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llviewercamera.cpp195
1 files changed, 142 insertions, 53 deletions
diff --git a/linden/indra/newview/llviewercamera.cpp b/linden/indra/newview/llviewercamera.cpp
index 0a8e8c2..7c4271a 100644
--- a/linden/indra/newview/llviewercamera.cpp
+++ b/linden/indra/newview/llviewercamera.cpp
@@ -48,16 +48,46 @@
48#include "llvovolume.h" 48#include "llvovolume.h"
49#include "llworld.h" 49#include "llworld.h"
50 50
51GLfloat gGLZFar;
52GLfloat gGLZNear;
53
51LLViewerCamera *gCamera = NULL; 54LLViewerCamera *gCamera = NULL;
52 55
56//glu pick matrix implementation borrowed from Mesa3D
57glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport)
58{
59 GLfloat m[16];
60 GLfloat sx, sy;
61 GLfloat tx, ty;
62
63 sx = viewport[2] / width;
64 sy = viewport[3] / height;
65 tx = (viewport[2] + 2.f * (viewport[0] - x)) / width;
66 ty = (viewport[3] + 2.f * (viewport[1] - y)) / height;
67
68 #define M(row,col) m[col*4+row]
69 M(0,0) = sx; M(0,1) = 0.f; M(0,2) = 0.f; M(0,3) = tx;
70 M(1,0) = 0.f; M(1,1) = sy; M(1,2) = 0.f; M(1,3) = ty;
71 M(2,0) = 0.f; M(2,1) = 0.f; M(2,2) = 1.f; M(2,3) = 0.f;
72 M(3,0) = 0.f; M(3,1) = 0.f; M(3,2) = 0.f; M(3,3) = 1.f;
73 #undef M
74
75 return glh::matrix4f(m);
76}
77
78glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
79{
80 GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f);
81
82 return glh::matrix4f(f/aspect, 0, 0, 0,
83 0, f, 0, 0,
84 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar),
85 0, 0, -1.f, 0);
86}
87
53LLViewerCamera::LLViewerCamera() : LLCamera() 88LLViewerCamera::LLViewerCamera() : LLCamera()
54{ 89{
55 calcProjection(getFar()); 90 calcProjection(getFar());
56 S32 i;
57 for (i = 0; i < 16; i++)
58 {
59 mGLProjectionMatrix[i] = 0.f;
60 }
61 mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; 91 mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
62 mPixelMeterRatio = 0.f; 92 mPixelMeterRatio = 0.f;
63 mScreenPixelArea = 0; 93 mScreenPixelArea = 0;
@@ -79,7 +109,20 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
79 // constrain to max distance from avatar 109 // constrain to max distance from avatar
80 LLVector3 camera_offset = center - gAgent.getPositionAgent(); 110 LLVector3 camera_offset = center - gAgent.getPositionAgent();
81 111
82 setOriginAndLookAt(center, up_direction, point_of_interest); 112 LLViewerRegion * regp = gAgent.getRegion();
113 F32 water_height = (NULL != regp) ? regp->getWaterHeight() : 0.f;
114
115 LLVector3 origin = center;
116 if (origin.mV[2] > water_height)
117 {
118 origin.mV[2] = llmax(origin.mV[2], water_height+0.20f);
119 }
120 else
121 {
122 origin.mV[2] = llmin(origin.mV[2], water_height-0.20f);
123 }
124
125 setOriginAndLookAt(origin, up_direction, point_of_interest);
83 126
84 F32 dpos = (center - last_position).magVec(); 127 F32 dpos = (center - last_position).magVec();
85 LLQuaternion rotation; 128 LLQuaternion rotation;
@@ -98,6 +141,7 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
98 141
99// Handy copies of last good GL matrices 142// Handy copies of last good GL matrices
100F64 gGLModelView[16]; 143F64 gGLModelView[16];
144F64 gGLLastModelView[16];
101F64 gGLProjection[16]; 145F64 gGLProjection[16];
102S32 gGLViewport[4]; 146S32 gGLViewport[4];
103 147
@@ -139,46 +183,70 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const
139// The picking region is centered on x,y and has the specified width and 183// The picking region is centered on x,y and has the specified width and
140// height. 184// height.
141 185
142LLMatrix4 gProjectionMat;
143
144//static 186//static
145void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho) 187void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip)
146{ 188{
147 GLint viewport[4]; 189 GLint* viewport = (GLint*) gGLViewport;
148 GLdouble model[16]; 190 GLdouble* model = gGLModelView;
149 GLdouble proj[16]; 191 GLdouble* proj = gGLProjection;
150 GLdouble objX,objY,objZ; 192 GLdouble objX,objY,objZ;
151 193
152 LLVector3 frust[8]; 194 LLVector3 frust[8];
153 195
154 glGetIntegerv(GL_VIEWPORT, viewport); 196 if (zflip)
155 glGetDoublev(GL_MODELVIEW_MATRIX, model);
156 glGetDoublev(GL_PROJECTION_MATRIX,proj);
157
158 gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
159 frust[0].setVec((F32)objX,(F32)objY,(F32)objZ);
160 gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
161 frust[1].setVec((F32)objX,(F32)objY,(F32)objZ);
162 gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
163 frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
164 gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
165 frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
166
167 if (ortho)
168 { 197 {
169 LLVector3 far_shift = LLVector3(camera.getFar()*2.0f,0,0); 198 gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
199 frust[0].setVec((F32)objX,(F32)objY,(F32)objZ);
200 gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
201 frust[1].setVec((F32)objX,(F32)objY,(F32)objZ);
202 gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
203 frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
204 gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
205 frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
206
207 gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
208 frust[4].setVec((F32)objX,(F32)objY,(F32)objZ);
209 gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
210 frust[5].setVec((F32)objX,(F32)objY,(F32)objZ);
211 gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
212 frust[6].setVec((F32)objX,(F32)objY,(F32)objZ);
213 gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
214 frust[7].setVec((F32)objX,(F32)objY,(F32)objZ);
215
170 for (U32 i = 0; i < 4; i++) 216 for (U32 i = 0; i < 4; i++)
171 { 217 {
172 frust[i+4] = frust[i] + far_shift; 218 frust[i+4] = frust[i+4]-frust[i];
219 frust[i+4].normVec();
220 frust[i+4] = frust[i] + frust[i+4]*camera.getFar();
173 } 221 }
174 } 222 }
175 else 223 else
176 { 224 {
177 for (U32 i = 0; i < 4; i++) 225 gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
226 frust[0].setVec((F32)objX,(F32)objY,(F32)objZ);
227 gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
228 frust[1].setVec((F32)objX,(F32)objY,(F32)objZ);
229 gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
230 frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
231 gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
232 frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
233
234 if (ortho)
178 { 235 {
179 LLVector3 vec = frust[i] - camera.getOrigin(); 236 LLVector3 far_shift = LLVector3(camera.getFar()*2.0f,0,0);
180 vec.normVec(); 237 for (U32 i = 0; i < 4; i++)
181 frust[i+4] = camera.getOrigin() + vec*camera.getFar()*2.0f; 238 {
239 frust[i+4] = frust[i] + far_shift;
240 }
241 }
242 else
243 {
244 for (U32 i = 0; i < 4; i++)
245 {
246 LLVector3 vec = frust[i] - camera.getOrigin();
247 vec.normVec();
248 frust[i+4] = camera.getOrigin() + vec*camera.getFar();
249 }
182 } 250 }
183 } 251 }
184 252
@@ -209,14 +277,15 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
209 glMatrixMode( GL_PROJECTION ); 277 glMatrixMode( GL_PROJECTION );
210 glLoadIdentity(); 278 glLoadIdentity();
211 279
280 glh::matrix4f proj_mat;
281
212 if (for_selection) 282 if (for_selection)
213 { 283 {
214 // make a tiny little viewport 284 // make a tiny little viewport
215 // anything drawn into this viewport will be "selected" 285 // anything drawn into this viewport will be "selected"
216 const U8 VIEWPORT_VECTOR_LEN = 4; 286 GLint* viewport = (GLint*) gGLViewport;
217 GLint viewport[VIEWPORT_VECTOR_LEN]; 287
218 glGetIntegerv(GL_VIEWPORT, viewport); 288 proj_mat = gl_pick_matrix(x+width/2.f, y_from_bot+height/2.f, (GLfloat) width, (GLfloat) height, viewport);
219 gluPickMatrix(x + width / 2, y_from_bot + height / 2, width, height, viewport);
220 289
221 if (limit_select_distance) 290 if (limit_select_distance)
222 { 291 {
@@ -236,6 +305,10 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
236 z_far = MAX_FAR_CLIP; 305 z_far = MAX_FAR_CLIP;
237 } 306 }
238 glViewport(x, y_from_bot, width, height); 307 glViewport(x, y_from_bot, width, height);
308 gGLViewport[0] = x;
309 gGLViewport[1] = y_from_bot;
310 gGLViewport[2] = width;
311 gGLViewport[3] = height;
239 } 312 }
240 313
241 if (mZoomFactor > 1.f) 314 if (mZoomFactor > 1.f)
@@ -243,27 +316,41 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
243 float offset = mZoomFactor - 1.f; 316 float offset = mZoomFactor - 1.f;
244 int pos_y = mZoomSubregion / llceil(mZoomFactor); 317 int pos_y = mZoomSubregion / llceil(mZoomFactor);
245 int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor)); 318 int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor));
246 glTranslatef(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f); 319 glh::matrix4f translate;
247 glScalef(mZoomFactor, mZoomFactor, 1.f); 320 translate.set_translate(glh::vec3f(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f));
321 glh::matrix4f scale;
322 scale.set_scale(glh::vec3f(mZoomFactor, mZoomFactor, 1.f));
323
324 proj_mat = scale*proj_mat;
325 proj_mat = translate*proj_mat;
248 } 326 }
249 327
250 calcProjection(z_far); // Update the projection matrix cache 328 calcProjection(z_far); // Update the projection matrix cache
251 329
252 gluPerspective(fov_y, 330 proj_mat *= gl_perspective(fov_y,aspect,z_near,z_far);
253 aspect, 331
254 z_near, 332 glLoadMatrixf(proj_mat.m);
255 z_far); 333
256 glGetDoublev(GL_PROJECTION_MATRIX, gGLProjection); 334 for (U32 i = 0; i < 16; i++)
257 glGetFloatv(GL_PROJECTION_MATRIX, (float*)&gProjectionMat); 335 {
258 336 gGLProjection[i] = proj_mat.m[i];
337 }
338
339 gGLZNear = z_near;
340 gGLZFar = z_far;
341
259 glMatrixMode( GL_MODELVIEW ); 342 glMatrixMode( GL_MODELVIEW );
260 343
261 glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame 344 glh::matrix4f modelview((GLfloat*) OGL_TO_CFR_ROTATION);
262 345
263 GLfloat ogl_matrix[16]; 346 GLfloat ogl_matrix[16];
347
264 getOpenGLTransform(ogl_matrix); 348 getOpenGLTransform(ogl_matrix);
265 glMultMatrixf(ogl_matrix);
266 349
350 modelview *= glh::matrix4f(ogl_matrix);
351
352 glLoadMatrixf(modelview.m);
353
267 if (for_selection && (width > 1 || height > 1)) 354 if (for_selection && (width > 1 || height > 1))
268 { 355 {
269 calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f, 356 calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f,
@@ -277,9 +364,11 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
277 if (!for_selection && mZoomFactor == 1.f) 364 if (!for_selection && mZoomFactor == 1.f)
278 { 365 {
279 // Save GL matrices for access elsewhere in code, especially project_world_to_screen 366 // Save GL matrices for access elsewhere in code, especially project_world_to_screen
280 glGetDoublev(GL_PROJECTION_MATRIX, mGLProjectionMatrix); 367 //glGetDoublev(GL_MODELVIEW_MATRIX, gGLModelView);
281 glGetDoublev(GL_MODELVIEW_MATRIX, gGLModelView); 368 for (U32 i = 0; i < 16; i++)
282 glGetIntegerv(GL_VIEWPORT, (GLint*)gGLViewport); 369 {
370 gGLModelView[i] = modelview.m[i];
371 }
283 } 372 }
284 373
285 updateFrustumPlanes(*this); 374 updateFrustumPlanes(*this);
@@ -302,7 +391,7 @@ void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 scree
302 GLdouble x, y, z; 391 GLdouble x, y, z;
303 gluUnProject( 392 gluUnProject(
304 GLdouble(screen_x), GLdouble(screen_y), 0.0, 393 GLdouble(screen_x), GLdouble(screen_y), 0.0,
305 gGLModelView, mGLProjectionMatrix, (GLint*)gGLViewport, 394 gGLModelView, gGLProjection, (GLint*)gGLViewport,
306 &x, 395 &x,
307 &y, 396 &y,
308 &z ); 397 &z );
@@ -333,7 +422,7 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord
333 } 422 }
334 423
335 if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], 424 if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ],
336 gGLModelView, mGLProjectionMatrix, (GLint*)gGLViewport, 425 gGLModelView, gGLProjection, (GLint*)gGLViewport,
337 &x, &y, &z)) 426 &x, &y, &z))
338 { 427 {
339 // convert screen coordinates to virtual UI coordinates 428 // convert screen coordinates to virtual UI coordinates
@@ -431,7 +520,7 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
431 GLdouble x, y, z; // object's window coords, GL-style 520 GLdouble x, y, z; // object's window coords, GL-style
432 if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], 521 if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY],
433 pos_agent.mV[VZ], gGLModelView, 522 pos_agent.mV[VZ], gGLModelView,
434 mGLProjectionMatrix, (GLint*)gGLViewport, 523 gGLProjection, (GLint*)gGLViewport,
435 &x, &y, &z)) 524 &x, &y, &z))
436 { 525 {
437 x /= gViewerWindow->getDisplayScale().mV[VX]; 526 x /= gViewerWindow->getDisplayScale().mV[VX];