Logo Search packages:      
Sourcecode: ogre version File versions

OgreCamera.cpp

/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreCamera.h"

#include "OgreMath.h"
#include "OgreMatrix3.h"
#include "OgreSceneManager.h"
#include "OgreSceneNode.h"
#include "OgreAxisAlignedBox.h"
#include "OgreSphere.h"
#include "OgreLogManager.h"
#include "OgreException.h"
#include "OgreRoot.h"
#include "OgreRenderSystem.h"

namespace Ogre {

    String Camera::msMovableType = "Camera";
    //-----------------------------------------------------------------------
00047     Camera::Camera( const String& name, SceneManager* sm)
        : mName( name ),
            mSceneMgr(sm),
            mOrientation(Quaternion::IDENTITY),
            mPosition(Vector3::ZERO),
            mSceneDetail(PM_SOLID),
            mAutoTrackTarget(0),
            mAutoTrackOffset(Vector3::ZERO),
            mSceneLodFactor(1.0f),
            mSceneLodFactorInv(1.0f),
            mWindowSet(false),
            mLastViewport(0),
            mAutoAspectRatio(false),
            mCullFrustum(0),
            mUseRenderingDistance(true)

    {

        // Reasonable defaults to camera params
        mFOVy = Radian(Math::PI/4.0);
        mNearDist = 100.0f;
        mFarDist = 100000.0f;
        mAspect = 1.33333333333333f;
        mProjType = PT_PERSPECTIVE;
        setFixedYawAxis(true);    // Default to fixed yaw, like freelook since most people expect this

        invalidateFrustum();
        invalidateView();

        // Init matrices
        mViewMatrix = Matrix4::ZERO;
        mProjMatrixRS = Matrix4::ZERO;

        mParentNode = 0;

        // no reflection
        mReflect = false;

        mVisible = false;

    }

    //-----------------------------------------------------------------------
00090     Camera::~Camera()
    {
        // Do nothing
    }

    //-----------------------------------------------------------------------
00096     SceneManager* Camera::getSceneManager(void) const
    {
        return mSceneMgr;
    }
    //-----------------------------------------------------------------------
00101     const String& Camera::getName(void) const
    {
        return mName;
    }


    //-----------------------------------------------------------------------
00108     void Camera::setPolygonMode(PolygonMode sd)
    {
        mSceneDetail = sd;
    }

    //-----------------------------------------------------------------------
00114     PolygonMode Camera::getPolygonMode(void) const
    {
        return mSceneDetail;
    }

    //-----------------------------------------------------------------------
00120     void Camera::setPosition(Real x, Real y, Real z)
    {
        mPosition.x = x;
        mPosition.y = y;
        mPosition.z = z;
        invalidateView();
    }

    //-----------------------------------------------------------------------
00129     void Camera::setPosition(const Vector3& vec)
    {
        mPosition = vec;
        invalidateView();
    }

    //-----------------------------------------------------------------------
00136     const Vector3& Camera::getPosition(void) const
    {
        return mPosition;
    }

    //-----------------------------------------------------------------------
00142     void Camera::move(const Vector3& vec)
    {
        mPosition = mPosition + vec;
        invalidateView();
    }

    //-----------------------------------------------------------------------
00149     void Camera::moveRelative(const Vector3& vec)
    {
        // Transform the axes of the relative vector by camera's local axes
        Vector3 trans = mOrientation * vec;

        mPosition = mPosition + trans;
        invalidateView();
    }

    //-----------------------------------------------------------------------
00159     void Camera::setDirection(Real x, Real y, Real z)
    {
        setDirection(Vector3(x,y,z));
    }

