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),
72 setUpdateCallback(new UpdateCallback);
75 SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
76 const osg::CopyOp& copyop):
77 osg::Transform(trans, copyop),
78 _placement_offset(trans._placement_offset),
79 _rotation(trans._rotation)
84 SGPlacementTransform::~SGPlacementTransform(void)
89 SGPlacementTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
90 osg::NodeVisitor*) const
93 for (int i = 0; i < 3; ++i) {
94 for (int j = 0; j < 3; ++j) {
95 t(j, i) = _rotation(i, j);
97 t(3, i) = _placement_offset(i);
100 if (_referenceFrame == RELATIVE_RF)
108 SGPlacementTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
109 osg::NodeVisitor*) const
112 for (int i = 0; i < 3; ++i) {
113 for (int j = 0; j < 3; ++j) {
114 t(j, i) = _rotation(i, j);
116 t(3, i) = _placement_offset(i);
118 t = osg::Matrix::inverse(t);
120 if (_referenceFrame == RELATIVE_RF)
127 // Functions to read / write SGPlacementTrans from / to a .osg file,
128 // mostly for debugging purposes.
132 bool PlacementTrans_readLocalData(osg::Object& obj, osgDB::Input& fr)
134 SGPlacementTransform& trans = static_cast<SGPlacementTransform&>(obj);
135 SGMatrixd rotation(1, 0, 0, 0,
139 SGVec3d placementOffset(0, 0, 0);
141 if (fr[0].matchWord("rotation") && fr[1].isOpenBracket()) {
143 for (int i = 0; i < 3; i++) {
145 if (!fr.readSequence(scratch.osg()))
148 for (int j = 0; j < 3; j++)
149 rotation(j, i) = scratch[j];
151 if (fr[0].isCloseBracket())
156 if (fr[0].matchWord("placement")) {
158 if (fr.readSequence(placementOffset.osg()))
163 trans.setTransform(placementOffset, rotation);
167 bool PlacementTrans_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
169 const SGPlacementTransform& trans
170 = static_cast<const SGPlacementTransform&>(obj);
171 const SGMatrixd& rotation = trans.getRotation();
172 const SGVec3d& placement = trans.getGlobalPos();
174 fw.indent() << "rotation {" << std::endl;
176 for (int i = 0; i < 3; i++) {
178 for (int j = 0; j < 3; j++) {
179 fw << rotation(j, i) << " ";
184 fw.indent() << "}" << std::endl;
185 int prec = fw.precision();
187 fw.indent() << "placement ";
188 for (int i = 0; i < 3; i++) {
189 fw << placement(i) << " ";
197 osgDB::RegisterDotOsgWrapperProxy g_SGPlacementTransProxy
199 new SGPlacementTransform,
200 "SGPlacementTransform",
201 "Object Node Transform SGPlacementTransform Group",
202 &PlacementTrans_readLocalData,
203 &PlacementTrans_writeLocalData