AnimatLab  2
Test
VsAutoTransform.cpp
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 "VsAutoTransform.h"
14 #include <osg/CullStack>
15 #include <osg/Notify>
16 #include <osg/io_utils>
17 
18 using namespace osg;
19 
20 namespace VortexAnimatSim
21 {
22  namespace Visualization
23  {
24 
25 VsAutoTransform::VsAutoTransform() :
26  _autoUpdateEyeMovementTolerance(0.0),
27  _autoRotateMode(NO_ROTATION),
28  _autoScaleToScreen(false),
29  _scale(1.0,1.0,1.0),
30  _firstTimeToInitEyePoint(true),
31  _minimumScale(0.0),
32  _maximumScale(DBL_MAX),
33  _autoScaleTransitionWidthRatio(0.25),
34  _matrixDirty(true)
35 {
36 // setNumChildrenRequiringUpdateTraversal(1);
37 }
38 
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),
47  _scale(pat._scale),
48  _firstTimeToInitEyePoint(true),
49  _minimumScale(pat._minimumScale),
50  _maximumScale(pat._maximumScale),
51  _autoScaleTransitionWidthRatio(pat._autoScaleTransitionWidthRatio),
52  _matrixDirty(true)
53 {
54 // setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
55 }
56 
57 void VsAutoTransform::setScale(const Vec3d& scale)
58 {
59  _scale = 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;
63 
64  if (_scale.x()>_maximumScale) _scale.x() = _maximumScale;
65  if (_scale.y()>_maximumScale) _scale.y() = _maximumScale;
66  if (_scale.z()>_maximumScale) _scale.z() = _maximumScale;
67 
68  _matrixDirty=true;
69  dirtyBound();
70 }
71 
72 
73 bool VsAutoTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
74 {
75  if (_matrixDirty) computeMatrix();
76 
77  if (_referenceFrame==RELATIVE_RF)
78  {
79  matrix.preMult(_cachedMatrix);
80  }
81  else // absolute
82  {
83  matrix = _cachedMatrix;
84  }
85  return true;
86 }
87 
88 
89 bool VsAutoTransform::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*) const
90 {
91  if (_scale.x() == 0.0 || _scale.y() == 0.0 || _scale.z() == 0.0)
92  return false;
93 
94  if (_referenceFrame==RELATIVE_RF)
95  {
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);
100  }
101  else // absolute
102  {
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);
107  }
108  return true;
109 }
110 
111 void VsAutoTransform::computeMatrix() const
112 {
113  if (!_matrixDirty) return;
114 
115  _cachedMatrix.makeRotate(_rotation);
116  _cachedMatrix.postMultTranslate(_position);
117  _cachedMatrix.preMultScale(_scale);
118  _cachedMatrix.preMultTranslate(-_pivotPoint);
119 
120  _matrixDirty = false;
121 }
122 
123 void VsAutoTransform::accept(NodeVisitor& nv)
124 {
125  if (nv.validNodeMask(*this))
126  {
127  // if app traversal update the frame count.
128  if (nv.getVisitorType()==NodeVisitor::UPDATE_VISITOR)
129  {
130  }
131  else
132  if (nv.getVisitorType()==NodeVisitor::CULL_VISITOR)
133  {
134 
135  CullStack* cs = dynamic_cast<CullStack*>(&nv);
136  if (cs)
137  {
138 
139  Viewport::value_type width = _previousWidth;
140  Viewport::value_type height = _previousHeight;
141 
142  osg::Viewport* viewport = cs->getViewport();
143  if (viewport)
144  {
145  width = viewport->width();
146  height = viewport->height();
147  }
148 
149  osg::Vec3d eyePoint = cs->getEyeLocal();
150  osg::Vec3d localUp = cs->getUpLocal();
151  osg::Vec3d position = getPosition();
152 
153  const osg::Matrix& projection = *(cs->getProjectionMatrix());
154 
155  bool doUpdate = _firstTimeToInitEyePoint;
156  if (!_firstTimeToInitEyePoint)
157  {
158  osg::Vec3d dv = _previousEyePoint-eyePoint;
159  if (dv.length2()>getAutoUpdateEyeMovementTolerance()*(eyePoint-getPosition()).length2())
160  {
161  doUpdate = true;
162  }
163  osg::Vec3d dupv = _previousLocalUp-localUp;
164  // rotating the camera only affects ROTATE_TO_*
165  if (_autoRotateMode &&
166  dupv.length2()>getAutoUpdateEyeMovementTolerance())
167  {
168  doUpdate = true;
169  }
170  else if (width!=_previousWidth || height!=_previousHeight)
171  {
172  doUpdate = true;
173  }
174  else if (projection != _previousProjection)
175  {
176  doUpdate = true;
177  }
178  else if (position != _previousPosition)
179  {
180  doUpdate = true;
181  }
182  }
183  _firstTimeToInitEyePoint = false;
184 
185  if (doUpdate)
186  {
187 
188  if (getAutoScaleToScreen())
189  {
190  double size = 1.0/cs->pixelSize(getPosition(),0.48f);
191 
192  if (_autoScaleTransitionWidthRatio>0.0)
193  {
194  if (_minimumScale>0.0)
195  {
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);
204 
205  if (size<k) size = _minimumScale;
206  else if (size<i) size = a + b*size + c*(size*size);
207  }
208 
209  if (_maximumScale<DBL_MAX)
210  {
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);
219 
220  if (size>p) size = _maximumScale;
221  else if (size>m) size = a + b*size + c*(size*size);
222  }
223  }
224 
225  setScale(size);
226  }
227 
228  if (_autoRotateMode==ROTATE_TO_SCREEN)
229  {
230  osg::Vec3d translation;
231  osg::Quat rotation;
232  osg::Vec3d scale;
233  osg::Quat so;
234 
235  cs->getModelViewMatrix()->decompose( translation, rotation, scale, so );
236 
237  setRotation(rotation.inverse());
238  }
239  else if (_autoRotateMode==ROTATE_TO_CAMERA)
240  {
241  osg::Vec3d PosToEye = _position - eyePoint;
242  osg::Matrix lookto = osg::Matrix::lookAt(
243  osg::Vec3d(0,0,0), PosToEye, localUp);
244  Quat q;
245  q.set(osg::Matrix::inverse(lookto));
246  setRotation(q);
247  }
248 
249  _previousEyePoint = eyePoint;
250  _previousLocalUp = localUp;
251  _previousWidth = width;
252  _previousHeight = height;
253  _previousProjection = projection;
254  _previousPosition = position;
255 
256  _matrixDirty = true;
257  }
258 
259  }
260  }
261 
262  // now do the proper accept
263  Transform::accept(nv);
264  }
265 }
266 
267 BoundingSphere VsAutoTransform::computeBound() const
268 {
269  BoundingSphere bsphere;
270 
271  if ( getAutoScaleToScreen() && _firstTimeToInitEyePoint )
272  return bsphere;
273 
274  bsphere = Transform::computeBound();
275 
276  return bsphere;
277 }
278 
279  }// end Visualization
280 }// end VortexAnimatSim
Classes for implementing the cm-labs vortex physics engine for AnimatLab.