    //-----------------------------------------------------------------------
00165     void Camera::setDirection(const Vector3& vec)
    {
        // Do nothing if given a zero vector
        // (Replaced assert since this could happen with auto tracking camera and
        //  camera passes through the lookAt point)
        if (vec == Vector3::ZERO) return;

        // Remember, camera points down -Z of local axes!
        // Therefore reverse direction of direction vector before determining local Z
        Vector3 zAdjustVec = -vec;
        zAdjustVec.normalise();


        if( mYawFixed )
        {
            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
            xVec.normalise();

            Vector3 yVec = zAdjustVec.crossProduct( xVec );
            yVec.normalise();

            mOrientation.FromAxes( xVec, yVec, zAdjustVec );
        }
        else
        {

            // Get axes from current quaternion
            Vector3 axes[3];
            updateView();
            mRealOrientation.ToAxes(axes);
            Quaternion rotQuat;
            if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f) 
            {
                // Oops, a 180 degree turn (infinite possible rotation axes)
                // Default to yaw i.e. use current UP
                rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
            }
            else
            {
                // Derive shortest arc to new direction
                rotQuat = axes[2].getRotationTo(zAdjustVec);

            }
            mOrientation = rotQuat * mOrientation;
        }

        // transform to parent space
        if (mParentNode)
        {
            mOrientation =
                mParentNode->_getDerivedOrientation().Inverse() * mOrientation;
        }

        // TODO If we have a fixed yaw axis, we mustn't break it by using the
        // shortest arc because this will sometimes cause a relative yaw
        // which will tip the camera

        invalidateView();

    }

    //-----------------------------------------------------------------------
    Vector3 Camera::getDirection(void) const
    {
        // Direction points down -Z by default
        return mOrientation * -Vector3::UNIT_Z;
    }

    //-----------------------------------------------------------------------
00234     Vector3 Camera::getUp(void) const
    {
        return mOrientation * Vector3::UNIT_Y;
    }

    //-----------------------------------------------------------------------
00240     Vector3 Camera::getRight(void) const
    {
        return mOrientation * Vector3::UNIT_X;
    }

    //-----------------------------------------------------------------------
00246     void Camera::lookAt(const Vector3& targetPoint)
    {
        updateView();
        this->setDirection(targetPoint - mRealPosition);
    }

    //-----------------------------------------------------------------------
00253     void Camera::lookAt( Real x, Real y, Real z )
    {
        Vector3 vTemp( x, y, z );
        this->lookAt(vTemp);
    }

    //-----------------------------------------------------------------------
00260     void Camera::roll(const Radian& angle)
    {
        // Rotate around local Z axis
        Vector3 zAxis = mOrientation * Vector3::UNIT_Z;
        rotate(zAxis, angle);

        invalidateView();
    }

    //-----------------------------------------------------------------------
00270     void Camera::yaw(const Radian& angle)
    {
        Vector3 yAxis;

        if (mYawFixed)
        {
            // Rotate around fixed yaw axis
            yAxis = mYawFixedAxis;
        }
        else
        {
            // Rotate around local Y axis
            yAxis = mOrientation * Vector3::UNIT_Y;
        }

        rotate(yAxis, angle);

        invalidateView();
    }

    //-----------------------------------------------------------------------
00291     void Camera::pitch(const Radian& angle)
    {
        // Rotate around local X axis
        Vector3 xAxis = mOrientation * Vector3::UNIT_X;
        rotate(xAxis, angle);

        invalidateView();

    }

    //-----------------------------------------------------------------------
00302     void Camera::rotate(const Vector3& axis, const Radian& angle)
    {
        Quaternion q;
        q.FromAngleAxis(angle,axis);
        rotate(q);
    }

    //-----------------------------------------------------------------------
