Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreCamera.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 29.8 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreCamera.h"
31
32#include "OgreMath.h"
33#include "OgreMatrix3.h"
34#include "OgreSceneManager.h"
35#include "OgreSceneNode.h"
36#include "OgreAxisAlignedBox.h"
37#include "OgreSphere.h"
38#include "OgreLogManager.h"
39#include "OgreException.h"
40#include "OgreRoot.h"
41#include "OgreRenderSystem.h"
42
43namespace Ogre {
44
45    String Camera::msMovableType = "Camera";
46    //-----------------------------------------------------------------------
47    Camera::Camera( const String& name, SceneManager* sm)
48        : mName( name ),
49                mSceneMgr(sm),
50                mOrientation(Quaternion::IDENTITY),
51                mPosition(Vector3::ZERO),
52                mSceneDetail(PM_SOLID),
53                mAutoTrackTarget(0),
54                mAutoTrackOffset(Vector3::ZERO),
55                mSceneLodFactor(1.0f),
56                mSceneLodFactorInv(1.0f),
57                mWindowSet(false),
58                mLastViewport(0),
59                mAutoAspectRatio(false),
60                mCullFrustum(0),
61                mUseRenderingDistance(true)
62
63    {
64
65        // Reasonable defaults to camera params
66        mFOVy = Radian(Math::PI/4.0);
67        mNearDist = 100.0f;
68        mFarDist = 100000.0f;
69        mAspect = 1.33333333333333f;
70        mProjType = PT_PERSPECTIVE;
71        setFixedYawAxis(true);    // Default to fixed yaw, like freelook since most people expect this
72
73        invalidateFrustum();
74        invalidateView();
75
76        // Init matrices
77        mViewMatrix = Matrix4::ZERO;
78        mProjMatrixRS = Matrix4::ZERO;
79
80        mParentNode = 0;
81
82        // no reflection
83        mReflect = false;
84
85        mVisible = false;
86
87    }
88
89    //-----------------------------------------------------------------------
90    Camera::~Camera()
91    {
92        // Do nothing
93    }
94
95    //-----------------------------------------------------------------------
96    SceneManager* Camera::getSceneManager(void) const
97    {
98        return mSceneMgr;
99    }
100    //-----------------------------------------------------------------------
101    const String& Camera::getName(void) const
102    {
103        return mName;
104    }
105
106
107    //-----------------------------------------------------------------------
108    void Camera::setPolygonMode(PolygonMode sd)
109    {
110        mSceneDetail = sd;
111    }
112
113    //-----------------------------------------------------------------------
114    PolygonMode Camera::getPolygonMode(void) const
115    {
116        return mSceneDetail;
117    }
118
119    //-----------------------------------------------------------------------
120    void Camera::setPosition(Real x, Real y, Real z)
121    {
122        mPosition.x = x;
123        mPosition.y = y;
124        mPosition.z = z;
125        invalidateView();
126    }
127
128    //-----------------------------------------------------------------------
129    void Camera::setPosition(const Vector3& vec)
130    {
131        mPosition = vec;
132        invalidateView();
133    }
134
135    //-----------------------------------------------------------------------
136    const Vector3& Camera::getPosition(void) const
137    {
138        return mPosition;
139    }
140
141    //-----------------------------------------------------------------------
142    void Camera::move(const Vector3& vec)
143    {
144        mPosition = mPosition + vec;
145        invalidateView();
146    }
147
148    //-----------------------------------------------------------------------
149    void Camera::moveRelative(const Vector3& vec)
150    {
151        // Transform the axes of the relative vector by camera's local axes
152        Vector3 trans = mOrientation * vec;
153
154        mPosition = mPosition + trans;
155        invalidateView();
156    }
157
158    //-----------------------------------------------------------------------
159    void Camera::setDirection(Real x, Real y, Real z)
160    {
161        setDirection(Vector3(x,y,z));
162    }
163
164    //-----------------------------------------------------------------------
165    void Camera::setDirection(const Vector3& vec)
166    {
167        // Do nothing if given a zero vector
168        // (Replaced assert since this could happen with auto tracking camera and
169        //  camera passes through the lookAt point)
170        if (vec == Vector3::ZERO) return;
171
172        // Remember, camera points down -Z of local axes!
173        // Therefore reverse direction of direction vector before determining local Z
174        Vector3 zAdjustVec = -vec;
175        zAdjustVec.normalise();
176
177
178        if( mYawFixed )
179        {
180            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
181            xVec.normalise();
182
183            Vector3 yVec = zAdjustVec.crossProduct( xVec );
184            yVec.normalise();
185
186            mOrientation.FromAxes( xVec, yVec, zAdjustVec );
187        }
188        else
189        {
190
191            // Get axes from current quaternion
192            Vector3 axes[3];
193            updateView();
194            mRealOrientation.ToAxes(axes);
195            Quaternion rotQuat;
196            if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f) 
197            {
198                // Oops, a 180 degree turn (infinite possible rotation axes)
199                // Default to yaw i.e. use current UP
200                rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
201            }
202            else
203            {
204                // Derive shortest arc to new direction
205                rotQuat = axes[2].getRotationTo(zAdjustVec);
206
207            }
208            mOrientation = rotQuat * mOrientation;
209        }
210
211        // transform to parent space
212        if (mParentNode)
213        {
214            mOrientation =
215                mParentNode->_getDerivedOrientation().Inverse() * mOrientation;
216        }
217
218        // TODO If we have a fixed yaw axis, we mustn't break it by using the
219        // shortest arc because this will sometimes cause a relative yaw
220        // which will tip the camera
221
222        invalidateView();
223
224    }
225
226    //-----------------------------------------------------------------------
227    Vector3 Camera::getDirection(void) const
228    {
229        // Direction points down -Z by default
230        return mOrientation * -Vector3::UNIT_Z;
231    }
232
233    //-----------------------------------------------------------------------
234    Vector3 Camera::getUp(void) const
235    {
236        return mOrientation * Vector3::UNIT_Y;
237    }
238
239    //-----------------------------------------------------------------------
240    Vector3 Camera::getRight(void) const
241    {
242        return mOrientation * Vector3::UNIT_X;
243    }
244
245    //-----------------------------------------------------------------------
246    void Camera::lookAt(const Vector3& targetPoint)
247    {
248        updateView();
249        this->setDirection(targetPoint - mRealPosition);
250    }
251
252    //-----------------------------------------------------------------------
253    void Camera::lookAt( Real x, Real y, Real z )
254    {
255        Vector3 vTemp( x, y, z );
256        this->lookAt(vTemp);
257    }
258
259    //-----------------------------------------------------------------------
260    void Camera::roll(const Radian& angle)
261    {
262        // Rotate around local Z axis
263        Vector3 zAxis = mOrientation * Vector3::UNIT_Z;
264        rotate(zAxis, angle);
265
266        invalidateView();
267    }
268
269    //-----------------------------------------------------------------------
270    void Camera::yaw(const Radian& angle)
271    {
272        Vector3 yAxis;
273
274        if (mYawFixed)
275        {
276            // Rotate around fixed yaw axis
277            yAxis = mYawFixedAxis;
278        }
279        else
280        {
281            // Rotate around local Y axis
282            yAxis = mOrientation * Vector3::UNIT_Y;
283        }
284
285        rotate(yAxis, angle);
286
287        invalidateView();
288    }
289
290    //-----------------------------------------------------------------------
291    void Camera::pitch(const Radian& angle)
292    {
293        // Rotate around local X axis
294        Vector3 xAxis = mOrientation * Vector3::UNIT_X;
295        rotate(xAxis, angle);
296
297        invalidateView();
298
299    }
300
301    //-----------------------------------------------------------------------
302    void Camera::rotate(const Vector3& axis, const Radian& angle)
303    {
304        Quaternion q;
305        q.FromAngleAxis(angle,axis);
306        rotate(q);
307    }
308
309    //-----------------------------------------------------------------------
310    void Camera::rotate(const Quaternion& q)
311    {
312        // Note the order of the mult, i.e. q comes after
313        mOrientation = q * mOrientation;
314        invalidateView();
315
316    }
317
318    //-----------------------------------------------------------------------
319    bool Camera::isViewOutOfDate(void) const
320    {
321        // Overridden from Frustum to use local orientation / position offsets
322        // Attached to node?
323        if (mParentNode != 0)
324        {
325            if (mRecalcView ||
326                mParentNode->_getDerivedOrientation() != mLastParentOrientation ||
327                mParentNode->_getDerivedPosition() != mLastParentPosition)
328            {
329                // Ok, we're out of date with SceneNode we're attached to
330                mLastParentOrientation = mParentNode->_getDerivedOrientation();
331                mLastParentPosition = mParentNode->_getDerivedPosition();
332                mRealOrientation = mLastParentOrientation * mOrientation;
333                mRealPosition = (mLastParentOrientation * mPosition) + mLastParentPosition;
334                mRecalcView = true;
335                mRecalcWindow = true;
336            }
337        }
338        else
339        {
340            // Rely on own updates
341            mRealOrientation = mOrientation;
342            mRealPosition = mPosition;
343        }
344
345        // Deriving reflection from linked plane?
346        if (mReflect && mLinkedReflectPlane && 
347            !(mLastLinkedReflectionPlane == mLinkedReflectPlane->_getDerivedPlane()))
348        {
349            mReflectPlane = mLinkedReflectPlane->_getDerivedPlane();
350            mReflectMatrix = Math::buildReflectionMatrix(mReflectPlane);
351            mLastLinkedReflectionPlane = mLinkedReflectPlane->_getDerivedPlane();
352            mRecalcView = true;
353            mRecalcWindow = true;
354        }
355
356        // Deriving reflected orientation / position
357        if (mRecalcView)
358        {
359            if (mReflect)
360            {
361                // Calculate reflected orientation, use up-vector as fallback axis.
362                                Vector3 dir = mRealOrientation * Vector3::NEGATIVE_UNIT_Z;
363                                Vector3 rdir = dir.reflect(mReflectPlane.normal);
364                Vector3 up = mRealOrientation * Vector3::UNIT_Y;
365                                mDerivedOrientation = dir.getRotationTo(rdir, up) * mRealOrientation;
366
367                // Calculate reflected position.
368                mDerivedPosition = mReflectMatrix.transformAffine(mRealPosition);
369            }
370            else
371            {
372                mDerivedOrientation = mRealOrientation;
373                mDerivedPosition = mRealPosition;
374            }
375        }
376
377        return mRecalcView;
378
379    }
380
381    // -------------------------------------------------------------------
382    void Camera::invalidateView() const
383    {
384        mRecalcWindow = true;
385        Frustum::invalidateView();
386    }
387    // -------------------------------------------------------------------
388    void Camera::invalidateFrustum(void) const
389    {
390        mRecalcWindow = true;
391        Frustum::invalidateFrustum();
392    }
393    //-----------------------------------------------------------------------
394    void Camera::_renderScene(Viewport *vp, bool includeOverlays)
395    {
396
397        mSceneMgr->_renderScene(this, vp, includeOverlays);
398    }
399
400
401    //-----------------------------------------------------------------------
402    std::ostream& operator<<( std::ostream& o, const Camera& c )
403    {
404        o << "Camera(Name='" << c.mName << "', pos=" << c.mPosition;
405        Vector3 dir(c.mOrientation*Vector3(0,0,-1));
406        o << ", direction=" << dir << ",near=" << c.mNearDist;
407        o << ", far=" << c.mFarDist << ", FOVy=" << c.mFOVy.valueDegrees();
408        o << ", aspect=" << c.mAspect << ", ";
409        o << ", xoffset=" << c.mFrustumOffset.x << ", yoffset=" << c.mFrustumOffset.y;
410        o << ", focalLength=" << c.mFocalLength << ", ";
411        o << "NearFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_NEAR] << ", ";
412        o << "FarFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_FAR] << ", ";
413        o << "LeftFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_LEFT] << ", ";
414        o << "RightFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_RIGHT] << ", ";
415        o << "TopFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_TOP] << ", ";
416        o << "BottomFrustumPlane=" << c.mFrustumPlanes[FRUSTUM_PLANE_BOTTOM];
417        o << ")";
418
419        return o;
420    }
421
422    //-----------------------------------------------------------------------
423    void Camera::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
424    {
425        mYawFixed = useFixed;
426        mYawFixedAxis = fixedAxis;
427    }
428
429    //-----------------------------------------------------------------------
430    void Camera::_notifyRenderedFaces(unsigned int numfaces)
431    {
432        mVisFacesLastRender = numfaces;
433    }
434
435    //-----------------------------------------------------------------------
436    void Camera::_notifyRenderedBatches(unsigned int numbatches)
437    {
438        mVisBatchesLastRender = numbatches;
439    }
440
441    //-----------------------------------------------------------------------
442    unsigned int Camera::_getNumRenderedFaces(void) const
443    {
444        return mVisFacesLastRender;
445    }
446    //-----------------------------------------------------------------------
447    unsigned int Camera::_getNumRenderedBatches(void) const
448    {
449        return mVisBatchesLastRender;
450    }
451    //-----------------------------------------------------------------------
452    const Quaternion& Camera::getOrientation(void) const
453    {
454        return mOrientation;
455    }
456
457    //-----------------------------------------------------------------------
458    void Camera::setOrientation(const Quaternion& q)
459    {
460        mOrientation = q;
461        invalidateView();
462    }
463    //-----------------------------------------------------------------------
464    const Quaternion& Camera::getDerivedOrientation(void) const
465    {
466        updateView();
467        return mDerivedOrientation;
468    }
469    //-----------------------------------------------------------------------
470    const Vector3& Camera::getDerivedPosition(void) const
471    {
472        updateView();
473        return mDerivedPosition;
474    }
475    //-----------------------------------------------------------------------
476    Vector3 Camera::getDerivedDirection(void) const
477    {
478        // Direction points down -Z
479        updateView();
480        return mDerivedOrientation * Vector3::NEGATIVE_UNIT_Z;
481    }
482    //-----------------------------------------------------------------------
483    Vector3 Camera::getDerivedUp(void) const
484    {
485        updateView();
486        return mDerivedOrientation * Vector3::UNIT_Y;
487    }
488    //-----------------------------------------------------------------------
489    Vector3 Camera::getDerivedRight(void) const
490    {
491        updateView();
492        return mDerivedOrientation * Vector3::UNIT_X;
493    }
494    //-----------------------------------------------------------------------
495    const Quaternion& Camera::getRealOrientation(void) const
496    {
497        updateView();
498        return mRealOrientation;
499    }
500    //-----------------------------------------------------------------------
501    const Vector3& Camera::getRealPosition(void) const
502    {
503        updateView();
504        return mRealPosition;
505    }
506    //-----------------------------------------------------------------------
507    Vector3 Camera::getRealDirection(void) const
508    {
509        // Direction points down -Z
510        updateView();
511        return mRealOrientation * Vector3::NEGATIVE_UNIT_Z;
512    }
513    //-----------------------------------------------------------------------
514    Vector3 Camera::getRealUp(void) const
515    {
516        updateView();
517        return mRealOrientation * Vector3::UNIT_Y;
518    }
519    //-----------------------------------------------------------------------
520    Vector3 Camera::getRealRight(void) const
521    {
522        updateView();
523        return mRealOrientation * Vector3::UNIT_X;
524    }
525    //-----------------------------------------------------------------------
526    const String& Camera::getMovableType(void) const
527    {
528        return msMovableType;
529    }
530    //-----------------------------------------------------------------------
531    void Camera::setAutoTracking(bool enabled, SceneNode* target, 
532        const Vector3& offset)
533    {
534        if (enabled)
535        {
536            assert (target != 0 && "target cannot be a null pointer if tracking is enabled");
537            mAutoTrackTarget = target;
538            mAutoTrackOffset = offset;
539        }
540        else
541        {
542            mAutoTrackTarget = 0;
543        }
544    }
545    //-----------------------------------------------------------------------
546    void Camera::_autoTrack(void)
547    {
548        // NB assumes that all scene nodes have been updated
549        if (mAutoTrackTarget)
550        {
551            lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset);
552        }
553    }
554    //-----------------------------------------------------------------------
555        void Camera::setLodBias(Real factor)
556        {
557                assert(factor > 0.0f && "Bias factor must be > 0!");
558                mSceneLodFactor = factor;
559                mSceneLodFactorInv = 1.0f / factor;
560        }
561    //-----------------------------------------------------------------------
562        Real Camera::getLodBias(void) const
563        {
564                return mSceneLodFactor;
565        }
566    //-----------------------------------------------------------------------
567        Real Camera::_getLodBiasInverse(void) const
568        {
569                return mSceneLodFactorInv;
570        }
571    //-----------------------------------------------------------------------
572    Ray Camera::getCameraToViewportRay(Real screenX, Real screenY) const
573    {
574                Matrix4 inverseVP = (getProjectionMatrix() * getViewMatrix(true)).inverse();
575
576                Real nx = (2.0f * screenX) - 1.0f;
577                Real ny = 1.0f - (2.0f * screenY);
578                Vector3 nearPoint(nx, ny, -1.f);
579                // Use midPoint rather than far point to avoid issues with infinite projection
580                Vector3 midPoint (nx, ny,  0.0f);
581
582                // Get ray origin and ray target on near plane in world space
583                Vector3 rayOrigin, rayTarget;
584               
585                rayOrigin = inverseVP * nearPoint;
586                rayTarget = inverseVP * midPoint;
587
588                Vector3 rayDirection = rayTarget - rayOrigin;
589                rayDirection.normalise();
590
591                return Ray(rayOrigin, rayDirection);
592    } 
593
594    // -------------------------------------------------------------------
595    void Camera::setWindow (Real Left, Real Top, Real Right, Real Bottom)
596    {
597        mWLeft = Left;
598        mWTop = Top;
599        mWRight = Right;
600        mWBottom = Bottom;
601
602        mWindowSet = true;
603        mRecalcWindow = true;
604    }
605    // -------------------------------------------------------------------
606    void Camera::resetWindow ()
607    {
608        mWindowSet = false;
609    }
610    // -------------------------------------------------------------------
611    void Camera::setWindowImpl() const
612    {
613        if (!mWindowSet || !mRecalcWindow)
614            return;
615
616        // Calculate general projection parameters
617        Real vpLeft, vpRight, vpBottom, vpTop;
618        calcProjectionParameters(vpLeft, vpRight, vpBottom, vpTop);
619
620        Real vpWidth = vpRight - vpLeft;
621        Real vpHeight = vpTop - vpBottom;
622
623        Real wvpLeft   = vpLeft + mWLeft * vpWidth;
624        Real wvpRight  = vpLeft + mWRight * vpWidth;
625        Real wvpTop    = vpTop - mWTop * vpHeight;
626        Real wvpBottom = vpTop - mWBottom * vpHeight;
627
628        Vector3 vp_ul (wvpLeft, wvpTop, -mNearDist);
629        Vector3 vp_ur (wvpRight, wvpTop, -mNearDist);
630        Vector3 vp_bl (wvpLeft, wvpBottom, -mNearDist);
631        Vector3 vp_br (wvpRight, wvpBottom, -mNearDist);
632
633        Matrix4 inv = mViewMatrix.inverseAffine();
634
635        Vector3 vw_ul = inv.transformAffine(vp_ul);
636        Vector3 vw_ur = inv.transformAffine(vp_ur);
637        Vector3 vw_bl = inv.transformAffine(vp_bl);
638        Vector3 vw_br = inv.transformAffine(vp_br);
639
640        if (mProjType == PT_PERSPECTIVE)
641        {
642            Vector3 position = getPosition();
643            mWindowClipPlanes.push_back(Plane(position, vw_bl, vw_ul));
644            mWindowClipPlanes.push_back(Plane(position, vw_ul, vw_ur));
645            mWindowClipPlanes.push_back(Plane(position, vw_ur, vw_br));
646            mWindowClipPlanes.push_back(Plane(position, vw_br, vw_bl));
647        }
648        else
649        {
650            Vector3 x_axis(inv[0][0], inv[0][1], inv[0][2]);
651            Vector3 y_axis(inv[1][0], inv[1][1], inv[1][2]);
652            x_axis.normalise();
653            y_axis.normalise();
654            mWindowClipPlanes.push_back(Plane( x_axis, vw_bl));
655            mWindowClipPlanes.push_back(Plane(-x_axis, vw_ur));
656            mWindowClipPlanes.push_back(Plane( y_axis, vw_bl));
657            mWindowClipPlanes.push_back(Plane(-y_axis, vw_ur));
658        }
659
660        mRecalcWindow = false;
661
662    }
663    // -------------------------------------------------------------------
664    const std::vector<Plane>& Camera::getWindowPlanes(void) const
665    {
666        updateView();
667        setWindowImpl();
668        return mWindowClipPlanes;
669    }
670    // -------------------------------------------------------------------
671    Real Camera::getBoundingRadius(void) const
672    {
673        // return a little bigger than the near distance
674        // just to keep things just outside
675        return mNearDist * 1.5;
676
677    }
678    //-----------------------------------------------------------------------
679    const Vector3& Camera::getPositionForViewUpdate(void) const
680    {
681        // Note no update, because we're calling this from the update!
682        return mRealPosition;
683    }
684    //-----------------------------------------------------------------------
685    const Quaternion& Camera::getOrientationForViewUpdate(void) const
686    {
687        return mRealOrientation;
688    }
689    //-----------------------------------------------------------------------
690    bool Camera::getAutoAspectRatio(void) const
691    {
692        return mAutoAspectRatio;
693    }
694    //-----------------------------------------------------------------------
695    void Camera::setAutoAspectRatio(bool autoratio)
696    {
697        mAutoAspectRatio = autoratio;
698    }
699        //-----------------------------------------------------------------------
700        bool Camera::isVisible(const AxisAlignedBox& bound, FrustumPlane* culledBy) const
701        {
702                if (mCullFrustum)
703                {
704                        return mCullFrustum->isVisible(bound, culledBy);
705                }
706                else
707                {
708                        return Frustum::isVisible(bound, culledBy);
709                }
710        }
711        //-----------------------------------------------------------------------
712        bool Camera::isVisible(const Sphere& bound, FrustumPlane* culledBy) const
713        {
714                if (mCullFrustum)
715                {
716                        return mCullFrustum->isVisible(bound, culledBy);
717                }
718                else
719                {
720                        return Frustum::isVisible(bound, culledBy);
721                }
722        }
723        //-----------------------------------------------------------------------
724        bool Camera::isVisible(const Vector3& vert, FrustumPlane* culledBy) const
725        {
726                if (mCullFrustum)
727                {
728                        return mCullFrustum->isVisible(vert, culledBy);
729                }
730                else
731                {
732                        return Frustum::isVisible(vert, culledBy);
733                }
734        }
735        //-----------------------------------------------------------------------
736        const Vector3* Camera::getWorldSpaceCorners(void) const
737        {
738                if (mCullFrustum)
739                {
740                        return mCullFrustum->getWorldSpaceCorners();
741                }
742                else
743                {
744                        return Frustum::getWorldSpaceCorners();
745                }
746        }
747        //-----------------------------------------------------------------------
748        const Plane& Camera::getFrustumPlane( unsigned short plane ) const
749        {
750                if (mCullFrustum)
751                {
752                        return mCullFrustum->getFrustumPlane(plane);
753                }
754                else
755                {
756                        return Frustum::getFrustumPlane(plane);
757                }
758        }
759        //-----------------------------------------------------------------------
760        bool Camera::projectSphere(const Sphere& sphere, 
761                Real* left, Real* top, Real* right, Real* bottom) const
762        {
763                if (mCullFrustum)
764                {
765                        return mCullFrustum->projectSphere(sphere, left, top, right, bottom);
766                }
767                else
768                {
769                        return Frustum::projectSphere(sphere, left, top, right, bottom);
770                }
771        }
772        //-----------------------------------------------------------------------
773        Real Camera::getNearClipDistance(void) const
774        {
775                if (mCullFrustum)
776                {
777                        return mCullFrustum->getNearClipDistance();
778                }
779                else
780                {
781                        return Frustum::getNearClipDistance();
782                }
783        }
784        //-----------------------------------------------------------------------
785        Real Camera::getFarClipDistance(void) const
786        {
787                if (mCullFrustum)
788                {
789                        return mCullFrustum->getFarClipDistance();
790                }
791                else
792                {
793                        return Frustum::getFarClipDistance();
794                }
795        }
796        //-----------------------------------------------------------------------
797        const Matrix4& Camera::getViewMatrix(void) const
798        {
799                if (mCullFrustum)
800                {
801                        return mCullFrustum->getViewMatrix();
802                }
803                else
804                {
805                        return Frustum::getViewMatrix();
806                }
807        }
808        //-----------------------------------------------------------------------
809        const Matrix4& Camera::getViewMatrix(bool ownFrustumOnly) const
810        {
811                if (ownFrustumOnly)
812                {
813                        return Frustum::getViewMatrix();
814                }
815                else
816                {
817                        return getViewMatrix();
818                }
819        }
820        //-----------------------------------------------------------------------
821        //_______________________________________________________
822        //|                                                                                                             |
823        //|     getRayForwardIntersect                                                          |
824        //|     -----------------------------                                           |
825        //|     get the intersections of frustum rays with a plane      |
826        //| of interest.  The plane is assumed to have constant |
827        //| z.  If this is not the case, rays                                   |
828        //| should be rotated beforehand to work in a                   |
829        //| coordinate system in which this is true.                    |
830        //|_____________________________________________________|
831        //
832        std::vector<Vector4> Camera::getRayForwardIntersect(const Vector3& anchor, const Vector3 *dir, Real planeOffset) const
833        {
834                std::vector<Vector4> res;
835
836                if(!dir)
837                        return res;
838
839                int infpt[4] = {0, 0, 0, 0}; // 0=finite, 1=infinite, 2=straddles infinity
840                Vector3 vec[4];
841
842                // find how much the anchor point must be displaced in the plane's
843                // constant variable
844                Real delta = planeOffset - anchor.z;
845
846                // now set the intersection point and note whether it is a
847                // point at infinity or straddles infinity
848                unsigned int i;
849                for (i=0; i<4; i++)
850                {
851                        Real test = dir[i].z * delta;
852                        if (test == 0.0) {
853                                vec[i] = dir[i];
854                                infpt[i] = 1;
855                        }
856                        else {
857                                Real lambda = delta / dir[i].z;
858                                vec[i] = anchor + (lambda * dir[i]);
859                                if(test < 0.0)
860                                        infpt[i] = 2;
861                        }
862                }
863
864                for (i=0; i<4; i++)
865                {
866                        // store the finite intersection points
867                        if (infpt[i] == 0)
868                                res.push_back(Vector4(vec[i].x, vec[i].y, vec[i].z, 1.0));
869                        else
870                        {
871                                // handle the infinite points of intersection;
872                                // cases split up into the possible frustum planes
873                                // pieces which may contain a finite intersection point
874                                int nextind = (i+1) % 4;
875                                int prevind = (i+3) % 4;
876                                if ((infpt[prevind] == 0) || (infpt[nextind] == 0))
877                                {
878                                        if (infpt[i] == 1)
879                                                res.push_back(Vector4(vec[i].x, vec[i].y, vec[i].z, 0.0));
880                                        else
881                                        {
882                                                // handle the intersection points that straddle infinity (back-project)
883                                                if(infpt[prevind] == 0) 
884                                                {
885                                                        Vector3 temp = vec[prevind] - vec[i];
886                                                        res.push_back(Vector4(temp.x, temp.y, temp.z, 0.0));
887                                                }
888                                                if(infpt[nextind] == 0)
889                                                {
890                                                        Vector3 temp = vec[nextind] - vec[i];
891                                                        res.push_back(Vector4(temp.x, temp.y, temp.z, 0.0));
892                                                }
893                                        }
894                                } // end if we need to add an intersection point to the list
895                        } // end if infinite point needs to be considered
896                } // end loop over frustun corners
897
898                // we end up with either 0, 3, 4, or 5 intersection points
899
900                return res;
901        }
902
903        //_______________________________________________________
904        //|                                                                                                             |
905        //|     forwardIntersect                                                                        |
906        //|     -----------------------------                                           |
907        //|     Forward intersect the camera's frustum rays with        |
908        //| a specified plane of interest.                                              |
909        //| Note that if the frustum rays shoot out and would   |
910        //| back project onto the plane, this means the forward |
911        //| intersection of the frustum would occur at the              |
912        //| line at infinity.                                                                   |
913        //|_____________________________________________________|
914        //
915        void Camera::forwardIntersect(const Plane& worldPlane, std::vector<Vector4>* intersect3d) const
916        {
917                if(!intersect3d)
918                        return;
919
920                Vector3 trCorner = getWorldSpaceCorners()[0];
921                Vector3 tlCorner = getWorldSpaceCorners()[1];
922                Vector3 blCorner = getWorldSpaceCorners()[2];
923                Vector3 brCorner = getWorldSpaceCorners()[3];
924
925                // need some sort of rotation that will bring the plane normal to the z axis
926                Plane pval = worldPlane;
927                if(pval.normal.z < 0.0)
928                {
929                        pval.normal *= -1.0;
930                        pval.d *= -1.0;
931                }
932                Quaternion invPlaneRot = pval.normal.getRotationTo(Vector3::UNIT_Z);
933
934                // get rotated light
935                Vector3 lPos = invPlaneRot * getDerivedPosition();
936                Vector3 vec[4];
937                vec[0] = invPlaneRot * trCorner - lPos;
938                vec[1] = invPlaneRot * tlCorner - lPos; 
939                vec[2] = invPlaneRot * blCorner - lPos; 
940                vec[3] = invPlaneRot * brCorner - lPos; 
941
942                // compute intersection points on plane
943                std::vector<Vector4> iPnt = getRayForwardIntersect(lPos, vec, -pval.d);
944
945
946                // return wanted data
947                if(intersect3d) 
948                {
949                        Quaternion planeRot = invPlaneRot.Inverse();
950                        (*intersect3d).clear();
951                        for(unsigned int i=0; i<iPnt.size(); i++)
952                        {
953                                Vector3 intersection = planeRot * Vector3(iPnt[i].x, iPnt[i].y, iPnt[i].z);
954                                (*intersect3d).push_back(Vector4(intersection.x, intersection.y, intersection.z, iPnt[i].w));
955                        }
956                }
957        }
958        //-----------------------------------------------------------------------
959
960
961} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.