1 // placementtrans.hxx -- class for carrying transforms for placing models in the world
3 // Written by Mathias Froehlich, started April 2005.
5 // Copyright (C) 2005 Mathias Froehlich
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 # include <simgear_config.h>
27 # error This library requires C++
30 #include <osgDB/Registry>
31 #include <osgDB/Input>
32 #include <osgDB/Output>
34 #include <simgear/compiler.h>
35 #include <simgear/constants.h>
37 #include "placementtrans.hxx"
39 #include <simgear/scene/util/SGUpdateVisitor.hxx>
41 class SGPlacementTransform::UpdateCallback : public osg::NodeCallback {
43 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
45 // short circuit updates if the model we place with that branch
47 // Note that the transform is still correct.
48 SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
50 SGPlacementTransform* placementTransform;
51 placementTransform = static_cast<SGPlacementTransform*>(node);
52 double dist2 = distSqr(updateVisitor->getGlobalEyePos(),
53 placementTransform->getGlobalPos());
54 if (updateVisitor->getSqrVisibility() < dist2)
57 // note, callback is responsible for scenegraph traversal so
58 // should always include call traverse(node,nv) to ensure
59 // that the rest of cullbacks and the scene graph are traversed.
65 SGPlacementTransform::SGPlacementTransform(void) :
66 _placement_offset(0, 0, 0),
67 _rotation(SGQuatd::unit())
69 setUpdateCallback(new UpdateCallback);
72 SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
73 const osg::CopyOp& copyop):
74 osg::Transform(trans, copyop),
75 _placement_offset(trans._placement_offset),
76 _rotation(trans._rotation)
81 SGPlacementTransform::~SGPlacementTransform(void)
86 SGPlacementTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
87 osg::NodeVisitor*) const
89 if (_referenceFrame == RELATIVE_RF) {
90 matrix.preMultTranslate(_placement_offset.osg());
91 matrix.preMultRotate(_rotation.osg());
93 matrix.makeRotate(_rotation.osg());
94 matrix.postMultTranslate(_placement_offset.osg());
100 SGPlacementTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
101 osg::NodeVisitor*) const
103 if (_referenceFrame == RELATIVE_RF) {
104 matrix.postMultTranslate(-_placement_offset.osg());
105 matrix.postMultRotate(inverse(_rotation).osg());
107 matrix.makeRotate(inverse(_rotation).osg());
108 matrix.preMultTranslate(-_placement_offset.osg());
113 // Functions to read / write SGPlacementTrans from / to a .osg file,
114 // mostly for debugging purposes.
118 bool PlacementTrans_readLocalData(osg::Object& obj, osgDB::Input& fr)
120 SGPlacementTransform& trans = static_cast<SGPlacementTransform&>(obj);
121 SGQuatd rotation = SGQuatd::unit();
122 SGVec3d placementOffset(0, 0, 0);
124 if (fr[0].matchWord("rotation")) {
127 if (fr.readSequence(vec4)) {
128 rotation = SGQuatd(vec4[0], vec4[1], vec4[2], vec4[3]);
133 if (fr[0].matchWord("placement")) {
135 if (fr.readSequence(placementOffset.osg()))
140 trans.setTransform(placementOffset, rotation);
144 bool PlacementTrans_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
146 const SGPlacementTransform& trans
147 = static_cast<const SGPlacementTransform&>(obj);
148 const SGQuatd& rotation = trans.getRotation();
149 const SGVec3d& placement = trans.getGlobalPos();
151 fw.indent() << "rotation ";
152 for (int i = 0; i < 4; i++) {
153 fw << rotation(i) << " ";
156 int prec = fw.precision();
158 fw.indent() << "placement ";
159 for (int i = 0; i < 3; i++) {
160 fw << placement(i) << " ";
168 osgDB::RegisterDotOsgWrapperProxy g_SGPlacementTransProxy
170 new SGPlacementTransform,
171 "SGPlacementTransform",
172 "Object Node Transform SGPlacementTransform Group",
173 &PlacementTrans_readLocalData,
174 &PlacementTrans_writeLocalData