00310     void Camera::rotate(const Quaternion& q)
    {
        // Note the order of the mult, i.e. q comes after
        mOrientation = q * mOrientation;
        invalidateView();

    }

    //-----------------------------------------------------------------------
    bool Camera::isViewOutOfDate(void) const
    {
        // Overridden from Frustum to use local orientation / position offsets
        // Attached to node?
        if (mParentNode != 0)
        {
            if (mRecalcView ||
                mParentNode->_getDerivedOrientation() != mLastParentOrientation ||
                mParentNode->_getDerivedPosition() != mLastParentPosition)
            {
                // Ok, we're out of date with SceneNode we're attached to
                mLastParentOrientation = mParentNode->_getDerivedOrientation();
                mLastParentPosition = mParentNode->_getDerivedPosition();
                mRealOrientation = mLastParentOrientation * mOrientation;
                mRealPosition = (mLastParentOrientation * mPosition) + mLastParentPosition;
                mRecalcView = true;
                mRecalcWindow = true;
            }
        }
        else
        {
            // Rely on own updates
            mRealOrientation = mOrientation;
            mRealPosition = mPosition;
        }

        // Deriving reflection from linked plane?
        if (mReflect && mLinkedReflectPlane && 
            !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane()))
        {
            mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
            mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
            mRecalcView = true;
            mRecalcWindow = true;
        }

        // Deriving reflected orientation / position
        if (mRecalcView)
        {
            if (mReflect)
            {
                // Calculate reflected orientation, use up-vector as fallback axis.
                        Vector3 dir = mRealOrientation * Vector3::NEGATIVE_UNIT_Z;
                        Vector3 rdir = dir.reflect(mReflectPlane.normal);
                Vector3 up = mRealOrientation * Vector3::UNIT_Y;
                        mDerivedOrientation = dir.getRotationTo(rdir, up) * mRealOrientation;

                // Calculate reflected position.
                mDerivedPosition = mReflectMatrix.transformAffine(mRealPosition);
            }
            else
            {
                mDerivedOrientation = mRealOrientation;
                mDerivedPosition = mRealPosition;
            }
        }

        return mRecalcView;

    }

    // -------------------------------------------------------------------
00382     void Camera::invalidateView() const
    {
        mRecalcWindow = true;
        Frustum::invalidateView();
    }
    // -------------------------------------------------------------------
00388     void Camera::invalidateFrustum(void) const
    {
        mRecalcWindow = true;
        Frustum::invalidateFrustum();
    }
    //-----------------------------------------------------------------------
00394     void Camera::_renderScene(Viewport *vp, bool includeOverlays)
    {

        mSceneMgr->_renderScene(this, vp, includeOverlays);
    }


    //-----------------------------------------------------------------------
00402     std::ostream& operator<<( std::ostream& o, const Camera& c )
    {
        o << "Camera(Name='" << c.mName << "', pos=" << c.mPosition;
        Vector3 dir(c.mOrientation*Vector3(0,0,-1));
        o << ", direction=" << dir << ",near=" << c.mNearDist;
        o << ", far=" << c.mFarDist << ", FOVy=" << c.mFOVy.valueDegrees();
        o << ", aspect=" << c.mAspect << ", ";
        o << ", xoffset=" << c.mFrustumOffset.x << ", yoffset=" << c.mFrustumOffset.y;
        o << ", focalLength=" << c.mFocalLength << ", ";
        o << "NearFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_NEAR] << ", ";
        o << "FarFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_FAR] << ", ";
        o << "LeftFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_LEFT] << ", ";
        o << "RightFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_RIGHT] << ", ";
        o << "TopFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_TOP] << ", ";
        o << "BottomFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_BOTTOM];
        o << ")";

        return o;
    }

    //-----------------------------------------------------------------------
00423     void Camera::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
    {
        mYawFixed = useFixed;
        mYawFixedAxis = fixedAxis;
    }

    //-----------------------------------------------------------------------
00430     void Camera::_notifyRenderedFaces(unsigned int numfaces)
    {
        mVisFacesLastRender = numfaces;
    }

    //-----------------------------------------------------------------------
00436     void Camera::_notifyRenderedBatches(unsigned int numbatches)
    {
        mVisBatchesLastRender = numbatches;
    }

    //-----------------------------------------------------------------------
00442     unsigned int Camera::_getNumRenderedFaces(void) const
    {
        return mVisFacesLastRender;
    }
    //-----------------------------------------------------------------------
00447     unsigned int Camera::_getNumRenderedBatches(void) const
    {
        return mVisBatchesLastRender;
    }
    //-----------------------------------------------------------------------
00452     const Quaternion& Camera::getOrientation(void) const
    {
        return mOrientation;
    }

    //-----------------------------------------------------------------------
