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