00001
00032 #include "llviewerprecompiledheaders.h"
00033 #include "llviewercamera.h"
00034
00035 #include <iomanip>
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
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 ¢er,
00099 const LLVector3 &up_direction,
00100 const LLVector3 &point_of_interest)
00101 {
00102
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
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
00144 mPixelMeterRatio = mViewHeightInPixels / (2.f*tanf(mCameraFOVDefault*0.5));
00145
00146 mScreenPixelArea =(S32)((F32)mViewHeightInPixels * ((F32)mViewHeightInPixels * mAspect));
00147 }
00148
00149
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
00189
00190
00191
00192
00193
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
00284 glMatrixMode( GL_PROJECTION );
00285 glLoadIdentity();
00286
00287 glh::matrix4f proj_mat;
00288
00289 if (for_selection)
00290 {
00291
00292
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
00300 z_far = gSavedSettings.getF32("MaxSelectDistance");
00301 }
00302 else
00303 {
00304 z_far = gAgent.mDrawDistance;
00305 }
00306 }
00307 else
00308 {
00309
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);
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
00371 if (!for_selection && mZoomFactor == 1.f)
00372 {
00373
00374
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
00394
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
00409
00410
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;
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
00436 x /= gViewerWindow->getDisplayScale().mV[VX];
00437 y /= gViewerWindow->getDisplayScale().mV[VY];
00438
00439
00440 const LLRect& window_rect = gViewerWindow->getWindowRect();
00441
00442
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
00513
00514
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;
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
00536 const LLRect& window_rect = gViewerWindow->getVirtualWindowRect();
00537
00538
00539 S32 int_x = lltrunc(x);
00540 S32 int_y = lltrunc(y);
00541
00542
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
00549 return FALSE;
00550 }
00551
00552
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
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
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
00594 int_y = window_rect.mBottom;
00595 }
00596 else
00597 {
00598
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
00608 int_x = window_rect.mLeft;
00609 }
00610 else
00611 {
00612
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
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
00671 LLCoordGL screen_point;
00672 if (!projectPosAgentToScreen(pos_agent, screen_point, FALSE))
00673 {
00674
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
00688
00689
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 }