00458     void Camera::setOrientation(const Quaternion& q)
    {
        mOrientation = q;
        invalidateView();
    }
    //-----------------------------------------------------------------------
00464     const Quaternion& Camera::getDerivedOrientation(void) const
    {
        updateView();
        return mDerivedOrientation;
    }
    //-----------------------------------------------------------------------
00470     const Vector3& Camera::getDerivedPosition(void) const
    {
        updateView();
        return mDerivedPosition;
    }
    //-----------------------------------------------------------------------
00476     Vector3 Camera::getDerivedDirection(void) const
    {
        // Direction points down -Z
        updateView();
        return mDerivedOrientation * Vector3::NEGATIVE_UNIT_Z;
    }
    //-----------------------------------------------------------------------
00483     Vector3 Camera::getDerivedUp(void) const
    {
        updateView();
        return mDerivedOrientation * Vector3::UNIT_Y;
    }
    //-----------------------------------------------------------------------
00489     Vector3 Camera::getDerivedRight(void) const
    {
        updateView();
        return mDerivedOrientation * Vector3::UNIT_X;
    }
    //-----------------------------------------------------------------------
00495     const Quaternion& Camera::getRealOrientation(void) const
    {
        updateView();
        return mRealOrientation;
    }
    //-----------------------------------------------------------------------
00501     const Vector3& Camera::getRealPosition(void) const
    {
        updateView();
        return mRealPosition;
    }
    //-----------------------------------------------------------------------
00507     Vector3 Camera::getRealDirection(void) const
    {
        // Direction points down -Z
        updateView();
        return mRealOrientation * Vector3::NEGATIVE_UNIT_Z;
    }
    //-----------------------------------------------------------------------
00514     Vector3 Camera::getRealUp(void) const
    {
        updateView();
        return mRealOrientation * Vector3::UNIT_Y;
    }
    //-----------------------------------------------------------------------
00520     Vector3 Camera::getRealRight(void) const
    {
        updateView();
        return mRealOrientation * Vector3::UNIT_X;
    }
    //-----------------------------------------------------------------------
00526     const String& Camera::getMovableType(void) const
    {
        return msMovableType;
    }
    //-----------------------------------------------------------------------
00531     void Camera::setAutoTracking(bool enabled, SceneNode* target, 
        const Vector3& offset)
    {
        if (enabled)
        {
            assert (target != 0 && "target cannot be a null pointer if tracking is enabled");
            mAutoTrackTarget = target;
            mAutoTrackOffset = offset;
        }
        else
        {
            mAutoTrackTarget = 0;
        }
    }
    //-----------------------------------------------------------------------
00546     void Camera::_autoTrack(void)
    {
        // NB assumes that all scene nodes have been updated
        if (mAutoTrackTarget)
        {
            lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset);
        }
    }
    //-----------------------------------------------------------------------
00555       void Camera::setLodBias(Real factor)
      {
            assert(factor > 0.0f && "Bias factor must be > 0!");
            mSceneLodFactor = factor;
            mSceneLodFactorInv = 1.0f / factor;
      }
    //-----------------------------------------------------------------------
00562       Real Camera::getLodBias(void) const
      {
            return mSceneLodFactor;
      }
    //-----------------------------------------------------------------------
00567       Real Camera::_getLodBiasInverse(void) const
      {
            return mSceneLodFactorInv;
      }
    //-----------------------------------------------------------------------
00572     Ray Camera::getCameraToViewportRay(Real screenX, Real screenY) const
    {
            Matrix4 inverseVP = (getProjectionMatrix() * getViewMatrix(true)).inverse();

            Real nx = (2.0f * screenX) - 1.0f;
            Real ny = 1.0f - (2.0f * screenY);
            Vector3 nearPoint(nx, ny, -1.f);
            // Use midPoint rather than far point to avoid issues with infinite projection
            Vector3 midPoint (nx, ny,  0.0f);

            // Get ray origin and ray target on near plane in world space
            Vector3 rayOrigin, rayTarget;
            
            rayOrigin = inverseVP * nearPoint;
            rayTarget = inverseVP * midPoint;

            Vector3 rayDirection = rayTarget - rayOrigin;
            rayDirection.normalise();

            return Ray(rayOrigin, rayDirection);
    } 

    // -------------------------------------------------------------------
