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 = Radian(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 invalidateFrustum(); 00064 invalidateView(); 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 mVisible = false; 00085 00086 00087 mWindowSet = false; 00088 mAutoAspectRatio = false; 00089 } 00090 00091 //----------------------------------------------------------------------- 00092 Camera::~Camera() 00093 { 00094 // Do nothing 00095 } 00096 00097 //----------------------------------------------------------------------- 00098 SceneManager* Camera::getSceneManager(void) const 00099 { 00100 return mSceneMgr; 00101 } 00102 //----------------------------------------------------------------------- 00103 const String& Camera::getName(void) const 00104 { 00105 return mName; 00106 } 00107 00108 00109 //----------------------------------------------------------------------- 00110 void Camera::setDetailLevel(SceneDetailLevel sd) 00111 { 00112 mSceneDetail = sd; 00113 } 00114 00115 //----------------------------------------------------------------------- 00116 SceneDetailLevel Camera::getDetailLevel(void) const 00117 { 00118 return mSceneDetail; 00119 } 00120 00121 //----------------------------------------------------------------------- 00122 void Camera::setPosition(Real x, Real y, Real z) 00123 { 00124 mPosition.x = x; 00125 mPosition.y = y; 00126 mPosition.z = z; 00127 invalidateView(); 00128 } 00129 00130 //----------------------------------------------------------------------- 00131 void Camera::setPosition(const Vector3& vec) 00132 { 00133 mPosition = vec; 00134 invalidateView(); 00135 } 00136 00137 //----------------------------------------------------------------------- 00138 const Vector3& Camera::getPosition(void) const 00139 { 00140 return mPosition; 00141 } 00142 00143 //----------------------------------------------------------------------- 00144 void Camera::move(const Vector3& vec) 00145 { 00146 mPosition = mPosition + vec; 00147 invalidateView(); 00148 } 00149 00150 //----------------------------------------------------------------------- 00151 void Camera::moveRelative(const Vector3& vec) 00152 { 00153 // Transform the axes of the relative vector by camera's local axes 00154 Vector3 trans = mOrientation * vec; 00155 00156 mPosition = mPosition + trans; 00157 invalidateView(); 00158 } 00159 00160 //----------------------------------------------------------------------- 00161 void Camera::setDirection(Real x, Real y, Real z) 00162 { 00163 setDirection(Vector3(x,y,z)); 00164 } 00165 00166 //----------------------------------------------------------------------- 00167 void Camera::setDirection(const Vector3& vec) 00168 { 00169 // Do nothing if given a zero vector 00170 // (Replaced assert since this could happen with auto tracking camera and 00171 // camera passes through the lookAt point) 00172 if (vec == Vector3::ZERO) return; 00173 00174 // Remember, camera points down -Z of local axes! 00175 // Therefore reverse direction of direction vector before determining local Z 00176 Vector3 zAdjustVec = -vec; 00177 zAdjustVec.normalise(); 00178 00179 00180 if( mYawFixed ) 00181 { 00182 Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec ); 00183 xVec.normalise(); 00184 00185 Vector3 yVec = zAdjustVec.crossProduct( xVec ); 00186 yVec.normalise(); 00187 00188 mOrientation.FromAxes( xVec, yVec, zAdjustVec ); 00189 } 00190 else 00191 { 00192 00193 // Get axes from current quaternion 00194 Vector3 axes[3]; 00195 updateView(); 00196 mDerivedOrientation.ToAxes(axes); 00197 Quaternion rotQuat; 00198 if (-zAdjustVec == axes[2]) 00199 { 00200 // Oops, a 180 degree turn (infinite possible rotation axes) 00201 // Default to yaw i.e. use current UP 00202 rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]); 00203 } 00204 else 00205 { 00206 // Derive shortest arc to new direction 00207 rotQuat = axes[2].getRotationTo(zAdjustVec); 00208 00209 } 00210 mOrientation = rotQuat * mOrientation; 00211 } 00212 00213 00214 // TODO If we have a fixed yaw axis, we mustn't break it by using the 00215 // shortest arc because this will sometimes cause a relative yaw 00216 // which will tip the camera 00217 00218 invalidateView(); 00219 00220 } 00221 00222 //----------------------------------------------------------------------- 00223 Vector3 Camera::getDirection(void) const 00224 { 00225 // Direction points down -Z by default 00226 return mOrientation * -Vector3::UNIT_Z; 00227 } 00228 00229 //----------------------------------------------------------------------- 00230 Vector3 Camera::getUp(void) const 00231 { 00232 return mOrientation * Vector3::UNIT_Y; 00233 } 00234 00235 //----------------------------------------------------------------------- 00236 Vector3 Camera::getRight(void) const 00237 { 00238 return mOrientation * Vector3::UNIT_X; 00239 } 00240 00241 //----------------------------------------------------------------------- 00242 void Camera::lookAt(const Vector3& targetPoint) 00243 { 00244 updateView(); 00245 this->setDirection(targetPoint - mDerivedPosition); 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 void Camera::roll(const Radian& angle) 00257 { 00258 // Rotate around local Z axis 00259 Vector3 zAxis = mOrientation * Vector3::UNIT_Z; 00260 rotate(zAxis, angle); 00261 00262 invalidateView(); 00263 } 00264 00265 //----------------------------------------------------------------------- 00266 void Camera::yaw(const Radian& angle) 00267 { 00268 Vector3 yAxis; 00269 00270 if (mYawFixed) 00271 { 00272 // Rotate around fixed yaw axis 00273 yAxis = mYawFixedAxis; 00274 } 00275 else 00276 { 00277 // Rotate around local Y axis 00278 yAxis = mOrientation * Vector3::UNIT_Y; 00279 } 00280 00281 rotate(yAxis, angle); 00282 00283 invalidateView(); 00284 } 00285 00286 //----------------------------------------------------------------------- 00287 void Camera::pitch(const Radian& angle) 00288 { 00289 // Rotate around local X axis 00290 Vector3 xAxis = mOrientation * Vector3::UNIT_X; 00291 rotate(xAxis, angle); 00292 00293 invalidateView(); 00294 00295 } 00296 00297 //----------------------------------------------------------------------- 00298 void Camera::rotate(const Vector3& axis, const Radian& angle) 00299 { 00300 Quaternion q; 00301 q.FromAngleAxis(angle,axis); 00302 rotate(q); 00303 } 00304 00305 //----------------------------------------------------------------------- 00306 void Camera::rotate(const Quaternion& q) 00307 { 00308 // Note the order of the mult, i.e. q comes after 00309 mOrientation = q * mOrientation; 00310 invalidateView(); 00311 00312 } 00313 00314 //----------------------------------------------------------------------- 00315 void Camera::updateFrustum(void) const 00316 { 00317 Frustum::updateFrustum(); 00318 // Set the clipping planes 00319 setWindowImpl(); 00320 } 00321 00322 //----------------------------------------------------------------------- 00323 bool Camera::isViewOutOfDate(void) const 00324 { 00325 bool returnVal = false; 00326 // Overridden from Frustum to use local orientation / position offsets 00327 // Attached to node? 00328 if (mParentNode != 0) 00329 { 00330 if (!mRecalcView && mParentNode->_getDerivedOrientation() == mLastParentOrientation && 00331 mParentNode->_getDerivedPosition() == mLastParentPosition) 00332 { 00333 returnVal = false; 00334 } 00335 else 00336 { 00337 // Ok, we're out of date with SceneNode we're attached to 00338 mLastParentOrientation = mParentNode->_getDerivedOrientation(); 00339 mLastParentPosition = mParentNode->_getDerivedPosition(); 00340 mDerivedOrientation = mLastParentOrientation * mOrientation; 00341 mDerivedPosition = (mLastParentOrientation * mPosition) + mLastParentPosition; 00342 returnVal = true; 00343 } 00344 } 00345 else 00346 { 00347 // Rely on own updates 00348 mDerivedOrientation = mOrientation; 00349 mDerivedPosition = mPosition; 00350 } 00351 00352 // Deriving reflection from linked plane? 00353 if (mReflect && mLinkedReflectPlane && 00354 !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane())) 00355 { 00356 mReflectPlane = mLinkedReflectPlane->_getDerivedPlane(); 00357 mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane); 00358 mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane(); 00359 returnVal = true; 00360 } 00361 00362 return returnVal || mRecalcView; 00363 00364 } 00365 00366 00367 //----------------------------------------------------------------------- 00368 void Camera::updateView(void) const 00369 { 00370 Frustum::updateView(); 00371 setWindowImpl(); 00372 00373 } 00374 // ------------------------------------------------------------------- 00375 void Camera::invalidateView() const 00376 { 00377 mRecalcView = true; 00378 mRecalcWindow = true; 00379 } 00380 // ------------------------------------------------------------------- 00381 void Camera::invalidateFrustum(void) const 00382 { 00383 mRecalcFrustum = true; 00384 mRecalcWindow = true; 00385 } 00386 //----------------------------------------------------------------------- 00387 void Camera::_renderScene(Viewport *vp, bool includeOverlays) 00388 { 00389 00390 mSceneMgr->_renderScene(this, vp, includeOverlays); 00391 } 00392 00393 00394 //----------------------------------------------------------------------- 00395 std::ostream& operator<<( std::ostream& o, Camera& c ) 00396 { 00397 o << "Camera(Name='" << c.mName << "', pos=" << c.mPosition; 00398 Vector3 dir(c.mOrientation*Vector3(0,0,-1)); 00399 o << ", direction=" << dir << ",near=" << c.mNearDist; 00400 o << ", far=" << c.mFarDist << ", FOVy=" << c.mFOVy.valueDegrees(); 00401 o << ", aspect=" << c.mAspect << ", "; 00402 o << "NearFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_NEAR] << ", "; 00403 o << "FarFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_FAR] << ", "; 00404 o << "LeftFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_LEFT] << ", "; 00405 o << "RightFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_RIGHT] << ", "; 00406 o << "TopFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_TOP] << ", "; 00407 o << "BottomFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_BOTTOM]; 00408 o << ")"; 00409 00410 return o; 00411 } 00412 00413 //----------------------------------------------------------------------- 00414 void Camera::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis) 00415 { 00416 mYawFixed = useFixed; 00417 mYawFixedAxis = fixedAxis; 00418 } 00419 00420 //----------------------------------------------------------------------- 00421 void Camera::_notifyRenderedFaces(unsigned int numfaces) 00422 { 00423 mVisFacesLastRender = numfaces; 00424 } 00425 00426 //----------------------------------------------------------------------- 00427 unsigned int Camera::_getNumRenderedFaces(void) const 00428 { 00429 return mVisFacesLastRender; 00430 } 00431 00432 //----------------------------------------------------------------------- 00433 const Quaternion& Camera::getOrientation(void) const 00434 { 00435 return mOrientation; 00436 } 00437 00438 //----------------------------------------------------------------------- 00439 void Camera::setOrientation(const Quaternion& q) 00440 { 00441 mOrientation = q; 00442 invalidateView(); 00443 } 00444 //----------------------------------------------------------------------- 00445 const Quaternion& Camera::getDerivedOrientation(void) const 00446 { 00447 updateView(); 00448 return mDerivedOrientation; 00449 } 00450 //----------------------------------------------------------------------- 00451 const Vector3& Camera::getDerivedPosition(void) const 00452 { 00453 updateView(); 00454 return mDerivedPosition; 00455 } 00456 //----------------------------------------------------------------------- 00457 Vector3 Camera::getDerivedDirection(void) const 00458 { 00459 // Direction points down -Z by default 00460 updateView(); 00461 return mDerivedOrientation * -Vector3::UNIT_Z; 00462 } 00463 //----------------------------------------------------------------------- 00464 const String& Camera::getMovableType(void) const 00465 { 00466 return msMovableType; 00467 } 00468 //----------------------------------------------------------------------- 00469 void Camera::setAutoTracking(bool enabled, SceneNode* target, 00470 const Vector3& offset) 00471 { 00472 if (enabled) 00473 { 00474 assert (target != 0 && "target cannot be a null pointer if tracking is enabled"); 00475 mAutoTrackTarget = target; 00476 mAutoTrackOffset = offset; 00477 } 00478 else 00479 { 00480 mAutoTrackTarget = 0; 00481 } 00482 } 00483 //----------------------------------------------------------------------- 00484 void Camera::_autoTrack(void) 00485 { 00486 // NB assumes that all scene nodes have been updated 00487 if (mAutoTrackTarget) 00488 { 00489 lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset); 00490 } 00491 } 00492 //----------------------------------------------------------------------- 00493 void Camera::setLodBias(Real factor) 00494 { 00495 assert(factor > 0.0f && "Bias factor must be > 0!"); 00496 mSceneLodFactor = factor; 00497 mSceneLodFactorInv = 1.0f / factor; 00498 } 00499 //----------------------------------------------------------------------- 00500 Real Camera::getLodBias(void) const 00501 { 00502 return mSceneLodFactor; 00503 } 00504 //----------------------------------------------------------------------- 00505 Real Camera::_getLodBiasInverse(void) const 00506 { 00507 return mSceneLodFactorInv; 00508 } 00509 //----------------------------------------------------------------------- 00510 Ray Camera::getCameraToViewportRay(Real screenX, Real screenY) const 00511 { 00512 Real centeredScreenX = (screenX - 0.5f); 00513 Real centeredScreenY = (0.5f - screenY); 00514 00515 Real normalizedSlope = Math::Tan(mFOVy / 2); 00516 Real viewportYToWorldY = normalizedSlope * mNearDist * 2; 00517 Real viewportXToWorldX = viewportYToWorldY * mAspect; 00518 00519 Vector3 rayDirection(centeredScreenX * viewportXToWorldX, 00520 centeredScreenY * viewportYToWorldY, 00521 -mNearDist); 00522 rayDirection = getDerivedOrientation() * rayDirection; 00523 rayDirection.normalise(); 00524 00525 return Ray(getDerivedPosition(), rayDirection); 00526 } 00527 00528 // ------------------------------------------------------------------- 00529 void Camera::setWindow (Real Left, Real Top, Real Right, Real Bottom) 00530 { 00531 mWLeft = Left; 00532 mWTop = Top; 00533 mWRight = Right; 00534 mWBottom = Bottom; 00535 00536 mWindowSet = true; 00537 mRecalcWindow = true; 00538 00539 invalidateView(); 00540 } 00541 // ------------------------------------------------------------------- 00542 void Camera::resetWindow () 00543 { 00544 mWindowSet = false; 00545 } 00546 // ------------------------------------------------------------------- 00547 void Camera::setWindowImpl() const 00548 { 00549 if (!mWindowSet || !mRecalcWindow) 00550 return; 00551 00552 00553 Radian thetaY ( mFOVy / 2.0f ); 00554 Real tanThetaY = Math::Tan(thetaY); 00555 //Real thetaX = thetaY * mAspect; 00556 Real tanThetaX = tanThetaY * mAspect; 00557 00558 Real vpTop = tanThetaY * mNearDist; 00559 Real vpLeft = -tanThetaX * mNearDist; 00560 Real vpWidth = -2 * vpLeft; 00561 Real vpHeight = 2 * vpTop; 00562 00563 Real wvpLeft = vpLeft + mWLeft * vpWidth; 00564 Real wvpRight = vpLeft + mWRight * vpWidth; 00565 Real wvpTop = vpTop - mWTop * vpHeight; 00566 Real wvpBottom = vpTop - mWBottom * vpHeight; 00567 00568 Vector3 vp_ul (wvpLeft, wvpTop, -mNearDist); 00569 Vector3 vp_ur (wvpRight, wvpTop, -mNearDist); 00570 Vector3 vp_bl (wvpLeft, wvpBottom, -mNearDist); 00571 Vector3 vp_br (wvpRight, wvpBottom, -mNearDist); 00572 00573 Matrix4 inv = mViewMatrix.inverse(); 00574 00575 Vector3 vw_ul = inv * vp_ul; 00576 Vector3 vw_ur = inv * vp_ur; 00577 Vector3 vw_bl = inv * vp_bl; 00578 Vector3 vw_br = inv * vp_br; 00579 00580 Vector3 position = getPosition(); 00581 00582 mWindowClipPlanes.clear(); 00583 mWindowClipPlanes.push_back(Plane(position, vw_bl, vw_ul)); 00584 mWindowClipPlanes.push_back(Plane(position, vw_ul, vw_ur)); 00585 mWindowClipPlanes.push_back(Plane(position, vw_ur, vw_br)); 00586 mWindowClipPlanes.push_back(Plane(position, vw_br, vw_bl)); 00587 00588 mRecalcWindow = false; 00589 00590 } 00591 // ------------------------------------------------------------------- 00592 const std::vector<Plane>& Camera::getWindowPlanes(void) const 00593 { 00594 setWindowImpl(); 00595 return mWindowClipPlanes; 00596 } 00597 // ------------------------------------------------------------------- 00598 Real Camera::getBoundingRadius(void) const 00599 { 00600 // return a little bigger than the near distance 00601 // just to keep things just outside 00602 return mNearDist * 1.5; 00603 00604 } 00605 //----------------------------------------------------------------------- 00606 const Vector3& Camera::getPositionForViewUpdate(void) const 00607 { 00608 // Note no update, because we're calling this from the update! 00609 return mDerivedPosition; 00610 } 00611 //----------------------------------------------------------------------- 00612 const Quaternion& Camera::getOrientationForViewUpdate(void) const 00613 { 00614 return mDerivedOrientation; 00615 } 00616 //----------------------------------------------------------------------- 00617 bool Camera::getAutoAspectRatio(void) const 00618 { 00619 return mAutoAspectRatio; 00620 } 00621 //----------------------------------------------------------------------- 00622 void Camera::setAutoAspectRatio(bool autoratio) 00623 { 00624 mAutoAspectRatio = autoratio; 00625 } 00626 00627 } // namespace Ogre
Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:17 2004