Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreCamera.cpp

Go to the documentation of this file.
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