00595     void Camera::setWindow (Real Left, Real Top, Real Right, Real Bottom)
    {
        mWLeft = Left;
        mWTop = Top;
        mWRight = Right;
        mWBottom = Bottom;

        mWindowSet = true;
        mRecalcWindow = true;
    }
    // -------------------------------------------------------------------
00606     void Camera::resetWindow ()
    {
        mWindowSet = false;
    }
    // -------------------------------------------------------------------
00611     void Camera::setWindowImpl() const
    {
        if (!mWindowSet || !mRecalcWindow)
            return;

        // Calculate general projection parameters
        Real vpLeft, vpRight, vpBottom, vpTop;
        calcProjectionParameters(vpLeft, vpRight, vpBottom, vpTop);

        Real vpWidth = vpRight - vpLeft;
        Real vpHeight = vpTop - vpBottom;

        Real wvpLeft   = vpLeft + mWLeft * vpWidth;
        Real wvpRight  = vpLeft + mWRight * vpWidth;
        Real wvpTop    = vpTop - mWTop * vpHeight;
        Real wvpBottom = vpTop - mWBottom * vpHeight;

        Vector3 vp_ul (wvpLeft, wvpTop, -mNearDist);
        Vector3 vp_ur (wvpRight, wvpTop, -mNearDist);
        Vector3 vp_bl (wvpLeft, wvpBottom, -mNearDist);
        Vector3 vp_br (wvpRight, wvpBottom, -mNearDist);

        Matrix4 inv = mViewMatrix.inverseAffine();

        Vector3 vw_ul = inv.transformAffine(vp_ul);
        Vector3 vw_ur = inv.transformAffine(vp_ur);
        Vector3 vw_bl = inv.transformAffine(vp_bl);
        Vector3 vw_br = inv.transformAffine(vp_br);

        if (mProjType == PT_PERSPECTIVE)
        {
            Vector3 position = getPosition();
            mWindowClipPlanes.push_back(Plane(position, vw_bl, vw_ul));
            mWindowClipPlanes.push_back(Plane(position, vw_ul, vw_ur));
            mWindowClipPlanes.push_back(Plane(position, vw_ur, vw_br));
            mWindowClipPlanes.push_back(Plane(position, vw_br, vw_bl));
        }
        else
        {
            Vector3 x_axis(inv[0][0], inv[0][1], inv[0][2]);
            Vector3 y_axis(inv[1][0], inv[1][1], inv[1][2]);
            x_axis.normalise();
            y_axis.normalise();
            mWindowClipPlanes.push_back(Plane( x_axis, vw_bl));
            mWindowClipPlanes.push_back(Plane(-x_axis, vw_ur));
            mWindowClipPlanes.push_back(Plane( y_axis, vw_bl));
            mWindowClipPlanes.push_back(Plane(-y_axis, vw_ur));
        }

        mRecalcWindow = false;

    }
    // -------------------------------------------------------------------
00664     const std::vector<Plane>& Camera::getWindowPlanes(void) const
    {
        updateView();
        setWindowImpl();
        return mWindowClipPlanes;
    }
    // -------------------------------------------------------------------
00671     Real Camera::getBoundingRadius(void) const
    {
        // return a little bigger than the near distance
        // just to keep things just outside
        return mNearDist * 1.5;

    }
    //-----------------------------------------------------------------------
00679     const Vector3& Camera::getPositionForViewUpdate(void) const
    {
        // Note no update, because we're calling this from the update!
        return mRealPosition;
    }
    //-----------------------------------------------------------------------
00685     const Quaternion& Camera::getOrientationForViewUpdate(void) const
    {
        return mRealOrientation;
    }
    //-----------------------------------------------------------------------
