source: OGRE/trunk/ogrenew/OgreMain/src/OgreCamera.cpp @ 657

Revision 657, 21.2 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://ogre.sourceforge.net/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26#include "OgreCamera.h"
27
28#include "OgreMath.h"
29#include "OgreMatrix3.h"
30#include "OgreSceneManager.h"
31#include "OgreSceneNode.h"
32#include "OgreAxisAlignedBox.h"
33#include "OgreSphere.h"
34#include "OgreLogManager.h"
35#include "OgreException.h"
36#include "OgreRoot.h"
37#include "OgreRenderSystem.h"
38
39namespace Ogre {
40
41    String Camera::msMovableType = "Camera";
42    //-----------------------------------------------------------------------
43    Camera::Camera( const String& name, SceneManager* sm)
44        : mName( name )
45    {
46        // Init camera location & direction
47
48        // Locate at (0,0,0)
49        mPosition.x = mPosition.y = mPosition.z = 0;
50        // Point down -Z axis
51        mOrientation = Quaternion::IDENTITY;
52
53
54        // Reasonable defaults to camera params
55        mFOVy = Radian(Math::PI/4.0);
56        mNearDist = 100.0f;
57        mFarDist = 100000.0f;
58        mAspect = 1.33333333333333f;
59        mProjType = PT_PERSPECTIVE;
60        mSceneDetail = SDL_SOLID;
61        setFixedYawAxis(true);    // Default to fixed yaw, like freelook since most people expect this
62
63        invalidateFrustum();
64        invalidateView();
65
66        // Init matrices
67        mViewMatrix = Matrix4::ZERO;
68        mProjMatrix = Matrix4::ZERO;
69
70        mParentNode = 0;
71
72        // Record SceneManager
73        mSceneMgr = sm;
74
75        // Init no tracking
76        mAutoTrackTarget = 0;
77
78        // Init lod
79        mSceneLodFactor = mSceneLodFactorInv =  1.0f;
80
81        // no reflection
82        mReflect = false;
83
84        mVisible = false;
85
86
87        mWindowSet = false;
88        mAutoAspectRatio = false;
89    }
90
91    //-----------------------------------------------------------------------
92    Camera::~Camera()
93    {
94        // Do nothing
95    }
96
97    //-----------------------------------------------------------------------
98    SceneManager* Camera::getSceneManager(void) const
99    {
100        return mSceneMgr;
101    }
102    //-----------------------------------------------------------------------
103    const String& Camera::getName(void) const
104    {
105        return mName;
106    }
107
108
109    //-----------------------------------------------------------------------
110    void Camera::setDetailLevel(SceneDetailLevel sd)
111    {
112        mSceneDetail = sd;
113    }
114
115    //-----------------------------------------------------------------------
116    SceneDetailLevel Camera::getDetailLevel(void) const
117    {
118        return mSceneDetail;
119    }
120
121    //-----------------------------------------------------------------------
122    void Camera::setPosition(Real x, Real y, Real z)
123    {
124        mPosition.x = x;
125        mPosition.y = y;
126        mPosition.z = z;
127        invalidateView();
128    }
129
130    //-----------------------------------------------------------------------
131    void Camera::setPosition(const Vector3& vec)
132    {
133        mPosition = vec;
134        invalidateView();
135    }
136
137    //-----------------------------------------------------------------------
138    const Vector3& Camera::getPosition(void) const
139    {
140        return mPosition;
141    }
142
143    //-----------------------------------------------------------------------
144    void Camera::move(const Vector3& vec)
145    {
146        mPosition = mPosition + vec;
147        invalidateView();
148    }
149
150    //-----------------------------------------------------------------------
151    void Camera::moveRelative(const Vector3& vec)
152    {
153        // Transform the axes of the relative vector by camera's local axes
154        Vector3 trans = mOrientation * vec;
155
156        mPosition = mPosition + trans;
157        invalidateView();
158    }
159
160    //-----------------------------------------------------------------------
161    void Camera::setDirection(Real x, Real y, Real z)
162    {
163        setDirection(Vector3(x,y,z));
164    }
165
166    //-----------------------------------------------------------------------
167    void Camera::setDirection(const Vector3& vec)
168    {
169        // Do nothing if given a zero vector
170        // (Replaced assert since this could happen with auto tracking camera and
171        //  camera passes through the lookAt point)
172        if (vec == Vector3::ZERO) return;
173
174        // Remember, camera points down -Z of local axes!
175        // Therefore reverse direction of direction vector before determining local Z
176        Vector3 zAdjustVec = -vec;
177        zAdjustVec.normalise();
178
179
180        if( mYawFixed )
181        {
182            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
183            xVec.normalise();
184
185            Vector3 yVec = zAdjustVec.crossProduct( xVec );
186            yVec.normalise();
187
188            mOrientation.FromAxes( xVec, yVec, zAdjustVec );
189        }
190        else
191        {
192
193            // Get axes from current quaternion
194            Vector3 axes[3];
195            updateView();
196            mDerivedOrientation.ToAxes(axes);
197            Quaternion rotQuat;
198            if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f)
199            {
200                // Oops, a 180 degree turn (infinite possible rotation axes)
201                // Default to yaw i.e. use current UP
202                rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
203            }
204            else
205            {
206                // Derive shortest arc to new direction
207                rotQuat = axes[2].getRotationTo(zAdjustVec);
208
209            }
210            mOrientation = rotQuat * mOrientation;
211        }
212
213
214        // TODO If we have a fixed yaw axis, we mustn't break it by using the
215        // shortest arc because this will sometimes cause a relative yaw
216        // which will tip the camera
217
218        invalidateView();
219
220    }
221
222    //-----------------------------------------------------------------------
223    Vector3 Camera::getDirection(void) const
224    {
225        // Direction points down -Z by default
226        return mOrientation * -Vector3::UNIT_Z;
227    }
228
229    //-----------------------------------------------------------------------
230    Vector3 Camera::getUp(void) const
231    {
232        return mOrientation * Vector3::UNIT_Y;
233    }
234
235    //-----------------------------------------------------------------------
236    Vector3 Camera::getRight(void) const
237    {
238        return mOrientation * Vector3::UNIT_X;
239    }
240
241    //-----------------------------------------------------------------------
242    void Camera::lookAt(const Vector3& targetPoint)
243    {
244        updateView();
245        this->setDirection(targetPoint - mDerivedPosition);
246    }
247
248    //-----------------------------------------------------------------------
249    void Camera::lookAt( Real x, Real y, Real z )
250    {
251        Vector3 vTemp( x, y, z );
252        this->lookAt(vTemp);
253    }
254
255    //-----------------------------------------------------------------------
256    void Camera::roll(const Radian& angle)
257    {
258        // Rotate around local Z axis
259        Vector3 zAxis = mOrientation * Vector3::UNIT_Z;
260        rotate(zAxis, angle);
261
262        invalidateView();
263    }
264
265    //-----------------------------------------------------------------------
266    void Camera::yaw(const Radian& angle)
267    {
268        Vector3 yAxis;
269
270        if (mYawFixed)
271        {
272            // Rotate around fixed yaw axis
273            yAxis = mYawFixedAxis;
274        }
275        else
276        {
277            // Rotate around local Y axis
278            yAxis = mOrientation * Vector3::UNIT_Y;
279        }
280
281        rotate(yAxis, angle);
282
283        invalidateView();
284    }
285
286    //-----------------------------------------------------------------------
287    void Camera::pitch(const Radian& angle)
288    {
289        // Rotate around local X axis
290        Vector3 xAxis = mOrientation * Vector3::UNIT_X;
291        rotate(xAxis, angle);
292
293        invalidateView();
294
295    }
296
297    //-----------------------------------------------------------------------
298    void Camera::rotate(const Vector3& axis, const Radian& angle)
299    {
300        Quaternion q;
301        q.FromAngleAxis(angle,axis);
302        rotate(q);
303    }
304
305    //-----------------------------------------------------------------------
306    void Camera::rotate(const Quaternion& q)
307    {
308        // Note the order of the mult, i.e. q comes after
309        mOrientation = q * mOrientation;
310        invalidateView();
311
312    }
313
314    //-----------------------------------------------------------------------
315    void Camera::updateFrustum(void) const
316    {
317        Frustum::updateFrustum();
318        // Set the clipping planes
319        setWindowImpl();
320    }
321
322    //-----------------------------------------------------------------------
323    bool Camera::isViewOutOfDate(void) const
324    {
325        bool returnVal = false;
326        // Overridden from Frustum to use local orientation / position offsets
327        // Attached to node?
328        if (mParentNode != 0)
329        {
330            if (!mRecalcView && mParentNode->_getDerivedOrientation() == mLastParentOrientation &&
331                mParentNode->_getDerivedPosition() == mLastParentPosition)
332            {
333                returnVal = false;
334            }
335            else
336            {
337                // Ok, we're out of date with SceneNode we're attached to
338                mLastParentOrientation = mParentNode->_getDerivedOrientation();
339                mLastParentPosition = mParentNode->_getDerivedPosition();
340                mDerivedOrientation = mLastParentOrientation * mOrientation;
341                mDerivedPosition = (mLastParentOrientation * mPosition) + mLastParentPosition;
342                returnVal = true;
343            }
344        }
345        else
346        {
347            // Rely on own updates
348            mDerivedOrientation = mOrientation;
349            mDerivedPosition = mPosition;
350        }
351
352        // Deriving reflection from linked plane?
353        if (mReflect && mLinkedReflectPlane &&
354            !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane()))
355        {
356            mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
357            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
358            mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
359            returnVal = true;
360        }
361
362        return returnVal || mRecalcView;
363
364    }
365
366
367    //-----------------------------------------------------------------------
368    void Camera::updateView(void) const
369    {
370        Frustum::updateView();
371        setWindowImpl();
372
373    }
374    // -------------------------------------------------------------------
375    void Camera::invalidateView() const
376    {
377        mRecalcView = true;
378        mRecalcWindow = true;
379    }
380    // -------------------------------------------------------------------
381    void Camera::invalidateFrustum(void) const
382    {
383        mRecalcFrustum = true;
384        mRecalcWindow = true;
385    }
386    //-----------------------------------------------------------------------
387    void Camera::_renderScene(Viewport *vp, bool includeOverlays)
388    {
389
390        mSceneMgr->_renderScene(this, vp, includeOverlays);
391    }
392
393
394    //-----------------------------------------------------------------------
395    std::ostream& operator<<( std::ostream& o, Camera& c )
396    {
397        o << "Camera(Name='" << c.mName << "', pos=" << c.mPosition;
398        Vector3 dir(c.mOrientation*Vector3(0,0,-1));
399        o << ", direction=" << dir << ",near=" << c.mNearDist;
400        o << ", far=" << c.mFarDist << ", FOVy=" << c.mFOVy.valueDegrees();
401        o << ", aspect=" << c.mAspect << ", ";
402        o << "NearFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_NEAR] << ", ";
403        o << "FarFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_FAR] << ", ";
404        o << "LeftFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_LEFT] << ", ";
405        o << "RightFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_RIGHT] << ", ";
406        o << "TopFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_TOP] << ", ";
407        o << "BottomFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_BOTTOM];
408        o << ")";
409
410        return o;
411    }
412
413    //-----------------------------------------------------------------------
414    void Camera::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
415    {
416        mYawFixed = useFixed;
417        mYawFixedAxis = fixedAxis;
418    }
419
420    //-----------------------------------------------------------------------
421    void Camera::_notifyRenderedFaces(unsigned int numfaces)
422    {
423        mVisFacesLastRender = numfaces;
424    }
425
426    //-----------------------------------------------------------------------
427    unsigned int Camera::_getNumRenderedFaces(void) const
428    {
429        return mVisFacesLastRender;
430    }
431
432    //-----------------------------------------------------------------------
433    const Quaternion& Camera::getOrientation(void) const
434    {
435        return mOrientation;
436    }
437
438    //-----------------------------------------------------------------------
439    void Camera::setOrientation(const Quaternion& q)
440    {
441        mOrientation = q;
442        invalidateView();
443    }
444    //-----------------------------------------------------------------------
445    const Quaternion& Camera::getDerivedOrientation(void) const
446    {
447        updateView();
448        return mDerivedOrientation;
449    }
450    //-----------------------------------------------------------------------
451    const Vector3& Camera::getDerivedPosition(void) const
452    {
453        updateView();
454        return mDerivedPosition;
455    }
456    //-----------------------------------------------------------------------
457    Vector3 Camera::getDerivedDirection(void) const
458    {
459        // Direction points down -Z by default
460        updateView();
461        return mDerivedOrientation * -Vector3::UNIT_Z;
462    }
463    //-----------------------------------------------------------------------
464    Vector3 Camera::getDerivedUp(void) const
465    {
466        updateView();
467        return mDerivedOrientation * Vector3::UNIT_Y;
468    }
469    //-----------------------------------------------------------------------
470    Vector3 Camera::getDerivedRight(void) const
471    {
472        updateView();
473        return mDerivedOrientation * Vector3::UNIT_X;
474    }
475    //-----------------------------------------------------------------------
476    const String& Camera::getMovableType(void) const
477    {
478        return msMovableType;
479    }
480    //-----------------------------------------------------------------------
481    void Camera::setAutoTracking(bool enabled, SceneNode* target,
482        const Vector3& offset)
483    {
484        if (enabled)
485        {
486            assert (target != 0 && "target cannot be a null pointer if tracking is enabled");
487            mAutoTrackTarget = target;
488            mAutoTrackOffset = offset;
489        }
490        else
491        {
492            mAutoTrackTarget = 0;
493        }
494    }
495    //-----------------------------------------------------------------------
496    void Camera::_autoTrack(void)
497    {
498        // NB assumes that all scene nodes have been updated
499        if (mAutoTrackTarget)
500        {
501            lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset);
502        }
503    }
504    //-----------------------------------------------------------------------
505        void Camera::setLodBias(Real factor)
506        {
507                assert(factor > 0.0f && "Bias factor must be > 0!");
508                mSceneLodFactor = factor;
509                mSceneLodFactorInv = 1.0f / factor;
510        }
511    //-----------------------------------------------------------------------
512        Real Camera::getLodBias(void) const
513        {
514                return mSceneLodFactor;
515        }
516    //-----------------------------------------------------------------------
517        Real Camera::_getLodBiasInverse(void) const
518        {
519                return mSceneLodFactorInv;
520        }
521    //-----------------------------------------------------------------------
522    Ray Camera::getCameraToViewportRay(Real screenX, Real screenY) const
523    {
524        Real centeredScreenX = (screenX - 0.5f);
525        Real centeredScreenY = (0.5f - screenY);
526
527                Real normalizedSlope = Math::Tan(mFOVy / 2);
528        Real viewportYToWorldY = normalizedSlope * mNearDist * 2;
529        Real viewportXToWorldX = viewportYToWorldY * mAspect;
530
531                Vector3 rayDirection, rayOrigin;
532                if (mProjType == PT_PERSPECTIVE)
533                {
534                        // From camera centre
535                        rayOrigin = getDerivedPosition();
536                        // Point to perspective projected position
537                        rayDirection.x = centeredScreenX * viewportXToWorldX;
538                        rayDirection.y = centeredScreenY * viewportYToWorldY;
539                        rayDirection.z = -mNearDist;
540                        rayDirection = getDerivedOrientation() * rayDirection;
541                        rayDirection.normalise();
542                }
543                else
544                {
545                        // Ortho always parallel to point on screen
546                        rayOrigin.x = centeredScreenX * viewportXToWorldX;
547                        rayOrigin.y = centeredScreenY * viewportYToWorldY;
548                        rayOrigin.z = 0.0f;
549                        rayOrigin = getDerivedOrientation() * rayOrigin;
550                        rayOrigin = getDerivedPosition() + rayOrigin;
551                        rayDirection = getDerivedDirection();
552                }
553
554        return Ray(rayOrigin, rayDirection);
555    }
556
557    // -------------------------------------------------------------------
558    void Camera::setWindow (Real Left, Real Top, Real Right, Real Bottom)
559    {
560        mWLeft = Left;
561        mWTop = Top;
562        mWRight = Right;
563        mWBottom = Bottom;
564
565        mWindowSet = true;
566        mRecalcWindow = true;
567
568        invalidateView();
569    }
570    // -------------------------------------------------------------------
571    void Camera::resetWindow ()
572    {
573        mWindowSet = false;
574    }
575    // -------------------------------------------------------------------
576    void Camera::setWindowImpl() const
577    {
578        if (!mWindowSet || !mRecalcWindow)
579            return;
580
581
582        Radian thetaY ( mFOVy / 2.0f );
583        Real tanThetaY = Math::Tan(thetaY);
584        //Real thetaX = thetaY * mAspect;
585        Real tanThetaX = tanThetaY * mAspect;
586
587        Real vpTop = tanThetaY * mNearDist;
588        Real vpLeft = -tanThetaX * mNearDist;
589        Real vpWidth = -2 * vpLeft;
590        Real vpHeight = 2 * vpTop;
591
592        Real wvpLeft   = vpLeft + mWLeft * vpWidth;
593        Real wvpRight  = vpLeft + mWRight * vpWidth;
594        Real wvpTop    = vpTop - mWTop * vpHeight;
595        Real wvpBottom = vpTop - mWBottom * vpHeight;
596
597        Vector3 vp_ul (wvpLeft, wvpTop, -mNearDist);
598        Vector3 vp_ur (wvpRight, wvpTop, -mNearDist);
599        Vector3 vp_bl (wvpLeft, wvpBottom, -mNearDist);
600        Vector3 vp_br (wvpRight, wvpBottom, -mNearDist);
601
602        Matrix4 inv = mViewMatrix.inverse();
603
604        Vector3 vw_ul = inv * vp_ul;
605        Vector3 vw_ur = inv * vp_ur;
606        Vector3 vw_bl = inv * vp_bl;
607        Vector3 vw_br = inv * vp_br;
608
609        Vector3 position = getPosition();
610
611        mWindowClipPlanes.clear();
612        mWindowClipPlanes.push_back(Plane(position, vw_bl, vw_ul));
613        mWindowClipPlanes.push_back(Plane(position, vw_ul, vw_ur));
614        mWindowClipPlanes.push_back(Plane(position, vw_ur, vw_br));
615        mWindowClipPlanes.push_back(Plane(position, vw_br, vw_bl));
616
617        mRecalcWindow = false;
618
619    }
620    // -------------------------------------------------------------------
621    const std::vector<Plane>& Camera::getWindowPlanes(void) const
622    {
623        setWindowImpl();
624        return mWindowClipPlanes;
625    }
626    // -------------------------------------------------------------------
627    Real Camera::getBoundingRadius(void) const
628    {
629        // return a little bigger than the near distance
630        // just to keep things just outside
631        return mNearDist * 1.5;
632
633    }
634    //-----------------------------------------------------------------------
635    const Vector3& Camera::getPositionForViewUpdate(void) const
636    {
637        // Note no update, because we're calling this from the update!
638        return mDerivedPosition;
639    }
640    //-----------------------------------------------------------------------
641    const Quaternion& Camera::getOrientationForViewUpdate(void) const
642    {
643        return mDerivedOrientation;
644    }
645    //-----------------------------------------------------------------------
646    bool Camera::getAutoAspectRatio(void) const
647    {
648        return mAutoAspectRatio;
649    }
650    //-----------------------------------------------------------------------
651    void Camera::setAutoAspectRatio(bool autoratio)
652    {
653        mAutoAspectRatio = autoratio;
654    }
655
656} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.