1 // Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
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.
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.
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.
22 #include "HLASceneObject.hxx"
24 #include <osg/Transform>
26 #include <simgear/scene/util/OsgMath.hxx>
27 #include <simgear/hla/HLAArrayDataElement.hxx>
28 #include <simgear/scene/util/SGReaderWriterOptions.hxx>
30 #include "HLASceneObjectClass.hxx"
31 #include "HLAViewerFederate.hxx"
35 class HLASceneObject::_ModelDataElement : public simgear::HLAProxyDataElement {
37 _ModelDataElement(const SGWeakPtr<HLASceneObject>& sceneObject) :
38 _sceneObject(sceneObject)
40 virtual ~_ModelDataElement()
43 virtual bool decode(simgear::HLADecodeStream& stream)
45 if (!HLAProxyDataElement::decode(stream))
49 if (!_name.getDataElement()->getDirty())
51 _name.getDataElement()->setDirty(false);
52 SGSharedPtr<HLASceneObject> sceneObject = _sceneObject.lock();
53 if (sceneObject.valid())
54 sceneObject->_setModelFileName(_name.getValue());
59 virtual simgear::HLAStringDataElement* _getDataElement()
60 { return _name.getDataElement(); }
61 virtual const simgear::HLAStringDataElement* _getDataElement() const
62 { return _name.getDataElement(); }
65 const SGWeakPtr<HLASceneObject> _sceneObject;
66 simgear::HLAStringData _name;
69 class HLASceneObject::_Transform : public osg::Transform {
71 _Transform(const SGWeakPtr<const HLASceneObject>& sceneObject) :
72 _sceneObject(sceneObject)
74 setCullingActive(false);
80 virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
84 const osg::FrameStamp* frameStamp = nv->getFrameStamp();
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()));
96 virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
100 const osg::FrameStamp* frameStamp = nv->getFrameStamp();
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())));
113 virtual osg::BoundingSphere computeBound() const
115 return osg::BoundingSphere();
119 SGLocationd _getLocation(const SGTimeStamp& timeStamp) const
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));
126 SGSharedPtr<const HLASceneObject> sceneObject = _sceneObject.lock();
127 if (!sceneObject.valid())
128 return SGLocationd(SGVec3d(0, 0, 0), simToModel);
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);
137 SGWeakPtr<const HLASceneObject> _sceneObject;
140 HLASceneObject::HLASceneObject(HLASceneObjectClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate) :
141 HLAObjectInstance(objectClass),
142 _sceneObject(federate)
144 _pagedLOD = new osg::PagedLOD;
145 _pagedLOD->setRange(0, 0, 80000);
147 _transform = new _Transform(this);
148 _transform->addChild(_pagedLOD.get());
151 HLASceneObject::~HLASceneObject()
153 _removeFromSceneGraph();
157 HLASceneObject::createAttributeDataElements()
159 /// FIXME at some point we should not need that anymore
160 HLAObjectInstance::createAttributeDataElements();
162 assert(dynamic_cast<HLASceneObjectClass*>(getObjectClass().get()));
163 HLASceneObjectClass& objectClass = static_cast<HLASceneObjectClass&>(*getObjectClass());
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;
172 setAttributeDataElement(objectClass.getSceneObjectNameIndex(), _sceneObject.getDataElement());
176 HLASceneObject::discoverInstance(const simgear::RTIData& tag)
178 HLAObjectInstance::discoverInstance(tag);
183 HLASceneObject::removeInstance(const simgear::RTIData& tag)
185 _removeFromSceneGraph();
186 HLAObjectInstance::removeInstance(tag);
190 HLASceneObject::registerInstance(simgear::HLAObjectClass* objectClass)
192 HLAObjectInstance::registerInstance(objectClass);
197 HLASceneObject::deleteInstance(const simgear::RTIData& tag)
199 _removeFromSceneGraph();
200 HLAObjectInstance::deleteInstance(tag);
203 const HLASceneObject*
204 HLASceneObject::getSceneObject() const
206 return _sceneObject.getObject();
210 HLASceneObject::getSceneObject()
212 return _sceneObject.getObject();
216 HLASceneObject::setSceneObject(HLASceneObject* sceneObject)
218 _sceneObject.setObject(sceneObject);
222 HLASceneObject::getLocation(const SGTimeStamp& timeStamp) const
224 const HLASceneObject* sceneObject = getSceneObject();
226 return _getRelativeLocation(timeStamp);
227 return sceneObject->getLocation(timeStamp).getAbsoluteLocation(_getRelativeLocation(timeStamp));
230 simgear::HLADataElement*
231 HLASceneObject::getModelDataElement()
233 return new _ModelDataElement(this);
237 HLASceneObject::getNode()
239 return _transform.get();
243 HLASceneObject::_getRelativeLocation(const SGTimeStamp& timeStamp) const
245 if (!_location.valid())
246 return SGLocationd(SGVec3d::zeros(), SGQuatd::unit());
247 return _location->getLocation(timeStamp);
251 HLASceneObject::_getRelativeAngularVelocity() const
253 if (!_location.valid())
254 return SGVec3d(0, 0, 0);
255 return _location->getAngularBodyVelocity();
259 HLASceneObject::_getRelativeLinearVelocity() const
261 if (!_location.valid())
262 return SGVec3d(0, 0, 0);
263 return _location->getLinearBodyVelocity();
267 HLASceneObject::_setModelFileName(const std::string& fileName)
269 if (0 < _pagedLOD->getNumFileNames() && fileName == _pagedLOD->getFileName(0))
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());
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());
284 // Finally set the file name
285 if (unsigned numChildren = _pagedLOD->getNumChildren())
286 _pagedLOD->removeChildren(0, numChildren);
287 _pagedLOD->setFileName(0, fileName);
291 HLASceneObject::_addToSceneGraph()
293 SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
294 if (!federate.valid())
296 assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
297 HLAViewerFederate* viewerFederate = static_cast<HLAViewerFederate*>(federate.get());
299 /// Add ourselves to the dynamic scene graph
300 viewerFederate->addDynamicModel(getNode());
304 HLASceneObject::_removeFromSceneGraph()
306 /// FIXME O(#SceneObjects), pool them and reuse in create
307 unsigned i = _transform->getNumParents();
309 osg::Group* parent = _transform->getParent(i);
310 parent->removeChild(_transform.get());
314 } // namespace fgviewer