llviewercamera.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 #include "llviewercamera.h"
00034 
00035 #include <iomanip> // for setprecision
00036 
00037 #include "llquaternion.h"
00038 
00039 #include "llagent.h"
00040 #include "llviewercontrol.h"
00041 #include "lldrawable.h"
00042 #include "llface.h"
00043 #include "llgl.h"
00044 #include "llglheaders.h"
00045 #include "llviewerobjectlist.h"
00046 #include "llviewerregion.h"
00047 #include "llviewerwindow.h"
00048 #include "llvovolume.h"
00049 #include "llworld.h"
00050 #include "lltoolmgr.h"
00051 #include "llviewerjoystick.h"
00052 
00053 GLfloat gGLZFar;
00054 GLfloat gGLZNear;
00055 
00056 //glu pick matrix implementation borrowed from Mesa3D
00057 glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport)
00058 {
00059         GLfloat m[16];
00060         GLfloat sx, sy;
00061         GLfloat tx, ty;
00062 
00063         sx = viewport[2] / width;
00064         sy = viewport[3] / height;
00065         tx = (viewport[2] + 2.f * (viewport[0] - x)) / width;
00066         ty = (viewport[3] + 2.f * (viewport[1] - y)) / height;
00067 
00068         #define M(row,col) m[col*4+row]
00069         M(0,0) = sx; M(0,1) = 0.f; M(0,2) = 0.f; M(0,3) = tx;
00070         M(1,0) = 0.f; M(1,1) = sy; M(1,2) = 0.f; M(1,3) = ty;
00071         M(2,0) = 0.f; M(2,1) = 0.f; M(2,2) = 1.f; M(2,3) = 0.f;
00072         M(3,0) = 0.f; M(3,1) = 0.f; M(3,2) = 0.f; M(3,3) = 1.f;
00073         #undef M
00074 
00075         return glh::matrix4f(m);
00076 }
00077 
00078 glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
00079 {
00080         GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f);
00081 
00082         return glh::matrix4f(f/aspect, 0, 0, 0,
00083                                                  0, f, 0, 0,
00084                                                  0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar),
00085                                                  0, 0, -1.f, 0);
00086 }
00087 
00088 LLViewerCamera::LLViewerCamera() : LLCamera()
00089 {
00090         calcProjection(getFar());
00091         mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;
00092         mPixelMeterRatio = 0.f;
00093         mScreenPixelArea = 0;
00094         mZoomFactor = 1.f;
00095         mZoomSubregion = 1;
00096 }
00097 
00098 void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
00099                                                                                         const LLVector3 &up_direction,
00100                                                                                         const LLVector3 &point_of_interest)
00101 {
00102         // do not update if we are in build mode AND avatar didn't move
00103         if (LLToolMgr::getInstance()->inBuildMode() 
00104                 && !LLViewerJoystick::getInstance()->getCameraNeedsUpdate())
00105         {
00106                 return;
00107         }
00108 
00109         LLVector3 last_position;
00110         LLVector3 last_axis;
00111         last_position = getOrigin();
00112         last_axis = getAtAxis();
00113 
00114         mLastPointOfInterest = point_of_interest;
00115 
00116         // constrain to max distance from avatar
00117         LLVector3 camera_offset = center - gAgent.getPositionAgent();
00118 
00119         LLViewerRegion * regp = gAgent.getRegion();
00120         F32 water_height = (NULL != regp) ? regp->getWaterHeight() : 0.f;
00121 
00122         LLVector3 origin = center;
00123         if (origin.mV[2] > water_height)
00124         {
00125                 origin.mV[2] = llmax(origin.mV[2], water_height+0.20f);
00126         }
00127         else
00128         {
00129                 origin.mV[2] = llmin(origin.mV[2], water_height-0.20f);
00130         }
00131 
00132         setOriginAndLookAt(origin, up_direction, point_of_interest);
00133 
00134         F32 dpos = (center - last_position).magVec();
00135         LLQuaternion rotation;
00136         rotation.shortestArc(last_axis, getAtAxis());
00137 
00138         F32 x, y, z;
00139         F32 drot;
00140         rotation.getAngleAxis(&drot, &x, &y, &z);
00141         mVelocityStat.addValue(dpos);
00142         mAngularVelocityStat.addValue(drot);
00143         // update pixel meter ratio using default fov, not modified one
00144         mPixelMeterRatio = mViewHeightInPixels / (2.f*tanf(mCameraFOVDefault*0.5));
00145         // update screen pixel area
00146         mScreenPixelArea =(S32)((F32)mViewHeightInPixels * ((F32)mViewHeightInPixels * mAspect));
00147 }
00148 
00149 // Handy copies of last good GL matrices
00150 F64     gGLModelView[16];
00151 F64     gGLLastModelView[16];
00152 F64 gGLProjection[16];
00153 S32     gGLViewport[4];
00154 
00155 const LLMatrix4 &LLViewerCamera::getProjection() const
00156 {
00157         calcProjection(getFar());
00158         return mProjectionMatrix;
00159 
00160 }
00161 
00162 const LLMatrix4 &LLViewerCamera::getModelview() const
00163 {
00164         LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
00165         getMatrixToLocal(mModelviewMatrix);
00166         mModelviewMatrix *= cfr;
00167         return mModelviewMatrix;
00168 }
00169 
00170 void LLViewerCamera::calcProjection(const F32 far_distance) const
00171 {
00172         F32 fov_y, z_far, z_near, aspect, f;
00173         fov_y = getView();
00174         z_far = far_distance;
00175         z_near = getNear();
00176         aspect = getAspect();
00177 
00178         f = 1/tan(fov_y*0.5f);
00179 
00180         mProjectionMatrix.setZero();
00181         mProjectionMatrix.mMatrix[0][0] = f/aspect;
00182         mProjectionMatrix.mMatrix[1][1] = f;
00183         mProjectionMatrix.mMatrix[2][2] = (z_far + z_near)/(z_near - z_far);
00184         mProjectionMatrix.mMatrix[3][2] = (2*z_far*z_near)/(z_near - z_far);
00185         mProjectionMatrix.mMatrix[2][3] = -1;
00186 }
00187 
00188 // Sets up opengl state for 3D drawing.  If for selection, also
00189 // sets up a pick matrix.  x and y are ignored if for_selection is false.
00190 // The picking region is centered on x,y and has the specified width and
00191 // height.
00192 
00193 //static
00194 void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip)
00195 {
00196         GLint* viewport = (GLint*) gGLViewport;
00197         GLdouble* model = gGLModelView;
00198         GLdouble* proj = gGLProjection;
00199         GLdouble objX,objY,objZ;
00200 
00201         LLVector3 frust[8];
00202 
00203         if (zflip)
00204         {
00205                 gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
00206                 frust[0].setVec((F32)objX,(F32)objY,(F32)objZ);
00207                 gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
00208                 frust[1].setVec((F32)objX,(F32)objY,(F32)objZ);
00209                 gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
00210                 frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
00211                 gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
00212                 frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
00213 
00214                 gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
00215                 frust[4].setVec((F32)objX,(F32)objY,(F32)objZ);
00216                 gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ);
00217                 frust[5].setVec((F32)objX,(F32)objY,(F32)objZ);
00218                 gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
00219                 frust[6].setVec((F32)objX,(F32)objY,(F32)objZ);
00220                 gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ);
00221                 frust[7].setVec((F32)objX,(F32)objY,(F32)objZ);
00222 
00223                 for (U32 i = 0; i < 4; i++)
00224                 {
00225                         frust[i+4] = frust[i+4]-frust[i];
00226                         frust[i+4].normVec();
00227                         frust[i+4] = frust[i] + frust[i+4]*camera.getFar();
00228                 }
00229         }
00230         else
00231         {
00232                 gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
00233                 frust[0].setVec((F32)objX,(F32)objY,(F32)objZ);
00234                 gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ);
00235                 frust[1].setVec((F32)objX,(F32)objY,(F32)objZ);
00236                 gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
00237                 frust[2].setVec((F32)objX,(F32)objY,(F32)objZ);
00238                 gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ);
00239                 frust[3].setVec((F32)objX,(F32)objY,(F32)objZ);
00240                 
00241                 if (ortho)
00242                 {
00243                         LLVector3 far_shift = LLVector3(camera.getFar()*2.0f,0,0);
00244                         for (U32 i = 0; i < 4; i++)
00245                         {
00246                                 frust[i+4] = frust[i] + far_shift;
00247                         }
00248                 }
00249                 else
00250                 {
00251                         for (U32 i = 0; i < 4; i++)
00252                         {
00253                                 LLVector3 vec = frust[i] - camera.getOrigin();
00254                                 vec.normVec();
00255                                 frust[i+4] = camera.getOrigin() + vec*camera.getFar();
00256                         }
00257                 }
00258         }
00259 
00260         camera.calcAgentFrustumPlanes(frust);
00261 }
00262 
00263 void LLViewerCamera::setPerspective(BOOL for_selection,
00264                                                                         S32 x, S32 y_from_bot, S32 width, S32 height,
00265                                                                         BOOL limit_select_distance,
00266                                                                         F32 z_near, F32 z_far)
00267 {
00268         F32 fov_y, aspect;
00269         fov_y = RAD_TO_DEG * getView();
00270         BOOL z_default_near, z_default_far = FALSE;
00271         if (z_far <= 0)
00272         {
00273                 z_default_far = TRUE;
00274                 z_far = getFar();
00275         }
00276         if (z_near <= 0)
00277         {
00278                 z_default_near = TRUE;
00279                 z_near = getNear();
00280         }
00281         aspect = getAspect();
00282 
00283         // Load camera view matrix
00284         glMatrixMode( GL_PROJECTION );
00285         glLoadIdentity();
00286 
00287         glh::matrix4f proj_mat;
00288 
00289         if (for_selection)
00290         {
00291                 // make a tiny little viewport
00292                 // anything drawn into this viewport will be "selected"
00293                 GLint*          viewport = (GLint*) gGLViewport;
00294                 
00295                 proj_mat = gl_pick_matrix(x+width/2.f, y_from_bot+height/2.f, (GLfloat) width, (GLfloat) height, viewport);
00296 
00297                 if (limit_select_distance)
00298                 {
00299                         // ...select distance from control
00300                         z_far = gSavedSettings.getF32("MaxSelectDistance");
00301                 }
00302                 else
00303                 {
00304                         z_far = gAgent.mDrawDistance;
00305                 }
00306         }
00307         else
00308         {
00309                 // Only override the far clip if it's not passed in explicitly.
00310                 if (z_default_far)
00311                 {
00312                         z_far = MAX_FAR_CLIP;
00313                 }
00314                 glViewport(x, y_from_bot, width, height);
00315                 gGLViewport[0] = x;
00316                 gGLViewport[1] = y_from_bot;
00317                 gGLViewport[2] = width;
00318                 gGLViewport[3] = height;
00319         }
00320         
00321         if (mZoomFactor > 1.f)
00322         {
00323                 float offset = mZoomFactor - 1.f;
00324                 int pos_y = mZoomSubregion / llceil(mZoomFactor);
00325                 int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor));
00326                 glh::matrix4f translate;
00327                 translate.set_translate(glh::vec3f(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f));
00328                 glh::matrix4f scale;
00329                 scale.set_scale(glh::vec3f(mZoomFactor, mZoomFactor, 1.f));
00330 
00331                 proj_mat = scale*proj_mat;
00332                 proj_mat = translate*proj_mat;
00333         }
00334 
00335         calcProjection(z_far); // Update the projection matrix cache
00336 
00337         proj_mat *= gl_perspective(fov_y,aspect,z_near,z_far);
00338 
00339         glLoadMatrixf(proj_mat.m);
00340 
00341         for (U32 i = 0; i < 16; i++)
00342         {
00343                 gGLProjection[i] = proj_mat.m[i];
00344         }
00345 
00346         gGLZNear = z_near;
00347         gGLZFar = z_far;
00348 
00349         glMatrixMode( GL_MODELVIEW );
00350 
00351         glh::matrix4f modelview((GLfloat*) OGL_TO_CFR_ROTATION);
00352 
00353         GLfloat                 ogl_matrix[16];
00354 
00355         getOpenGLTransform(ogl_matrix);
00356 
00357         modelview *= glh::matrix4f(ogl_matrix);
00358         
00359         glLoadMatrixf(modelview.m);
00360         
00361         if (for_selection && (width > 1 || height > 1))
00362         {
00363                 calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f,
00364                                                                 (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f,
00365                                                                 (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f,
00366                                                                 (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f);
00367 
00368         }
00369 
00370         // if not picking and not doing a snapshot, cache various GL matrices
00371         if (!for_selection && mZoomFactor == 1.f)
00372         {
00373                 // Save GL matrices for access elsewhere in code, especially project_world_to_screen
00374                 //glGetDoublev(GL_MODELVIEW_MATRIX, gGLModelView);
00375                 for (U32 i = 0; i < 16; i++)
00376                 {
00377                         gGLModelView[i] = modelview.m[i];
00378                 }
00379         }
00380 
00381         updateFrustumPlanes(*this);
00382 
00383         if (gSavedSettings.getBOOL("CameraOffset"))
00384         {
00385                 glMatrixMode(GL_PROJECTION);
00386                 glTranslatef(0,0,-50);
00387                 glRotatef(20.0,1,0,0);
00388                 glMatrixMode(GL_MODELVIEW);
00389         }
00390 }
00391 
00392 
00393 // Uses the last GL matrices set in set_perspective to project a point from
00394 // screen coordinates to the agent's region.
00395 void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 screen_y, LLVector3* pos_agent) const
00396 {
00397 
00398         GLdouble x, y, z;
00399         gluUnProject(
00400                 GLdouble(screen_x), GLdouble(screen_y), 0.0,
00401                 gGLModelView, gGLProjection, (GLint*)gGLViewport,
00402                 &x,
00403                 &y,
00404                 &z );
00405         pos_agent->setVec( (F32)x, (F32)y, (F32)z );
00406 }
00407 
00408 // Uses the last GL matrices set in set_perspective to project a point from
00409 // the agent's region space to screen coordinates.  Returns TRUE if point in within
00410 // the current window.
00411 BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp) const
00412 {
00413         BOOL in_front = TRUE;
00414         GLdouble        x, y, z;                        // object's window coords, GL-style
00415 
00416         LLVector3 dir_to_point = pos_agent - getOrigin();
00417         dir_to_point /= dir_to_point.magVec();
00418 
00419         if (dir_to_point * getAtAxis() < 0.f)
00420         {
00421                 if (clamp)
00422                 {
00423                         return FALSE;
00424                 }
00425                 else
00426                 {
00427                         in_front = FALSE;
00428                 }
00429         }
00430 
00431         if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ],
00432                                                                 gGLModelView, gGLProjection, (GLint*)gGLViewport,
00433                                                                 &x, &y, &z))
00434         {
00435                 // convert screen coordinates to virtual UI coordinates
00436                 x /= gViewerWindow->getDisplayScale().mV[VX];
00437                 y /= gViewerWindow->getDisplayScale().mV[VY];
00438 
00439                 // should now have the x,y coords of grab_point in screen space
00440                 const LLRect& window_rect = gViewerWindow->getWindowRect();
00441 
00442                 // ...sanity check
00443                 S32 int_x = lltrunc(x);
00444                 S32 int_y = lltrunc(y);
00445 
00446                 BOOL valid = TRUE;
00447 
00448                 if (clamp)
00449                 {
00450                         if (int_x < window_rect.mLeft)
00451                         {
00452                                 out_point.mX = window_rect.mLeft;
00453                                 valid = FALSE;
00454                         }
00455                         else if (int_x > window_rect.mRight)
00456                         {
00457                                 out_point.mX = window_rect.mRight;
00458                                 valid = FALSE;
00459                         }
00460                         else
00461                         {
00462                                 out_point.mX = int_x;
00463                         }
00464 
00465                         if (int_y < window_rect.mBottom)
00466                         {
00467                                 out_point.mY = window_rect.mBottom;
00468                                 valid = FALSE;
00469                         }
00470                         else if (int_y > window_rect.mTop)
00471                         {
00472                                 out_point.mY = window_rect.mTop;
00473                                 valid = FALSE;
00474                         }
00475                         else
00476                         {
00477                                 out_point.mY = int_y;
00478                         }
00479                         return valid;
00480                 }
00481                 else
00482                 {
00483                         out_point.mX = int_x;
00484                         out_point.mY = int_y;
00485 
00486                         if (int_x < window_rect.mLeft)
00487                         {
00488                                 valid = FALSE;
00489                         }
00490                         else if (int_x > window_rect.mRight)
00491                         {
00492                                 valid = FALSE;
00493                         }
00494                         if (int_y < window_rect.mBottom)
00495                         {
00496                                 valid = FALSE;
00497                         }
00498                         else if (int_y > window_rect.mTop)
00499                         {
00500                                 valid = FALSE;
00501                         }
00502 
00503                         return in_front && valid;
00504                 }
00505         }
00506         else
00507         {
00508                 return FALSE;
00509         }
00510 }
00511 
00512 // Uses the last GL matrices set in set_perspective to project a point from
00513 // the agent's region space to the nearest edge in screen coordinates.
00514 // Returns TRUE if projection succeeds.
00515 BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent,
00516                                                                                                 LLCoordGL &out_point) const
00517 {
00518         LLVector3 dir_to_point = pos_agent - getOrigin();
00519         dir_to_point /= dir_to_point.magVec();
00520 
00521         BOOL in_front = TRUE;
00522         if (dir_to_point * getAtAxis() < 0.f)
00523         {
00524                 in_front = FALSE;
00525         }
00526 
00527         GLdouble        x, y, z;                        // object's window coords, GL-style
00528         if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY],
00529                                                           pos_agent.mV[VZ], gGLModelView,
00530                                                           gGLProjection, (GLint*)gGLViewport,
00531                                                           &x, &y, &z))
00532         {
00533                 x /= gViewerWindow->getDisplayScale().mV[VX];
00534                 y /= gViewerWindow->getDisplayScale().mV[VY];
00535                 // should now have the x,y coords of grab_point in screen space
00536                 const LLRect& window_rect = gViewerWindow->getVirtualWindowRect();
00537 
00538                 // ...sanity check
00539                 S32 int_x = lltrunc(x);
00540                 S32 int_y = lltrunc(y);
00541 
00542                 // find the center
00543                 GLdouble center_x = (GLdouble)(0.5f * (window_rect.mLeft + window_rect.mRight));
00544                 GLdouble center_y = (GLdouble)(0.5f * (window_rect.mBottom + window_rect.mTop));
00545 
00546                 if (x == center_x  &&  y == center_y)
00547                 {
00548                         // can't project to edge from exact center
00549                         return FALSE;
00550                 }
00551 
00552                 // find the line from center to local
00553                 GLdouble line_x = x - center_x;
00554                 GLdouble line_y = y - center_y;
00555 
00556                 int_x = lltrunc(center_x);
00557                 int_y = lltrunc(center_y);
00558 
00559 
00560                 if (0.f == line_x)
00561                 {
00562                         // the slope of the line is undefined
00563                         if (line_y > 0.f)
00564                         {
00565                                 int_y = window_rect.mTop;
00566                         }
00567                         else
00568                         {
00569                                 int_y = window_rect.mBottom;
00570                         }
00571                 }
00572                 else if (0 == window_rect.getWidth())
00573                 {
00574                         // the diagonal slope of the view is undefined
00575                         if (y < window_rect.mBottom)
00576                         {
00577                                 int_y = window_rect.mBottom;
00578                         }
00579                         else if ( y > window_rect.mTop)
00580                         {
00581                                 int_y = window_rect.mTop;
00582                         }
00583                 }
00584                 else
00585                 {
00586                         F32 line_slope = (F32)(line_y / line_x);
00587                         F32 rect_slope = ((F32)window_rect.getHeight()) / ((F32)window_rect.getWidth());
00588 
00589                         if (fabs(line_slope) > rect_slope)
00590                         {
00591                                 if (line_y < 0.f)
00592                                 {
00593                                         // bottom
00594                                         int_y = window_rect.mBottom;
00595                                 }
00596                                 else
00597                                 {
00598                                         // top
00599                                         int_y = window_rect.mTop;
00600                                 }
00601                                 int_x = lltrunc(((GLdouble)int_y - center_y) / line_slope + center_x);
00602                         }
00603                         else if (fabs(line_slope) < rect_slope)
00604                         {
00605                                 if (line_x < 0.f)
00606                                 {
00607                                         // left
00608                                         int_x = window_rect.mLeft;
00609                                 }
00610                                 else
00611                                 {
00612                                         // right
00613                                         int_x = window_rect.mRight;
00614                                 }
00615                                 int_y = lltrunc(((GLdouble)int_x - center_x) * line_slope + center_y);
00616                         }
00617                         else
00618                         {
00619                                 // exactly parallel ==> push to the corners
00620                                 if (line_x > 0.f)
00621                                 {
00622                                         int_x = window_rect.mRight;
00623                                 }
00624                                 else
00625                                 {
00626                                         int_x = window_rect.mLeft;
00627                                 }
00628                                 if (line_y > 0.0f)
00629                                 {
00630                                         int_y = window_rect.mTop;
00631                                 }
00632                                 else
00633                                 {
00634                                         int_y = window_rect.mBottom;
00635                                 }
00636                         }
00637                 }
00638                 if (!in_front)
00639                 {
00640                         int_x = window_rect.mLeft + window_rect.mRight - int_x;
00641                         int_y = window_rect.mBottom + window_rect.mTop - int_y;
00642                 }
00643                 out_point.mX = int_x;
00644                 out_point.mY = int_y;
00645                 return TRUE;
00646         }
00647         return FALSE;
00648 }
00649 
00650 
00651 void LLViewerCamera::getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right)
00652 {
00653         LLVector3 to_vec = pos_agent - getOrigin();
00654 
00655         F32 at_dist = to_vec * getAtAxis();
00656 
00657         F32 height_meters = at_dist* (F32)tan(getView()/2.f);
00658         F32 height_pixels = getViewHeightInPixels()/2.f;
00659 
00660         F32 pixel_aspect = gViewerWindow->getWindow()->getPixelAspectRatio();
00661 
00662         F32 meters_per_pixel = height_meters / height_pixels;
00663         up = getUpAxis() * meters_per_pixel * gViewerWindow->getDisplayScale().mV[VY];
00664         right = -1.f * pixel_aspect * meters_per_pixel * getLeftAxis() * gViewerWindow->getDisplayScale().mV[VX];
00665 }
00666 
00667 LLVector3 LLViewerCamera::roundToPixel(const LLVector3 &pos_agent)
00668 {
00669         F32 dist = (pos_agent - getOrigin()).magVec();
00670         // Convert to screen space and back, preserving the depth.
00671         LLCoordGL screen_point;
00672         if (!projectPosAgentToScreen(pos_agent, screen_point, FALSE))
00673         {
00674                 // Off the screen, just return the original position.
00675                 return pos_agent;
00676         }
00677 
00678         LLVector3 ray_dir;
00679 
00680         projectScreenToPosAgent(screen_point.mX, screen_point.mY, &ray_dir);
00681         ray_dir -= getOrigin();
00682         ray_dir.normVec();
00683 
00684         LLVector3 pos_agent_rounded = getOrigin() + ray_dir*dist;
00685 
00686         /*
00687         LLVector3 pixel_x, pixel_y;
00688         getPixelVectors(pos_agent_rounded, pixel_y, pixel_x);
00689         pos_agent_rounded += 0.5f*pixel_x, 0.5f*pixel_y;
00690         */
00691         return pos_agent_rounded;
00692 }
00693 
00694 BOOL LLViewerCamera::cameraUnderWater() const
00695 {
00696         return getOrigin().mV[VZ] < gAgent.getRegion()->getWaterHeight();
00697 }
00698 
00699 BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts)
00700 {
00701         S32 i, num_faces;
00702         LLDrawable* drawablep = volumep->mDrawable;
00703 
00704         if (!drawablep)
00705         {
00706                 return FALSE;
00707         }
00708 
00709         LLVolume* volume = volumep->getVolume();
00710         if (!volume)
00711         {
00712                 return FALSE;
00713         }
00714 
00715         LLVOVolume* vo_volume = (LLVOVolume*) volumep;
00716 
00717         vo_volume->updateRelativeXform();
00718         LLMatrix4 mat = vo_volume->getRelativeXform();
00719         
00720         LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition()));
00721 
00722         num_faces = volume->getNumVolumeFaces();
00723         for (i = 0; i < num_faces; i++)
00724         {
00725                 const LLVolumeFace& face = volume->getVolumeFace(i);
00726                                 
00727                 for (U32 v = 0; v < face.mVertices.size(); v++)
00728                 {
00729                         LLVector4 vec = LLVector4(face.mVertices[v].mPosition) * mat;
00730 
00731                         if (drawablep->isActive())
00732                         {
00733                                 vec = vec * render_mat; 
00734                         }
00735 
00736                         BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0;
00737 
00738                         if ( !in_frustum && all_verts ||
00739                                  in_frustum && !all_verts)
00740                         {
00741                                 return !all_verts;
00742                         }
00743                 }
00744         }
00745         return all_verts;
00746 }

Generated on Fri May 16 08:34:09 2008 for SecondLife by  doxygen 1.5.5