root/OpenSceneGraph/trunk/src/osg/AutoTransform.cpp @ 7965

Revision 7965, 7.7 kB (checked in by robert, 6 years ago)

Added minimum and maximum scale support to osg::AutoTransform?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13#include <osg/AutoTransform>
14#include <osg/CullStack>
15#include <osg/Notify>
16#include <osg/io_utils>
17
18using namespace osg;
19
20AutoTransform::AutoTransform():
21    _autoUpdateEyeMovementTolerance(0.0f),
22    _autoRotateMode(NO_ROTATION),
23    _autoScaleToScreen(false),
24    _scale(1.0f,1.0f,1.0f),
25    _firstTimeToInitEyePoint(true),
26    _minimumScale(0.0f),
27    _maximumScale(FLT_MAX),
28    _matrixDirty(true)
29{
30//    setNumChildrenRequiringUpdateTraversal(1);
31}
32
33AutoTransform::AutoTransform(const AutoTransform& pat,const CopyOp& copyop):
34    Transform(pat,copyop),
35    _position(pat._position),
36    _pivotPoint(pat._pivotPoint),
37    _autoUpdateEyeMovementTolerance(pat._autoUpdateEyeMovementTolerance),
38    _autoRotateMode(pat._autoRotateMode),
39    _autoScaleToScreen(pat._autoScaleToScreen),
40    _rotation(pat._rotation),
41    _scale(pat._scale),
42    _firstTimeToInitEyePoint(true),
43    _minimumScale(pat._minimumScale),
44    _maximumScale(pat._maximumScale),
45    _matrixDirty(true)
46{
47//    setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);           
48}
49
50void AutoTransform::setScale(const Vec3& scale)
51{
52    _scale = scale;
53    if (_scale.x()<_minimumScale) _scale.x() = _minimumScale;
54    if (_scale.y()<_minimumScale) _scale.y() = _minimumScale;
55    if (_scale.z()<_minimumScale) _scale.z() = _minimumScale;
56   
57    if (_scale.x()>_maximumScale) _scale.x() = _maximumScale;
58    if (_scale.y()>_maximumScale) _scale.y() = _maximumScale;
59    if (_scale.z()>_maximumScale) _scale.z() = _maximumScale;
60   
61    _matrixDirty=true;
62    dirtyBound();
63}
64
65
66bool AutoTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
67{
68    if (_matrixDirty) computeMatrix();
69   
70    if (_referenceFrame==RELATIVE_RF)
71    {
72        matrix.preMult(_cachedMatrix);
73    }
74    else // absolute
75    {
76        matrix = _cachedMatrix;
77    }
78    return true;
79}
80
81
82bool AutoTransform::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*) const
83{
84    if (_referenceFrame==RELATIVE_RF)
85    {
86        matrix.postMult(osg::Matrix::translate(-_position)*
87                        osg::Matrix::rotate(_rotation.inverse())*
88                        osg::Matrix::scale(1.0f/_scale.x(),1.0f/_scale.y(),1.0f/_scale.z())*
89                        osg::Matrix::translate(_pivotPoint));
90    }
91    else // absolute
92    {
93        matrix = osg::Matrix::translate(-_position)*
94                 osg::Matrix::rotate(_rotation.inverse())*
95                 osg::Matrix::scale(1.0f/_scale.x(),1.0f/_scale.y(),1.0f/_scale.z())*
96                 osg::Matrix::translate(_pivotPoint);
97    }
98    return true;
99}
100
101void AutoTransform::computeMatrix() const
102{
103    if (!_matrixDirty) return;
104   
105    _cachedMatrix.set(osg::Matrix::translate(-_pivotPoint)*
106                      osg::Matrix::scale(_scale)*
107                      osg::Matrix::rotate(_rotation)*
108                      osg::Matrix::translate(_position));
109   
110    _matrixDirty = false;
111}
112
113void AutoTransform::accept(NodeVisitor& nv)
114{
115    if (nv.validNodeMask(*this))
116    {
117        // if app traversal update the frame count.
118        if (nv.getVisitorType()==NodeVisitor::UPDATE_VISITOR)
119        {
120        }
121        else
122        if (nv.getVisitorType()==NodeVisitor::CULL_VISITOR)
123        {
124
125            CullStack* cs = dynamic_cast<CullStack*>(&nv);
126            if (cs)
127            {
128
129                Viewport::value_type width = _previousWidth;
130                Viewport::value_type height = _previousHeight;
131
132                osg::Viewport* viewport = cs->getViewport();
133                if (viewport)
134                {
135                    width = viewport->width();
136                    height = viewport->height();
137                }
138
139                osg::Vec3 eyePoint = cs->getEyeLocal();
140                osg::Vec3 localUp = cs->getUpLocal();
141                osg::Vec3 position = getPosition();
142
143                const osg::Matrix& projection = *(cs->getProjectionMatrix());
144
145                bool doUpdate = _firstTimeToInitEyePoint;
146                if (!_firstTimeToInitEyePoint)
147                {
148                    osg::Vec3 dv = _previousEyePoint-eyePoint;
149                    if (dv.length2()>getAutoUpdateEyeMovementTolerance()*(eyePoint-getPosition()).length2())
150                    {
151                        doUpdate = true;
152                    }
153                    osg::Vec3 dupv = _previousLocalUp-localUp;
154                    // rotating the camera only affects ROTATE_TO_*
155                    if (_autoRotateMode &&
156                        dupv.length2()>getAutoUpdateEyeMovementTolerance())
157                    {
158                        doUpdate = true;
159                    }
160                    else if (width!=_previousWidth || height!=_previousHeight)
161                    {
162                        doUpdate = true;
163                    }
164                    else if (projection != _previousProjection)
165                    {
166                        doUpdate = true;
167                    }               
168                    else if (position != _previousPosition)
169                    {
170                        doUpdate = true;
171                    }
172                }
173                _firstTimeToInitEyePoint = false;
174
175                if (doUpdate)
176                {           
177
178                    if (getAutoScaleToScreen())
179                    {
180                        float size = 1.0f/cs->pixelSize(getPosition(),0.48f);
181                       
182                        if (size<_minimumScale) size = _minimumScale;
183                        if (size>_maximumScale) size = _maximumScale;
184                       
185                        setScale(size);
186                    }
187
188                    if (_autoRotateMode==ROTATE_TO_SCREEN)
189                    {
190                        osg::Vec3d translation;
191                        osg::Quat rotation;
192                        osg::Vec3d scale;
193                        osg::Quat so;
194                       
195                        cs->getModelViewMatrix()->decompose( translation, rotation, scale, so );
196
197                        setRotation(rotation.inverse());
198                    }
199                    else if (_autoRotateMode==ROTATE_TO_CAMERA)
200                    {
201                        osg::Vec3 PosToEye = _position - eyePoint;
202                        osg::Matrix lookto = osg::Matrix::lookAt(
203                            osg::Vec3(0,0,0), PosToEye, localUp);
204                        Quat q;
205                        q.set(osg::Matrix::inverse(lookto));
206                        setRotation(q);
207                    }
208
209                    _previousEyePoint = eyePoint;
210                    _previousLocalUp = localUp;
211                    _previousWidth = width;
212                    _previousHeight = height;
213                    _previousProjection = projection;
214                    _previousPosition = position;
215
216                    _matrixDirty = true;
217                }
218
219            }
220        }
221
222        // now do the proper accept
223        Transform::accept(nv);
224    }
225}
226
227BoundingSphere AutoTransform::computeBound() const
228{
229    BoundingSphere bsphere;
230
231    if ( getAutoScaleToScreen() && _firstTimeToInitEyePoint )
232        return bsphere;
233
234    bsphere = Transform::computeBound();
235
236    return bsphere;
237}
Note: See TracBrowser for help on using the browser.