]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/placementtrans.cxx
Modified Files:
[simgear.git] / simgear / scene / model / placementtrans.cxx
1 // placementtrans.hxx -- class for carrying transforms for placing models in the world
2 //
3 // Written by Mathias Froehlich, started April 2005.
4 //
5 // Copyright (C) 2005 Mathias Froehlich
6 //
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.
11 //
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.
16 //
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.
20 //
21
22 #ifdef HAVE_CONFIG_H
23 #  include <simgear_config.h>
24 #endif
25
26 #ifndef __cplusplus
27 # error This library requires C++
28 #endif
29
30 #include <simgear/compiler.h>
31 #include <simgear/constants.h>
32
33 #include "placementtrans.hxx"
34
35 #include <simgear/scene/util/SGUpdateVisitor.hxx>
36
37 class SGPlacementTransform::UpdateCallback : public osg::NodeCallback {
38 public:
39   virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
40   {
41     // short circuit updates if the model we place with that branch
42     // out of sight.
43     // Note that the transform is still correct.
44     SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
45     if (updateVisitor) {
46       SGPlacementTransform* placementTransform;
47       placementTransform = static_cast<SGPlacementTransform*>(node);
48       double dist2 = distSqr(updateVisitor->getGlobalEyePos(),
49                              placementTransform->getGlobalPos());
50       if (updateVisitor->getSqrVisibility() < dist2)
51         return;
52     }
53     // note, callback is responsible for scenegraph traversal so
54     // should always include call traverse(node,nv) to ensure 
55     // that the rest of cullbacks and the scene graph are traversed.
56     traverse(node, nv);
57   }
58 };
59
60
61 SGPlacementTransform::SGPlacementTransform(void) :
62   _placement_offset(0, 0, 0),
63   _scenery_center(0, 0, 0),
64   _rotation(1, 0, 0, 0,
65             0, 1, 0, 0,
66             0, 0, 1, 0,
67             0, 0, 0, 1)
68 {
69   setUpdateCallback(new UpdateCallback);
70 }
71
72 SGPlacementTransform::~SGPlacementTransform(void)
73 {
74 }
75
76 bool
77 SGPlacementTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
78                                                 osg::NodeVisitor*) const
79 {
80   osg::Matrix t;
81   for (int i = 0; i < 3; ++i) {
82     for (int j = 0; j < 3; ++j) {
83       t(j, i) = _rotation(i, j);
84     }
85     t(3, i) = _placement_offset(i) - _scenery_center(i);
86   }
87   
88   if (_referenceFrame == RELATIVE_RF)
89     matrix.preMult(t);
90   else
91     matrix = t;
92   return true;
93 }
94
95 bool
96 SGPlacementTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
97                                                 osg::NodeVisitor*) const
98 {
99   osg::Matrix t;
100   for (int i = 0; i < 3; ++i) {
101     for (int j = 0; j < 3; ++j) {
102       t(j, i) = _rotation(i, j);
103     }
104     t(3, i) = _placement_offset(i) - _scenery_center(i);
105   }
106   t = osg::Matrix::inverse(t);
107
108   if (_referenceFrame == RELATIVE_RF)
109     matrix.postMult(t);
110   else
111     matrix = t;
112   return true;
113 }