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 = 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