00690     bool Camera::getAutoAspectRatio(void) const
    {
        return mAutoAspectRatio;
    }
    //-----------------------------------------------------------------------
00695     void Camera::setAutoAspectRatio(bool autoratio)
    {
        mAutoAspectRatio = autoratio;
    }
      //-----------------------------------------------------------------------
00700       bool Camera::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->isVisible(bound, culledBy);
            }
            else
            {
                  return Frustum::isVisible(bound, culledBy);
            }
      }
      //-----------------------------------------------------------------------
00712       bool Camera::isVisible(const Sphere& bound, FrustumPlane* culledBy) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->isVisible(bound, culledBy);
            }
            else
            {
                  return Frustum::isVisible(bound, culledBy);
            }
      }
      //-----------------------------------------------------------------------
00724       bool Camera::isVisible(const Vector3& vert, FrustumPlane* culledBy) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->isVisible(vert, culledBy);
            }
            else
            {
                  return Frustum::isVisible(vert, culledBy);
            }
      }
      //-----------------------------------------------------------------------
00736       const Vector3* Camera::getWorldSpaceCorners(void) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->getWorldSpaceCorners();
            }
            else
            {
                  return Frustum::getWorldSpaceCorners();
            }
      }
      //-----------------------------------------------------------------------
00748       const Plane& Camera::getFrustumPlane( unsigned short plane ) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->getFrustumPlane(plane);
            }
            else
            {
                  return Frustum::getFrustumPlane(plane);
            }
      }
      //-----------------------------------------------------------------------
00760       bool Camera::projectSphere(const Sphere& sphere, 
            Real* left, Real* top, Real* right, Real* bottom) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->projectSphere(sphere, left, top, right, bottom);
            }
            else
            {
                  return Frustum::projectSphere(sphere, left, top, right, bottom);
            }
      }
      //-----------------------------------------------------------------------
00773       Real Camera::getNearClipDistance(void) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->getNearClipDistance();
            }
            else
            {
                  return Frustum::getNearClipDistance();
            }
      }
      //-----------------------------------------------------------------------
00785       Real Camera::getFarClipDistance(void) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->getFarClipDistance();
            }
            else
            {
                  return Frustum::getFarClipDistance();
            }
      }
      //-----------------------------------------------------------------------
00797       const Matrix4& Camera::getViewMatrix(void) const
      {
            if (mCullFrustum)
            {
                  return mCullFrustum->getViewMatrix();
            }
            else
            {
                  return Frustum::getViewMatrix();
            }
      }
      //-----------------------------------------------------------------------
00809       const Matrix4& Camera::getViewMatrix(bool ownFrustumOnly) const
      {
            if (ownFrustumOnly)
            {
                  return Frustum::getViewMatrix();
            }
            else
            {
                  return getViewMatrix();
            }
      }
      //-----------------------------------------------------------------------
      //_______________________________________________________
      //|                                                                                 |
      //|   getRayForwardIntersect                                            |
      //|   -----------------------------                               |
      //|   get the intersections of frustum rays with a plane    |
      //| of interest.  The plane is assumed to have constant     |
      //| z.  If this is not the case, rays                             |
      //| should be rotated beforehand to work in a               |
      //| coordinate system in which this is true.                |
      //|_____________________________________________________|
      //
