13 #include "VsAutoTransform.h"
14 #include <osg/CullStack>
16 #include <osg/io_utils>
22 namespace Visualization
25 VsAutoTransform::VsAutoTransform() :
26 _autoUpdateEyeMovementTolerance(0.0),
27 _autoRotateMode(NO_ROTATION),
28 _autoScaleToScreen(false),
30 _firstTimeToInitEyePoint(true),
32 _maximumScale(DBL_MAX),
33 _autoScaleTransitionWidthRatio(0.25),
39 VsAutoTransform::VsAutoTransform(
const VsAutoTransform& pat,
const CopyOp& copyop):
40 Transform(pat,copyop),
41 _position(pat._position),
42 _pivotPoint(pat._pivotPoint),
43 _autoUpdateEyeMovementTolerance(pat._autoUpdateEyeMovementTolerance),
44 _autoRotateMode(pat._autoRotateMode),
45 _autoScaleToScreen(pat._autoScaleToScreen),
46 _rotation(pat._rotation),
48 _firstTimeToInitEyePoint(true),
49 _minimumScale(pat._minimumScale),
50 _maximumScale(pat._maximumScale),
51 _autoScaleTransitionWidthRatio(pat._autoScaleTransitionWidthRatio),
57 void VsAutoTransform::setScale(
const Vec3d& scale)
60 if (_scale.x()<_minimumScale) _scale.x() = _minimumScale;
61 if (_scale.y()<_minimumScale) _scale.y() = _minimumScale;
62 if (_scale.z()<_minimumScale) _scale.z() = _minimumScale;
64 if (_scale.x()>_maximumScale) _scale.x() = _maximumScale;
65 if (_scale.y()>_maximumScale) _scale.y() = _maximumScale;
66 if (_scale.z()>_maximumScale) _scale.z() = _maximumScale;
73 bool VsAutoTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*)
const
75 if (_matrixDirty) computeMatrix();
77 if (_referenceFrame==RELATIVE_RF)
79 matrix.preMult(_cachedMatrix);
83 matrix = _cachedMatrix;
89 bool VsAutoTransform::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*)
const
91 if (_scale.x() == 0.0 || _scale.y() == 0.0 || _scale.z() == 0.0)
94 if (_referenceFrame==RELATIVE_RF)
96 matrix.postMultTranslate(-_position);
97 matrix.postMultRotate(_rotation.inverse());
98 matrix.postMultScale(Vec3d(1.0/_scale.x(), 1.0/_scale.y(), 1.0/_scale.z()));
99 matrix.postMultTranslate(_pivotPoint);
103 matrix.makeRotate(_rotation.inverse());
104 matrix.preMultTranslate(-_position);
105 matrix.postMultScale(Vec3d(1.0/_scale.x(), 1.0/_scale.y(), 1.0/_scale.z()));
106 matrix.postMultTranslate(_pivotPoint);
111 void VsAutoTransform::computeMatrix()
const
113 if (!_matrixDirty)
return;
115 _cachedMatrix.makeRotate(_rotation);
116 _cachedMatrix.postMultTranslate(_position);
117 _cachedMatrix.preMultScale(_scale);
118 _cachedMatrix.preMultTranslate(-_pivotPoint);
120 _matrixDirty =
false;
123 void VsAutoTransform::accept(NodeVisitor& nv)
125 if (nv.validNodeMask(*
this))
128 if (nv.getVisitorType()==NodeVisitor::UPDATE_VISITOR)
132 if (nv.getVisitorType()==NodeVisitor::CULL_VISITOR)
135 CullStack* cs =
dynamic_cast<CullStack*
>(&nv);
139 Viewport::value_type width = _previousWidth;
140 Viewport::value_type height = _previousHeight;
142 osg::Viewport* viewport = cs->getViewport();
145 width = viewport->width();
146 height = viewport->height();
149 osg::Vec3d eyePoint = cs->getEyeLocal();
150 osg::Vec3d localUp = cs->getUpLocal();
151 osg::Vec3d position = getPosition();
153 const osg::Matrix& projection = *(cs->getProjectionMatrix());
155 bool doUpdate = _firstTimeToInitEyePoint;
156 if (!_firstTimeToInitEyePoint)
158 osg::Vec3d dv = _previousEyePoint-eyePoint;
159 if (dv.length2()>getAutoUpdateEyeMovementTolerance()*(eyePoint-getPosition()).length2())
163 osg::Vec3d dupv = _previousLocalUp-localUp;
165 if (_autoRotateMode &&
166 dupv.length2()>getAutoUpdateEyeMovementTolerance())
170 else if (width!=_previousWidth || height!=_previousHeight)
174 else if (projection != _previousProjection)
178 else if (position != _previousPosition)
183 _firstTimeToInitEyePoint =
false;
188 if (getAutoScaleToScreen())
190 double size = 1.0/cs->pixelSize(getPosition(),0.48f);
192 if (_autoScaleTransitionWidthRatio>0.0)
194 if (_minimumScale>0.0)
196 double j = _minimumScale;
197 double i = (_maximumScale<DBL_MAX) ?
198 _minimumScale+(_maximumScale-_minimumScale)*_autoScaleTransitionWidthRatio :
199 _minimumScale*(1.0+_autoScaleTransitionWidthRatio);
200 double c = 1.0/(4.0*(i-j));
201 double b = 1.0 - 2.0*c*i;
202 double a = j + b*b / (4.0*c);
203 double k = -b / (2.0*c);
205 if (size<k) size = _minimumScale;
206 else if (size<i) size = a + b*size + c*(size*size);
209 if (_maximumScale<DBL_MAX)
211 double n = _maximumScale;
212 double m = (_minimumScale>0.0) ?
213 _maximumScale+(_minimumScale-_maximumScale)*_autoScaleTransitionWidthRatio :
214 _maximumScale*(1.0-_autoScaleTransitionWidthRatio);
215 double c = 1.0 / (4.0*(m-n));
216 double b = 1.0 - 2.0*c*m;
217 double a = n + b*b/(4.0*c);
218 double p = -b / (2.0*c);
220 if (size>p) size = _maximumScale;
221 else if (size>m) size = a + b*size + c*(size*size);
228 if (_autoRotateMode==ROTATE_TO_SCREEN)
230 osg::Vec3d translation;
235 cs->getModelViewMatrix()->decompose( translation, rotation, scale, so );
237 setRotation(rotation.inverse());
239 else if (_autoRotateMode==ROTATE_TO_CAMERA)
241 osg::Vec3d PosToEye = _position - eyePoint;
242 osg::Matrix lookto = osg::Matrix::lookAt(
243 osg::Vec3d(0,0,0), PosToEye, localUp);
245 q.set(osg::Matrix::inverse(lookto));
249 _previousEyePoint = eyePoint;
250 _previousLocalUp = localUp;
251 _previousWidth = width;
252 _previousHeight = height;
253 _previousProjection = projection;
254 _previousPosition = position;
263 Transform::accept(nv);
267 BoundingSphere VsAutoTransform::computeBound()
const
269 BoundingSphere bsphere;
271 if ( getAutoScaleToScreen() && _firstTimeToInitEyePoint )
274 bsphere = Transform::computeBound();
Classes for implementing the cm-labs vortex physics engine for AnimatLab.