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 _scenery_center(0, 0, 0),
73 setUpdateCallback(new UpdateCallback);
76 SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
77 const osg::CopyOp& copyop):
78 osg::Transform(trans, copyop),
79 _placement_offset(trans._placement_offset),
80 _scenery_center(trans._scenery_center),
81 _rotation(trans._rotation)
86 SGPlacementTransform::~SGPlacementTransform(void)
91 SGPlacementTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
92 osg::NodeVisitor*) const
95 for (int i = 0; i < 3; ++i) {
96 for (int j = 0; j < 3; ++j) {
97 t(j, i) = _rotation(i, j);
99 t(3, i) = _placement_offset(i) - _scenery_center(i);
102 if (_referenceFrame == RELATIVE_RF)
110 SGPlacementTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
111 osg::NodeVisitor*) const
114 for (int i = 0; i < 3; ++i) {
115 for (int j = 0; j < 3; ++j) {
116 t(j, i) = _rotation(i, j);
118 t(3, i) = _placement_offset(i) - _scenery_center(i);
120 t = osg::Matrix::inverse(t);
122 if (_referenceFrame == RELATIVE_RF)
129 // Functions to read / write SGPlacementTrans from / to a .osg file,
130 // mostly for debugging purposes.
134 bool PlacementTrans_readLocalData(osg::Object& obj, osgDB::Input& fr)
136 SGPlacementTransform& trans = static_cast<SGPlacementTransform&>(obj);
137 SGMatrixd rotation(1, 0, 0, 0,
141 SGVec3d placementOffset(0, 0, 0);
142 SGVec3d sceneryCenter(0, 0, 0);
144 if (fr[0].matchWord("rotation") && fr[1].isOpenBracket()) {
146 for (int i = 0; i < 3; i++) {
148 if (!fr.readSequence(scratch.osg()))
151 for (int j = 0; j < 3; j++)
152 rotation(j, i) = scratch[j];
154 if (fr[0].isCloseBracket())
159 if (fr[0].matchWord("placement")) {
161 if (fr.readSequence(placementOffset.osg()))
166 if (fr[0].matchWord("sceneryCenter")) {
168 if (fr.readSequence(sceneryCenter.osg()))
173 trans.setTransform(placementOffset, rotation);
174 trans.setSceneryCenter(sceneryCenter);
178 bool PlacementTrans_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
180 const SGPlacementTransform& trans
181 = static_cast<const SGPlacementTransform&>(obj);
182 const SGMatrixd& rotation = trans.getRotation();
183 const SGVec3d& placement = trans.getGlobalPos();
184 const SGVec3d& sceneryCenter = trans.getSceneryCenter();
186 fw.indent() << "rotation {" << std::endl;
188 for (int i = 0; i < 3; i++) {
190 for (int j = 0; j < 3; j++) {
191 fw << rotation(j, i) << " ";
196 fw.indent() << "}" << std::endl;
197 int prec = fw.precision();
199 fw.indent() << "placement ";
200 for (int i = 0; i < 3; i++) {
201 fw << placement(i) << " ";
204 fw.indent() << "sceneryCenter ";
205 for (int i = 0; i < 3; i++) {
206 fw << sceneryCenter(i) << " ";
214 osgDB::RegisterDotOsgWrapperProxy g_SGPlacementTransProxy
216 new SGPlacementTransform,
217 "SGPlacementTransform",
218 "Object Node Transform SGPlacementTransform Group",
219 &PlacementTrans_readLocalData,
220 &PlacementTrans_writeLocalData