00832       std::vector<Vector4> Camera::getRayForwardIntersect(const Vector3& anchor, const Vector3 *dir, Real planeOffset) const
      {
            std::vector<Vector4> res;

            if(!dir)
                  return res;

            int infpt[4] = {0, 0, 0, 0}; // 0=finite, 1=infinite, 2=straddles infinity
            Vector3 vec[4];

            // find how much the anchor point must be displaced in the plane's
            // constant variable
            Real delta = planeOffset - anchor.z;

            // now set the intersection point and note whether it is a 
            // point at infinity or straddles infinity
            unsigned int i;
            for (i=0; i<4; i++)
            {
                  Real test = dir[i].z * delta;
                  if (test == 0.0) {
                        vec[i] = dir[i];
                        infpt[i] = 1;
                  }
                  else {
                        Real lambda = delta / dir[i].z;
                        vec[i] = anchor + (lambda * dir[i]);
                        if(test < 0.0)
                              infpt[i] = 2;
                  }
            }

            for (i=0; i<4; i++)
            {
                  // store the finite intersection points
                  if (infpt[i] == 0)
                        res.push_back(Vector4(vec[i].x, vec[i].y, vec[i].z, 1.0));
                  else
                  {
                        // handle the infinite points of intersection;
                        // cases split up into the possible frustum planes 
                        // pieces which may contain a finite intersection point
                        int nextind = (i+1) % 4;
                        int prevind = (i+3) % 4;
                        if ((infpt[prevind] == 0) || (infpt[nextind] == 0))
                        {
                              if (infpt[i] == 1)
                                    res.push_back(Vector4(vec[i].x, vec[i].y, vec[i].z, 0.0));
                              else
                              {
                                    // handle the intersection points that straddle infinity (back-project)
                                    if(infpt[prevind] == 0) 
                                    {
                                          Vector3 temp = vec[prevind] - vec[i];
                                          res.push_back(Vector4(temp.x, temp.y, temp.z, 0.0));
                                    }
                                    if(infpt[nextind] == 0)
                                    {
                                          Vector3 temp = vec[nextind] - vec[i];
                                          res.push_back(Vector4(temp.x, temp.y, temp.z, 0.0));
                                    }
                              }
                        } // end if we need to add an intersection point to the list
                  } // end if infinite point needs to be considered
            } // end loop over frustun corners

            // we end up with either 0, 3, 4, or 5 intersection points

            return res;
      }

      //_______________________________________________________
      //|                                                                                 |
      //|   forwardIntersect                                                  |
      //|   -----------------------------                               |
      //|   Forward intersect the camera's frustum rays with      |
      //| a specified plane of interest.                                |
      //| Note that if the frustum rays shoot out and would |
      //| back project onto the plane, this means the forward     |
      //| intersection of the frustum would occur at the          |
      //| line at infinity.                                                   |
      //|_____________________________________________________|
      //
00915       void Camera::forwardIntersect(const Plane& worldPlane, std::vector<Vector4>* intersect3d) const
      {
            if(!intersect3d)
                  return;

            Vector3 trCorner = getWorldSpaceCorners()[0];
            Vector3 tlCorner = getWorldSpaceCorners()[1];
            Vector3 blCorner = getWorldSpaceCorners()[2];
            Vector3 brCorner = getWorldSpaceCorners()[3];

            // need some sort of rotation that will bring the plane normal to the z axis
            Plane pval = worldPlane;
            if(pval.normal.z < 0.0)
            {
                  pval.normal *= -1.0;
                  pval.d *= -1.0;
            }
            Quaternion invPlaneRot = pval.normal.getRotationTo(Vector3::UNIT_Z);

            // get rotated light
            Vector3 lPos = invPlaneRot * getDerivedPosition();
            Vector3 vec[4];
            vec[0] = invPlaneRot * trCorner - lPos;
            vec[1] = invPlaneRot * tlCorner - lPos; 
            vec[2] = invPlaneRot * blCorner - lPos; 
            vec[3] = invPlaneRot * brCorner - lPos; 

            // compute intersection points on plane
            std::vector<Vector4> iPnt = getRayForwardIntersect(lPos, vec, -pval.d);


            // return wanted data
            if(intersect3d) 
            {
                  Quaternion planeRot = invPlaneRot.Inverse();
                  (*intersect3d).clear();
                  for(unsigned int i=0; i<iPnt.size(); i++)
                  {
                        Vector3 intersection = planeRot * Vector3(iPnt[i].x, iPnt[i].y, iPnt[i].z);
                        (*intersect3d).push_back(Vector4(intersection.x, intersection.y, intersection.z, iPnt[i].w));
                  }
            }
      }
      //-----------------------------------------------------------------------


} // namespace Ogre

Generated by  Doxygen 1.6.0   Back to index