00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://ogre.sourceforge.net/ 00006 00007 Copyright © 2000-2002 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #include "OgreStableHeaders.h" 00026 #include "OgreCamera.h" 00027 00028 #include "OgreMath.h" 00029 #include "OgreMatrix3.h" 00030 #include "OgreSceneManager.h" 00031 #include "OgreSceneNode.h" 00032 #include "OgreAxisAlignedBox.h" 00033 #include "OgreSphere.h" 00034 #include "OgreLogManager.h" 00035 #include "OgreException.h" 00036 #include "OgreRoot.h" 00037 #include "OgreRenderSystem.h" 00038 00039 namespace Ogre { 00040 00041 String Camera::msMovableType = "Camera"; 00042 //----------------------------------------------------------------------- 00043 Camera::Camera( const String& name, SceneManager* sm) 00044 : mName( name ) 00045 { 00046 // Init camera location & direction 00047 00048 // Locate at (0,0,0) 00049 mPosition.x = mPosition.y = mPosition.z = 0; 00050 // Point down -Z axis 00051 mOrientation = Quaternion::IDENTITY; 00052 00053 00054 // Reasonable defaults to camera params 00055 mFOVy = Math::RadiansToAngleUnits(Math::PI/4.0); 00056 mNearDist = 100.0f; 00057 mFarDist = 100000.0f; 00058 mAspect = 1.33333333333333f; 00059 mProjType = PT_PERSPECTIVE; 00060 mSceneDetail = SDL_SOLID; 00061 setFixedYawAxis(true); // Default to fixed yaw, like freelook since most people expect this 00062 00063 mRecalcFrustum = true; 00064 mRecalcView = true; 00065 00066 // Init matrices 00067 mViewMatrix = Matrix4::ZERO; 00068 mProjMatrix = Matrix4::ZERO; 00069 00070 mParentNode = 0; 00071 00072 // Record SceneManager 00073 mSceneMgr = sm; 00074 00075 // Init no tracking 00076 mAutoTrackTarget = 0; 00077 00078 // Init lod 00079 mSceneLodFactor = mSceneLodFactorInv = 1.0f; 00080 00081 // no reflection 00082 mReflect = false; 00083 00084 00085 updateView(); 00086 } 00087 00088 //----------------------------------------------------------------------- 00089 Camera::~Camera() 00090 { 00091 // Do nothing 00092 } 00093 00094 //----------------------------------------------------------------------- 00095 SceneManager* Camera::getSceneManager(void) const 00096 { 00097 return mSceneMgr; 00098 } 00099 //----------------------------------------------------------------------- 00100 const String& Camera::getName(void) const 00101 { 00102 return mName; 00103 } 00104 00105 //----------------------------------------------------------------------- 00106 void Camera::setProjectionType(ProjectionType pt) 00107 { 00108 mProjType = pt; 00109 mRecalcFrustum = true; 00110 } 00111 00112 //----------------------------------------------------------------------- 00113 ProjectionType Camera::getProjectionType(void) const 00114 { 00115 return mProjType; 00116 } 00117 00118 //----------------------------------------------------------------------- 00119 void Camera::setDetailLevel(SceneDetailLevel sd) 00120 { 00121 mSceneDetail = sd; 00122 } 00123 00124 //----------------------------------------------------------------------- 00125 SceneDetailLevel Camera::getDetailLevel(void) const 00126 { 00127 return mSceneDetail; 00128 } 00129 00130 //----------------------------------------------------------------------- 00131 void Camera::setPosition(Real x, Real y, Real z) 00132 { 00133 mPosition.x = x; 00134 mPosition.y = y; 00135 mPosition.z = z; 00136 mRecalcView = true; 00137 } 00138 00139 //----------------------------------------------------------------------- 00140 void Camera::setPosition(const Vector3& vec) 00141 { 00142 mPosition = vec; 00143 mRecalcView = true; 00144 } 00145 00146 //----------------------------------------------------------------------- 00147 const Vector3& Camera::getPosition(void) const 00148 { 00149 return mPosition; 00150 } 00151 00152 //----------------------------------------------------------------------- 00153 void Camera::move(const Vector3& vec) 00154 { 00155 mPosition = mPosition + vec; 00156 mRecalcView = true; 00157 } 00158 00159 //----------------------------------------------------------------------- 00160 void Camera::moveRelative(const Vector3& vec) 00161 { 00162 // Transform the axes of the relative vector by camera's local axes 00163 Vector3 trans = mOrientation * vec; 00164 00165 mPosition = mPosition + trans; 00166 mRecalcView = true; 00167 } 00168 00169 //----------------------------------------------------------------------- 00170 void Camera::setDirection(Real x, Real y, Real z) 00171 { 00172 setDirection(Vector3(x,y,z)); 00173 } 00174 00175 //----------------------------------------------------------------------- 00176 void Camera::setDirection(const Vector3& vec) 00177 { 00178 // Do nothing if given a zero vector 00179 // (Replaced assert since this could happen with auto tracking camera and 00180 // camera passes through the lookAt point) 00181 if (vec == Vector3::ZERO) return; 00182 00183 // Remember, camera points down -Z of local axes! 00184 // Therefore reverse direction of direction vector before determining local Z 00185 Vector3 zAdjustVec = -vec; 00186 zAdjustVec.normalise(); 00187 00188 00189 if( mYawFixed ) 00190 { 00191 Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec ); 00192 xVec.normalise(); 00193 00194 Vector3 yVec = zAdjustVec.crossProduct( xVec ); 00195 yVec.normalise(); 00196 00197 mOrientation.FromAxes( xVec, yVec, zAdjustVec ); 00198 } 00199 else 00200 { 00201 00202 // Get axes from current quaternion 00203 Vector3 axes[3]; 00204 updateView(); 00205 mDerivedOrientation.ToAxes(axes); 00206 Quaternion rotQuat; 00207 if (-zAdjustVec == axes[2]) 00208 { 00209 // Oops, a 180 degree turn (infinite possible rotation axes) 00210 // Default to yaw i.e. use current UP 00211 rotQuat.FromAngleAxis(Math::PI, axes[1]); 00212 } 00213 else 00214 { 00215 // Derive shortest arc to new direction 00216 rotQuat = axes[2].getRotationTo(zAdjustVec); 00217 00218 } 00219 mOrientation = rotQuat * mOrientation; 00220 } 00221 00222 00223 // TODO If we have a fixed yaw axis, we mustn't break it by using the 00224 // shortest arc because this will sometimes cause a relative yaw 00225 // which will tip the camera 00226 00227 mRecalcView = true; 00228 00229 } 00230 00231 //----------------------------------------------------------------------- 00232 Vector3 Camera::getDirection(void) const 00233 { 00234 // Direction points down -Z by default 00235 return mOrientation * -Vector3::UNIT_Z; 00236 } 00237 00238 00239 //----------------------------------------------------------------------- 00240 void Camera::lookAt(const Vector3& targetPoint) 00241 { 00242 00243 updateView(); 00244 this->setDirection(targetPoint - mDerivedPosition); 00245 00246 } 00247 00248 //----------------------------------------------------------------------- 00249 void Camera::lookAt( Real x, Real y, Real z ) 00250 { 00251 Vector3 vTemp( x, y, z ); 00252 this->lookAt(vTemp); 00253 00254 } 00255 00256 //----------------------------------------------------------------------- 00257 void Camera::setFOVy(Real fov) 00258 { 00259 mFOVy = fov; 00260 mRecalcFrustum = true; 00261 } 00262 00263 //----------------------------------------------------------------------- 00264 Real Camera::getFOVy(void) const 00265 { 00266 return mFOVy; 00267 } 00268 00269 00270 //----------------------------------------------------------------------- 00271 void Camera::setFarClipDistance(Real farPlane) 00272 { 00273 mFarDist = farPlane; 00274 mRecalcFrustum = true; 00275 } 00276 00277 //----------------------------------------------------------------------- 00278 Real Camera::getFarClipDistance(void) const 00279 { 00280 return mFarDist; 00281 } 00282 00283 //----------------------------------------------------------------------- 00284 void Camera::setNearClipDistance(Real nearPlane) 00285 { 00286 if (nearPlane <= 0) 00287 Except(Exception::ERR_INVALIDPARAMS, "Near clip distance must be greater than zero.", 00288 "Camera::setNearClipDistance"); 00289 mNearDist = nearPlane; 00290 mRecalcFrustum = true; 00291 } 00292 00293 //----------------------------------------------------------------------- 00294 Real Camera::getNearClipDistance(void) const 00295 { 00296 return mNearDist; 00297 } 00298 00299 //----------------------------------------------------------------------- 00300 const Matrix4& Camera::getProjectionMatrix(void) const 00301 { 00302 00303 updateFrustum(); 00304 00305 return mProjMatrix; 00306 } 00307 //----------------------------------------------------------------------- 00308 const Matrix4& Camera::getStandardProjectionMatrix(void) const 00309 { 00310 00311 updateFrustum(); 00312 00313 return mStandardProjMatrix; 00314 } 00315 //----------------------------------------------------------------------- 00316 const Matrix4& Camera::getViewMatrix(void) const 00317 { 00318 updateView(); 00319 00320 return mViewMatrix; 00321 00322 } 00323 00324 //----------------------------------------------------------------------- 00325 void Camera::roll(Real degrees) 00326 { 00327 // Rotate around local Z axis 00328 Vector3 zAxis = mOrientation * Vector3::UNIT_Z; 00329 rotate(zAxis, degrees); 00330 00331 mRecalcView = true; 00332 } 00333 00334 //----------------------------------------------------------------------- 00335 void Camera::yaw(Real degrees) 00336 { 00337 Vector3 yAxis; 00338 00339 if (mYawFixed) 00340 { 00341 // Rotate around fixed yaw axis 00342 yAxis = mYawFixedAxis; 00343 } 00344 else 00345 { 00346 // Rotate around local Y axis 00347 yAxis = mOrientation * Vector3::UNIT_Y; 00348 } 00349 00350 rotate(yAxis, degrees); 00351 00352 mRecalcView = true; 00353 } 00354 00355 //----------------------------------------------------------------------- 00356 void Camera::pitch(Real degrees) 00357 { 00358 // Rotate around local X axis 00359 Vector3 xAxis = mOrientation * Vector3::UNIT_X; 00360 rotate(xAxis, degrees); 00361 00362 mRecalcView = true; 00363 00364 } 00365 00366 //----------------------------------------------------------------------- 00367 void Camera::rotate(const Vector3& axis, Real degrees) 00368 { 00369 Quaternion q; 00370 q.FromAngleAxis(Math::AngleUnitsToRadians(degrees),axis); 00371 rotate(q); 00372 00373 } 00374 //----------------------------------------------------------------------- 00375 void Camera::rotate(const Quaternion& q) 00376 { 00377 // Note the order of the mult, i.e. q comes after 00378 mOrientation = q * mOrientation; 00379 mRecalcView = true; 00380 00381 } 00382 00383 //----------------------------------------------------------------------- 00384 const Plane& Camera::getFrustumPlane(FrustumPlane plane) const 00385 { 00386 // Make any pending updates to the calculated frustum 00387 updateView(); 00388 00389 return mFrustumPlanes[plane]; 00390 00391 } 00392 00393 //----------------------------------------------------------------------- 00394 bool Camera::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const 00395 { 00396 // Null boxes always invisible 00397 if (bound.isNull()) return false; 00398 00399 // Make any pending updates to the calculated frustum 00400 updateView(); 00401 00402 // Get corners of the box 00403 const Vector3* pCorners = bound.getAllCorners(); 00404 00405 00406 // For each plane, see if all points are on the negative side 00407 // If so, object is not visible 00408 for (size_t plane = 0; plane < 6; ++plane) 00409 { 00410 if (mFrustumPlanes[plane].getSide(pCorners[0]) == Plane::NEGATIVE_SIDE && 00411 mFrustumPlanes[plane].getSide(pCorners[1]) == Plane::NEGATIVE_SIDE && 00412 mFrustumPlanes[plane].getSide(pCorners[2]) == Plane::NEGATIVE_SIDE && 00413 mFrustumPlanes[plane].getSide(pCorners[3]) == Plane::NEGATIVE_SIDE && 00414 mFrustumPlanes[plane].getSide(pCorners[4]) == Plane::NEGATIVE_SIDE && 00415 mFrustumPlanes[plane].getSide(pCorners[5]) == Plane::NEGATIVE_SIDE && 00416 mFrustumPlanes[plane].getSide(pCorners[6]) == Plane::NEGATIVE_SIDE && 00417 mFrustumPlanes[plane].getSide(pCorners[7]) == Plane::NEGATIVE_SIDE) 00418 { 00419 // ALL corners on negative side therefore out of view 00420 if (culledBy) 00421 *culledBy = (FrustumPlane)plane; 00422 return false; 00423 } 00424 00425 } 00426 00427 return true; 00428 } 00429 00430 //----------------------------------------------------------------------- 00431 bool Camera::isVisible(const Vector3& vert, FrustumPlane* culledBy) const 00432 { 00433 // Make any pending updates to the calculated frustum 00434 updateView(); 00435 00436 // For each plane, see if all points are on the negative side 00437 // If so, object is not visible 00438 for (size_t plane = 0; plane < 6; ++plane) 00439 { 00440 if (mFrustumPlanes[plane].getSide(vert) == Plane::NEGATIVE_SIDE) 00441 { 00442 // ALL corners on negative side therefore out of view 00443 if (culledBy) 00444 *culledBy = (FrustumPlane)plane; 00445 return false; 00446 } 00447 00448 } 00449 00450 return true; 00451 } 00452 00453 //----------------------------------------------------------------------- 00454 bool Camera::isVisible(const Sphere& sphere, FrustumPlane* culledBy) const 00455 { 00456 // Make any pending updates to the calculated frustum 00457 updateView(); 00458 00459 // For each plane, see if sphere is on negative side 00460 // If so, object is not visible 00461 for (size_t plane = 0; plane < 6; ++plane) 00462 { 00463 // If the distance from sphere center to plane is negative, and 'more negative' 00464 // than the radius of the sphere, sphere is outside frustum 00465 if (mFrustumPlanes[plane].getDistance(sphere.getCenter()) < -sphere.getRadius()) 00466 { 00467 // ALL corners on negative side therefore out of view 00468 if (culledBy) 00469 *culledBy = (FrustumPlane)plane; 00470 return false; 00471 } 00472 00473 } 00474 00475 return true; 00476 } 00477 //----------------------------------------------------------------------- 00478 void Camera::updateFrustum(void) const 00479 { 00480 if (mRecalcFrustum) 00481 { 00482 // Recalc if frustum params changed 00483 if (mProjType == PT_PERSPECTIVE) 00484 { 00485 // PERSPECTIVE transform, API specific 00486 Root::getSingleton().getRenderSystem()->_makeProjectionMatrix(mFOVy, 00487 mAspect, mNearDist, mFarDist, mProjMatrix); 00488 00489 // PERSPECTIVE transform, API specific for Gpu Programs 00490 Root::getSingleton().getRenderSystem()->_makeProjectionMatrix(mFOVy, 00491 mAspect, mNearDist, mFarDist, mStandardProjMatrix, true); 00492 00493 // standard perspective transform, not API specific 00494 Real thetaY = Math::AngleUnitsToRadians(mFOVy / 2.0f); 00495 Real tanThetaY = Math::Tan(thetaY); 00496 00497 // Calculate co-efficients for the frustum planes 00498 // Special-cased for L = -R and B = -T i.e. viewport centered 00499 // on direction vector. 00500 // Taken from ideas in WildMagic 0.2 http://www.magic-software.com 00501 //Real thetaX = thetaY * mAspect; 00502 Real tanThetaX = tanThetaY * mAspect; 00503 00504 Real vpTop = tanThetaY * mNearDist; 00505 Real vpRight = tanThetaX * mNearDist; 00506 Real vpBottom = -vpTop; 00507 Real vpLeft = -vpRight; 00508 00509 Real fNSqr = mNearDist * mNearDist; 00510 Real fLSqr = vpRight * vpRight; 00511 Real fRSqr = fLSqr; 00512 Real fTSqr = vpTop * vpTop; 00513 Real fBSqr = fTSqr; 00514 00515 Real fInvLength = 1.0 / Math::Sqrt( fNSqr + fLSqr ); 00516 mCoeffL[0] = mNearDist * fInvLength; 00517 mCoeffL[1] = -vpLeft * fInvLength; 00518 00519 fInvLength = 1.0 / Math::Sqrt( fNSqr + fRSqr ); 00520 mCoeffR[0] = -mNearDist * fInvLength; 00521 mCoeffR[1] = vpRight * fInvLength; 00522 00523 fInvLength = 1.0 / Math::Sqrt( fNSqr + fBSqr ); 00524 mCoeffB[0] = mNearDist * fInvLength; 00525 mCoeffB[1] = -vpBottom * fInvLength; 00526 00527 fInvLength = 1.0 / Math::Sqrt( fNSqr + fTSqr ); 00528 mCoeffT[0] = -mNearDist * fInvLength; 00529 mCoeffT[1] = vpTop * fInvLength; 00530 00531 } 00532 else if (mProjType == PT_ORTHOGRAPHIC) 00533 { 00534 // ORTHOGRAPHIC projection 00535 00536 // --------------------------- 00537 // Calculate Projection Matrix 00538 // --------------------------- 00539 // Get tangent of vertical FOV 00540 Real thetaY = Math::AngleUnitsToRadians(mFOVy / 2.0f); 00541 Real sinThetaY = Math::Sin(thetaY); 00542 Real thetaX = thetaY * mAspect; 00543 Real sinThetaX = Math::Sin(thetaX); 00544 Real w = 1.0 / (sinThetaX * mNearDist); 00545 Real h = 1.0 / (sinThetaY * mNearDist); 00546 Real q = 1.0 / (mFarDist - mNearDist); 00547 //Real qn = -(mFarDist + mNearDist) / (mFarDist - mNearDist); 00548 00549 //---------------------------- 00550 // Matrix elements 00551 //---------------------------- 00552 00553 // [ w 0 0 0 ] 00554 // [ 0 h 0 0 ] 00555 // [ 0 0 q 0 ] 00556 // [ 0 0 0 -1 ] 00557 00558 00559 mProjMatrix = Matrix4::ZERO; 00560 mProjMatrix[0][0] = w; 00561 mProjMatrix[1][1] = h; 00562 mProjMatrix[2][2] = -q; 00563 mProjMatrix[3][3] = 1; 00564 00565 // Calculate co-efficients for the frustum planes 00566 // Special-cased for L = -R and B = -T i.e. viewport centered 00567 // on direction vector. 00568 // Taken from ideas in WildMagic 0.2 http://www.magic-software.com 00569 Real vpTop = sinThetaY * mNearDist; 00570 Real vpRight = sinThetaX * mNearDist; 00571 Real vpBottom = -vpTop; 00572 Real vpLeft = -vpRight; 00573 00574 Real fNSqr = mNearDist * mNearDist; 00575 Real fLSqr = vpRight * vpRight; 00576 Real fRSqr = fLSqr; 00577 Real fTSqr = vpTop * vpTop; 00578 Real fBSqr = fTSqr; 00579 00580 Real fInvLength = 1.0 / Math::Sqrt( fNSqr + fLSqr ); 00581 mCoeffL[0] = mNearDist * fInvLength; 00582 mCoeffL[1] = -vpLeft * fInvLength; 00583 00584 fInvLength = 1.0 / Math::Sqrt( fNSqr + fRSqr ); 00585 mCoeffR[0] = -mNearDist * fInvLength; 00586 mCoeffR[1] = vpRight * fInvLength; 00587 00588 fInvLength = 1.0 / Math::Sqrt( fNSqr + fBSqr ); 00589 mCoeffB[0] = mNearDist * fInvLength; 00590 mCoeffB[1] = -vpBottom * fInvLength; 00591 00592 fInvLength = 1.0 / Math::Sqrt( fNSqr + fTSqr ); 00593 mCoeffT[0] = -mNearDist * fInvLength; 00594 mCoeffT[1] = vpTop * fInvLength; 00595 00596 } 00597 mRecalcFrustum = false; 00598 } 00599 } 00600 00601 //----------------------------------------------------------------------- 00602 bool Camera::isViewOutOfDate(void) const 00603 { 00604 // Attached to node? 00605 if (mParentNode != 0) 00606 { 00607 if (!mRecalcView && mParentNode->_getDerivedOrientation() == mLastParentOrientation && 00608 mParentNode->_getDerivedPosition() == mLastParentPosition) 00609 { 00610 return false; 00611 } 00612 else 00613 { 00614 // Ok, we're out of date with SceneNode we're attached to 00615 mLastParentOrientation = mParentNode->_getDerivedOrientation(); 00616 mLastParentPosition = mParentNode->_getDerivedPosition(); 00617 mDerivedOrientation = mLastParentOrientation * mOrientation; 00618 mDerivedPosition = (mLastParentOrientation * mPosition) + mLastParentPosition; 00619 return true; 00620 } 00621 } 00622 else 00623 { 00624 // Rely on own updates 00625 mDerivedOrientation = mOrientation; 00626 mDerivedPosition = mPosition; 00627 return mRecalcView; 00628 } 00629 } 00630 00631 //----------------------------------------------------------------------- 00632 bool Camera::isFrustumOutOfDate(void) const 00633 { 00634 return mRecalcFrustum; 00635 } 00636 00637 //----------------------------------------------------------------------- 00638 void Camera::updateView(void) const 00639 { 00640 if (isViewOutOfDate()) 00641 { 00642 // ---------------------- 00643 // Update the view matrix 00644 // ---------------------- 00645 00646 // View matrix is: 00647 // 00648 // [ Lx Uy Dz Tx ] 00649 // [ Lx Uy Dz Ty ] 00650 // [ Lx Uy Dz Tz ] 00651 // [ 0 0 0 1 ] 00652 // 00653 // Where T = -(Transposed(Rot) * Pos) 00654 00655 // This is most efficiently done using 3x3 Matrices 00656 00657 // Get orientation from quaternion 00658 00659 Matrix3 rot; 00660 mDerivedOrientation.ToRotationMatrix(rot); 00661 Vector3 left = rot.GetColumn(0); 00662 Vector3 up = rot.GetColumn(1); 00663 Vector3 direction = rot.GetColumn(2); 00664 00665 00666 // Make the translation relative to new axes 00667 Matrix3 rotT = rot.Transpose(); 00668 Vector3 trans = -rotT * mDerivedPosition; 00669 00670 // Make final matrix 00671 // Must init entire matrix incase reflection was used 00672 mViewMatrix = Matrix4::IDENTITY; 00673 mViewMatrix = rotT; // fills upper 3x3 00674 mViewMatrix[0][3] = trans.x; 00675 mViewMatrix[1][3] = trans.y; 00676 mViewMatrix[2][3] = trans.z; 00677 00678 // Deal with reflections 00679 if (mReflect) 00680 { 00681 mViewMatrix = mViewMatrix * mReflectMatrix; 00682 } 00683 00684 00685 // ------------------------- 00686 // Update the frustum planes 00687 // ------------------------- 00688 updateFrustum(); 00689 // Use camera view direction for frustum, which is -Z not Z as for matrix calc 00690 Vector3 camDirection = mDerivedOrientation* -Vector3::UNIT_Z; 00691 // Calc distance along direction to position 00692 Real fDdE = camDirection.dotProduct(mDerivedPosition); 00693 00694 // left plane 00695 mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal = mCoeffL[0]*left + 00696 mCoeffL[1]*camDirection; 00697 mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = 00698 -mDerivedPosition.dotProduct(mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal); 00699 00700 // right plane 00701 mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal = mCoeffR[0]*left + 00702 mCoeffR[1]*camDirection; 00703 mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = 00704 -mDerivedPosition.dotProduct(mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal); 00705 00706 // bottom plane 00707 mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal = mCoeffB[0]*up + 00708 mCoeffB[1]*camDirection; 00709 mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = 00710 -mDerivedPosition.dotProduct(mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal); 00711 00712 // top plane 00713 mFrustumPlanes[FRUSTUM_PLANE_TOP].normal = mCoeffT[0]*up + 00714 mCoeffT[1]*camDirection; 00715 mFrustumPlanes[FRUSTUM_PLANE_TOP].d = 00716 -mDerivedPosition.dotProduct(mFrustumPlanes[FRUSTUM_PLANE_TOP].normal); 00717 00718 // far plane 00719 mFrustumPlanes[FRUSTUM_PLANE_FAR].normal = -camDirection; 00720 // d is distance along normal to origin 00721 mFrustumPlanes[FRUSTUM_PLANE_FAR].d = fDdE + mFarDist; 00722 00723 // near plane 00724 mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal = camDirection; 00725 mFrustumPlanes[FRUSTUM_PLANE_NEAR].d = -(fDdE + mNearDist); 00726 00727 // Deal with reflection on frustum planes 00728 if (mReflect) 00729 { 00730 Vector3 pos = mReflectMatrix * mDerivedPosition; 00731 Vector3 dir = camDirection.reflect(mReflectPlane.normal); 00732 fDdE = dir.dotProduct(pos); 00733 for (unsigned int i = 0; i < 6; ++i) 00734 { 00735 mFrustumPlanes[i].normal = mFrustumPlanes[i].normal.reflect(mReflectPlane.normal); 00736 // Near / far plane dealt with differently since they don't pass through camera 00737 switch (i) 00738 { 00739 case FRUSTUM_PLANE_NEAR: 00740 mFrustumPlanes[i].d = -(fDdE + mNearDist); 00741 break; 00742 case FRUSTUM_PLANE_FAR: 00743 mFrustumPlanes[i].d = fDdE + mFarDist; 00744 break; 00745 default: 00746 mFrustumPlanes[i].d = -pos.dotProduct(mFrustumPlanes[i].normal); 00747 } 00748 } 00749 } 00750 00751 00752 mRecalcView = false; 00753 00754 } 00755 00756 } 00757 00758 //----------------------------------------------------------------------- 00759 void Camera::_renderScene(Viewport *vp, bool includeOverlays) 00760 { 00761 00762 mSceneMgr->_renderScene(this, vp, includeOverlays); 00763 } 00764 00765 //----------------------------------------------------------------------- 00766 Real Camera::getAspectRatio(void) const 00767 { 00768 return mAspect; 00769 } 00770 00771 //----------------------------------------------------------------------- 00772 void Camera::setAspectRatio(Real r) 00773 { 00774 mAspect = r; 00775 mRecalcFrustum = true; 00776 } 00777 00778 //----------------------------------------------------------------------- 00779 std::ostream& operator<<( std::ostream& o, Camera& c ) 00780 { 00781 o << "Camera(Name='" << c.mName << "', pos=" << c.mPosition; 00782 Vector3 dir(c.mOrientation*Vector3(0,0,-1)); 00783 o << ", direction=" << dir << ",near=" << c.mNearDist; 00784 o << ", far=" << c.mFarDist << ", FOVy=" << c.mFOVy; 00785 o << ", aspect=" << c.mAspect << ", "; 00786 o << "NearFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_NEAR] << ", "; 00787 o << "FarFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_FAR] << ", "; 00788 o << "LeftFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_LEFT] << ", "; 00789 o << "RightFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_RIGHT] << ", "; 00790 o << "TopFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_TOP] << ", "; 00791 o << "BottomFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_BOTTOM]; 00792 o << ")"; 00793 00794 return o; 00795 } 00796 00797 //----------------------------------------------------------------------- 00798 void Camera::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis) 00799 { 00800 mYawFixed = useFixed; 00801 mYawFixedAxis = fixedAxis; 00802 } 00803 00804 //----------------------------------------------------------------------- 00805 void Camera::_notifyRenderedFaces(unsigned int numfaces) 00806 { 00807 mVisFacesLastRender = numfaces; 00808 } 00809 00810 //----------------------------------------------------------------------- 00811 unsigned int Camera::_getNumRenderedFaces(void) const 00812 { 00813 return mVisFacesLastRender; 00814 } 00815 00816 //----------------------------------------------------------------------- 00817 const Quaternion& Camera::getOrientation(void) const 00818 { 00819 return mOrientation; 00820 } 00821 00822 //----------------------------------------------------------------------- 00823 void Camera::setOrientation(const Quaternion& q) 00824 { 00825 mOrientation = q; 00826 mRecalcView = true; 00827 } 00828 //----------------------------------------------------------------------- 00829 Quaternion Camera::getDerivedOrientation(void) const 00830 { 00831 updateView(); 00832 return mDerivedOrientation; 00833 } 00834 //----------------------------------------------------------------------- 00835 Vector3 Camera::getDerivedPosition(void) const 00836 { 00837 updateView(); 00838 return mDerivedPosition; 00839 } 00840 //----------------------------------------------------------------------- 00841 Vector3 Camera::getDerivedDirection(void) const 00842 { 00843 // Direction points down -Z by default 00844 updateView(); 00845 return mDerivedOrientation * -Vector3::UNIT_Z; 00846 } 00847 //----------------------------------------------------------------------- 00848 void Camera::_notifyCurrentCamera(Camera* cam) 00849 { 00850 // Do nothing 00851 } 00852 //----------------------------------------------------------------------- 00853 const AxisAlignedBox& Camera::getBoundingBox(void) const 00854 { 00855 // Null, cameras are not visible 00856 static AxisAlignedBox box; 00857 return box; 00858 } 00859 //----------------------------------------------------------------------- 00860 void Camera::_updateRenderQueue(RenderQueue* queue) 00861 { 00862 // Do nothing 00863 } 00864 //----------------------------------------------------------------------- 00865 const String& Camera::getMovableType(void) const 00866 { 00867 return msMovableType; 00868 } 00869 //----------------------------------------------------------------------- 00870 void Camera::setAutoTracking(bool enabled, SceneNode* target, 00871 const Vector3& offset) 00872 { 00873 if (enabled) 00874 { 00875 assert (target != 0 && "target cannot be a null pointer if tracking is enabled"); 00876 mAutoTrackTarget = target; 00877 mAutoTrackOffset = offset; 00878 } 00879 else 00880 { 00881 mAutoTrackTarget = 0; 00882 } 00883 } 00884 //----------------------------------------------------------------------- 00885 void Camera::_autoTrack(void) 00886 { 00887 // NB assumes that all scene nodes have been updated 00888 if (mAutoTrackTarget) 00889 { 00890 lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset); 00891 } 00892 } 00893 //----------------------------------------------------------------------- 00894 void Camera::setLodBias(Real factor) 00895 { 00896 assert(factor > 0.0f && "Bias factor must be > 0!"); 00897 mSceneLodFactor = factor; 00898 mSceneLodFactorInv = 1.0f / factor; 00899 } 00900 //----------------------------------------------------------------------- 00901 Real Camera::getLodBias(void) const 00902 { 00903 return mSceneLodFactor; 00904 } 00905 //----------------------------------------------------------------------- 00906 Real Camera::_getLodBiasInverse(void) const 00907 { 00908 return mSceneLodFactorInv; 00909 } 00910 //----------------------------------------------------------------------- 00911 Real Camera::getBoundingRadius(void) const 00912 { 00913 return mNearDist; 00914 } 00915 //----------------------------------------------------------------------- 00916 void Camera::enableReflection(const Plane& p) 00917 { 00918 mReflect = true; 00919 mReflectPlane = p; 00920 mReflectMatrix = Math::buildReflectionMatrix(p); 00921 mRecalcView = true; 00922 00923 } 00924 //----------------------------------------------------------------------- 00925 void Camera::disableReflection(void) 00926 { 00927 mReflect = false; 00928 mRecalcView = true; 00929 } 00930 } // namespace Ogre
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:04 2004