]> git.mxchange.org Git - flightgear.git/blob - utils/fgviewer/HLASceneObject.cxx
fgviewer: Import hla based viewer application.
[flightgear.git] / utils / fgviewer / HLASceneObject.cxx
1 // Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
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 GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include "HLASceneObject.hxx"
23
24 #include <osg/Transform>
25
26 #include <simgear/scene/util/OsgMath.hxx>
27 #include <simgear/hla/HLAArrayDataElement.hxx>
28 #include <simgear/scene/util/SGReaderWriterOptions.hxx>
29
30 #include "HLASceneObjectClass.hxx"
31 #include "HLAViewerFederate.hxx"
32
33 namespace fgviewer {
34
35 class HLASceneObject::_ModelDataElement : public simgear::HLAProxyDataElement {
36 public:
37     _ModelDataElement(const SGWeakPtr<HLASceneObject>& sceneObject) :
38         _sceneObject(sceneObject)
39     { }
40     virtual ~_ModelDataElement()
41     { }
42     
43     virtual bool decode(simgear::HLADecodeStream& stream)
44     {
45         if (!HLAProxyDataElement::decode(stream))
46             return false;
47         
48         // No change?
49         if (!_name.getDataElement()->getDirty())
50             return true;
51         _name.getDataElement()->setDirty(false);
52         SGSharedPtr<HLASceneObject> sceneObject = _sceneObject.lock();
53         if (sceneObject.valid())
54             sceneObject->_setModelFileName(_name.getValue());
55         return true;
56     }
57     
58 protected:
59     virtual simgear::HLAStringDataElement* _getDataElement()
60     { return _name.getDataElement(); }
61     virtual const simgear::HLAStringDataElement* _getDataElement() const
62     { return _name.getDataElement(); }
63     
64 private:
65     const SGWeakPtr<HLASceneObject> _sceneObject;
66     simgear::HLAStringData _name;
67 };
68
69 class HLASceneObject::_Transform : public osg::Transform {
70 public:
71     _Transform(const SGWeakPtr<const HLASceneObject>& sceneObject) :
72         _sceneObject(sceneObject)
73     {
74         setCullingActive(false);
75     }
76     virtual ~_Transform()
77     {
78     }
79
80     virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
81     {
82         if (!nv)
83             return false;
84         const osg::FrameStamp* frameStamp = nv->getFrameStamp();
85         if (!frameStamp)
86             return false;
87         
88         SGLocationd location = _getLocation(SGTimeStamp::fromSec(frameStamp->getSimulationTime()));
89         // the position of the view
90         matrix.preMultTranslate(toOsg(location.getPosition()));
91         // the orientation of the view
92         matrix.preMultRotate(toOsg(location.getOrientation()));
93     
94         return true;
95     }
96     virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
97     {
98         if (!nv)
99             return false;
100         const osg::FrameStamp* frameStamp = nv->getFrameStamp();
101         if (!frameStamp)
102             return false;
103         
104         SGLocationd location = _getLocation(SGTimeStamp::fromSec(frameStamp->getSimulationTime()));
105         // the position of the view
106         matrix.postMultTranslate(toOsg(-location.getPosition()));
107         // the orientation of the view
108         matrix.postMultRotate(toOsg(inverse(location.getOrientation())));
109     
110         return true;
111     }
112
113     virtual osg::BoundingSphere computeBound() const
114     {
115         return osg::BoundingSphere();
116     }
117
118 private:
119     SGLocationd _getLocation(const SGTimeStamp& timeStamp) const
120     {
121         // transform from the simulation typical x-forward/y-right/z-down
122         // to the flightgear model system x-back/y-right/z-up
123         // SGQuatd simToModel = SGQuatd::fromEulerDeg(0, 180, 0);
124         SGQuatd simToModel = SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0));
125
126         SGSharedPtr<const HLASceneObject> sceneObject = _sceneObject.lock();
127         if (!sceneObject.valid())
128             return SGLocationd(SGVec3d(0, 0, 0), simToModel);
129
130         // Get the cartesian location at the given time stamp from the hla object
131         SGLocationd location = sceneObject->getLocation(timeStamp);
132         location.setOrientation(location.getOrientation()*simToModel);
133
134         return location;
135     }
136
137     SGWeakPtr<const HLASceneObject> _sceneObject;
138 };
139
140 HLASceneObject::HLASceneObject(HLASceneObjectClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate) :
141     HLAObjectInstance(objectClass),
142     _sceneObject(federate)
143 {
144     _pagedLOD = new osg::PagedLOD;
145     _pagedLOD->setRange(0, 0, 80000);
146         
147     _transform = new _Transform(this);
148     _transform->addChild(_pagedLOD.get());
149 }
150
151 HLASceneObject::~HLASceneObject()
152 {
153     _removeFromSceneGraph();
154 }
155
156 void
157 HLASceneObject::createAttributeDataElements()
158 {
159     /// FIXME at some point we should not need that anymore
160     HLAObjectInstance::createAttributeDataElements();
161
162     assert(dynamic_cast<HLASceneObjectClass*>(getObjectClass().get()));
163     HLASceneObjectClass& objectClass = static_cast<HLASceneObjectClass&>(*getObjectClass());
164
165     simgear::HLACartesianLocation* location = new simgear::HLACartesianLocation;
166     setAttributeDataElement(objectClass.getPositionIndex(), location->getPositionDataElement());
167     setAttributeDataElement(objectClass.getOrientationIndex(), location->getOrientationDataElement());
168     setAttributeDataElement(objectClass.getAngularVelocityIndex(), location->getAngularVelocityDataElement());
169     setAttributeDataElement(objectClass.getLinearVelocityIndex(), location->getLinearVelocityDataElement());
170     _location = location;
171
172     setAttributeDataElement(objectClass.getSceneObjectNameIndex(), _sceneObject.getDataElement());
173 }
174
175 void
176 HLASceneObject::discoverInstance(const simgear::RTIData& tag)
177 {
178     HLAObjectInstance::discoverInstance(tag);
179     _addToSceneGraph();
180 }
181
182 void
183 HLASceneObject::removeInstance(const simgear::RTIData& tag)
184 {
185     _removeFromSceneGraph();
186     HLAObjectInstance::removeInstance(tag);
187 }
188
189 void
190 HLASceneObject::registerInstance(simgear::HLAObjectClass* objectClass)
191 {
192     HLAObjectInstance::registerInstance(objectClass);
193     _addToSceneGraph();
194 }
195
196 void
197 HLASceneObject::deleteInstance(const simgear::RTIData& tag)
198 {
199     _removeFromSceneGraph();
200     HLAObjectInstance::deleteInstance(tag);
201 }
202
203 const HLASceneObject*
204 HLASceneObject::getSceneObject() const
205 {
206     return _sceneObject.getObject();
207 }
208
209 HLASceneObject*
210 HLASceneObject::getSceneObject()
211 {
212     return _sceneObject.getObject();
213 }
214
215 void
216 HLASceneObject::setSceneObject(HLASceneObject* sceneObject)
217 {
218     _sceneObject.setObject(sceneObject);
219 }
220
221 SGLocationd
222 HLASceneObject::getLocation(const SGTimeStamp& timeStamp) const
223 {
224     const HLASceneObject* sceneObject = getSceneObject();
225     if (!sceneObject)
226         return _getRelativeLocation(timeStamp);
227     return sceneObject->getLocation(timeStamp).getAbsoluteLocation(_getRelativeLocation(timeStamp));
228 }
229
230 simgear::HLADataElement*
231 HLASceneObject::getModelDataElement()
232 {
233     return new _ModelDataElement(this);
234 }
235
236 osg::Node*
237 HLASceneObject::getNode()
238 {
239     return _transform.get();
240 }
241
242 SGLocationd
243 HLASceneObject::_getRelativeLocation(const SGTimeStamp& timeStamp) const
244 {
245     if (!_location.valid())
246         return SGLocationd(SGVec3d::zeros(), SGQuatd::unit());
247     return _location->getLocation(timeStamp);
248 }
249
250 SGVec3d
251 HLASceneObject::_getRelativeAngularVelocity() const
252 {
253     if (!_location.valid())
254         return SGVec3d(0, 0, 0);
255     return _location->getAngularBodyVelocity();
256 }
257
258 SGVec3d
259 HLASceneObject::_getRelativeLinearVelocity() const
260 {
261     if (!_location.valid())
262         return SGVec3d(0, 0, 0);
263     return _location->getLinearBodyVelocity();
264 }
265
266 void
267 HLASceneObject::_setModelFileName(const std::string& fileName)
268 {
269     if (0 < _pagedLOD->getNumFileNames() && fileName == _pagedLOD->getFileName(0))
270         return;
271
272     SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
273     if (federate.valid()) {
274         assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
275         HLAViewerFederate* viewerFederate = static_cast<HLAViewerFederate*>(federate.get());
276
277         osg::ref_ptr<osgDB::Options> localOptions;
278         localOptions = static_cast<osgDB::Options*>(viewerFederate->getReaderWriterOptions()->clone(osg::CopyOp()));
279         // FIXME: particle systems have some issues. Do not use them currently.
280         localOptions->setPluginStringData("SimGear::PARTICLESYSTEM", "OFF");
281         _pagedLOD->setDatabaseOptions(localOptions.get());
282     }
283
284     // Finally set the file name
285     if (unsigned numChildren = _pagedLOD->getNumChildren())
286         _pagedLOD->removeChildren(0, numChildren);
287     _pagedLOD->setFileName(0, fileName);
288 }
289
290 void
291 HLASceneObject::_addToSceneGraph()
292 {
293     SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
294     if (!federate.valid())
295         return;
296     assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
297     HLAViewerFederate* viewerFederate = static_cast<HLAViewerFederate*>(federate.get());
298
299     /// Add ourselves to the dynamic scene graph
300     viewerFederate->addDynamicModel(getNode());
301 }
302
303 void
304 HLASceneObject::_removeFromSceneGraph()
305 {
306     /// FIXME O(#SceneObjects), pool them and reuse in create
307     unsigned i = _transform->getNumParents();
308     while (i--) {
309         osg::Group* parent = _transform->getParent(i);
310         parent->removeChild(_transform.get());
311     }
312 }
313
314 } // namespace fgviewer