]> git.mxchange.org Git - flightgear.git/commitdiff
fgviewer: Import hla based viewer application.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Sun, 16 Dec 2012 15:43:22 +0000 (16:43 +0100)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Sun, 16 Dec 2012 15:52:28 +0000 (16:52 +0100)
66 files changed:
utils/fgviewer/CMakeLists.txt
utils/fgviewer/Drawable.cxx [new file with mode: 0644]
utils/fgviewer/Drawable.hxx [new file with mode: 0644]
utils/fgviewer/Frustum.hxx [new file with mode: 0644]
utils/fgviewer/HLACamera.cxx [new file with mode: 0644]
utils/fgviewer/HLACamera.hxx [new file with mode: 0644]
utils/fgviewer/HLACameraClass.cxx [new file with mode: 0644]
utils/fgviewer/HLACameraClass.hxx [new file with mode: 0644]
utils/fgviewer/HLACameraManipulator.cxx [new file with mode: 0644]
utils/fgviewer/HLACameraManipulator.hxx [new file with mode: 0644]
utils/fgviewer/HLADrawable.cxx [new file with mode: 0644]
utils/fgviewer/HLADrawable.hxx [new file with mode: 0644]
utils/fgviewer/HLADrawableClass.cxx [new file with mode: 0644]
utils/fgviewer/HLADrawableClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAEyeTracker.cxx [new file with mode: 0644]
utils/fgviewer/HLAEyeTracker.hxx [new file with mode: 0644]
utils/fgviewer/HLAEyeTrackerClass.cxx [new file with mode: 0644]
utils/fgviewer/HLAEyeTrackerClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAMPAircraft.cxx [new file with mode: 0644]
utils/fgviewer/HLAMPAircraft.hxx [new file with mode: 0644]
utils/fgviewer/HLAMPAircraftClass.cxx [new file with mode: 0644]
utils/fgviewer/HLAMPAircraftClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAObjectReferenceData.hxx [new file with mode: 0644]
utils/fgviewer/HLAOrthographicCamera.cxx [new file with mode: 0644]
utils/fgviewer/HLAOrthographicCamera.hxx [new file with mode: 0644]
utils/fgviewer/HLAOrthographicCameraClass.cxx [new file with mode: 0644]
utils/fgviewer/HLAOrthographicCameraClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAPerspectiveCamera.cxx [new file with mode: 0644]
utils/fgviewer/HLAPerspectiveCamera.hxx [new file with mode: 0644]
utils/fgviewer/HLAPerspectiveCameraClass.cxx [new file with mode: 0644]
utils/fgviewer/HLAPerspectiveCameraClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAPerspectiveViewer.cxx [new file with mode: 0644]
utils/fgviewer/HLAPerspectiveViewer.hxx [new file with mode: 0644]
utils/fgviewer/HLAPerspectiveViewerClass.cxx [new file with mode: 0644]
utils/fgviewer/HLAPerspectiveViewerClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAProxyDataElement.hxx [new file with mode: 0644]
utils/fgviewer/HLARenderer.cxx [new file with mode: 0644]
utils/fgviewer/HLARenderer.hxx [new file with mode: 0644]
utils/fgviewer/HLARendererClass.cxx [new file with mode: 0644]
utils/fgviewer/HLARendererClass.hxx [new file with mode: 0644]
utils/fgviewer/HLASceneObject.cxx [new file with mode: 0644]
utils/fgviewer/HLASceneObject.hxx [new file with mode: 0644]
utils/fgviewer/HLASceneObjectClass.cxx [new file with mode: 0644]
utils/fgviewer/HLASceneObjectClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAView.cxx [new file with mode: 0644]
utils/fgviewer/HLAView.hxx [new file with mode: 0644]
utils/fgviewer/HLAViewClass.cxx [new file with mode: 0644]
utils/fgviewer/HLAViewClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAViewer.cxx [new file with mode: 0644]
utils/fgviewer/HLAViewer.hxx [new file with mode: 0644]
utils/fgviewer/HLAViewerClass.cxx [new file with mode: 0644]
utils/fgviewer/HLAViewerClass.hxx [new file with mode: 0644]
utils/fgviewer/HLAViewerFederate.cxx [new file with mode: 0644]
utils/fgviewer/HLAViewerFederate.hxx [new file with mode: 0644]
utils/fgviewer/HLAWindowDrawable.cxx [new file with mode: 0644]
utils/fgviewer/HLAWindowDrawable.hxx [new file with mode: 0644]
utils/fgviewer/HLAWindowDrawableClass.cxx [new file with mode: 0644]
utils/fgviewer/HLAWindowDrawableClass.hxx [new file with mode: 0644]
utils/fgviewer/MEncoderCaptureOperation.hxx [new file with mode: 0644]
utils/fgviewer/Renderer.cxx [new file with mode: 0644]
utils/fgviewer/Renderer.hxx [new file with mode: 0644]
utils/fgviewer/SlaveCamera.cxx [new file with mode: 0644]
utils/fgviewer/SlaveCamera.hxx [new file with mode: 0644]
utils/fgviewer/Viewer.cxx [new file with mode: 0644]
utils/fgviewer/Viewer.hxx [new file with mode: 0644]
utils/fgviewer/fgviewer.cxx

index dcfc3ac622ea9e2675b279e29a537a90e56373d1..bbbdac3e4c9842dc8a0d9db8a11f0e4a217408d5 100644 (file)
@@ -1,11 +1,52 @@
+set(FGVIEWER_SOURCES
+  fgviewer.cxx
+  Drawable.cxx
+  Renderer.cxx
+  SlaveCamera.cxx
+  Viewer.cxx
+)
 
-add_executable(fgviewer fgviewer.cxx)
+if(RTI_FOUND)
+  set(FGVIEWER_RTI_SOURCES
+    HLACamera.cxx
+    HLACameraClass.cxx
+    HLACameraManipulator.cxx
+    HLADrawable.cxx
+    HLADrawableClass.cxx
+    HLAEyeTracker.cxx
+    HLAEyeTrackerClass.cxx
+    HLAMPAircraft.cxx
+    HLAMPAircraftClass.cxx
+    HLAOrthographicCamera.cxx
+    HLAOrthographicCameraClass.cxx
+    HLAPerspectiveCamera.cxx
+    HLAPerspectiveCameraClass.cxx
+    HLAPerspectiveViewer.cxx
+    HLAPerspectiveViewerClass.cxx
+    HLARenderer.cxx
+    HLARendererClass.cxx
+    HLASceneObject.cxx
+    HLASceneObjectClass.cxx
+    HLAView.cxx
+    HLAViewClass.cxx
+    HLAViewer.cxx
+    HLAViewerClass.cxx
+    HLAViewerFederate.cxx
+    HLAWindowDrawable.cxx
+    HLAWindowDrawableClass.cxx
+  )
+  set(FGVIEWER_RTI_LIBRARIES ${RTI_LIBRARIES})
+else()
+  set(FGVIEWER_RTI_LIBRARIES "")
+  set(FGVIEWER_RTI_SOURCES "")
+endif()
 
+add_executable(fgviewer ${FGVIEWER_SOURCES} ${FGVIEWER_RTI_SOURCES})
 target_link_libraries(fgviewer
+       ${FGVIEWER_RTI_LIBRARIES}
        ${SIMGEAR_LIBRARIES}
        ${OPENSCENEGRAPH_LIBRARIES}
        ${OPENGL_LIBRARIES}
         ${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
 )
-
 install(TARGETS fgviewer RUNTIME DESTINATION bin)
diff --git a/utils/fgviewer/Drawable.cxx b/utils/fgviewer/Drawable.cxx
new file mode 100644 (file)
index 0000000..8d2f0a8
--- /dev/null
@@ -0,0 +1,128 @@
+// Viewer.hxx -- alternative flightgear viewer application
+//
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "Drawable.hxx"
+
+#include "Viewer.hxx"
+
+namespace fgviewer  {
+
+class Drawable::_ResizedCallback : public osg::GraphicsContext::ResizedCallback {
+public:
+    _ResizedCallback(Drawable* drawable) :
+        _drawable(drawable)
+    { }
+    virtual ~_ResizedCallback()
+    { }
+    virtual void resizedImplementation(osg::GraphicsContext*, int x, int y, int width, int height)
+    {
+        SGSharedPtr<Drawable> drawable = _drawable.lock();
+        if (!drawable.valid())
+            return;
+        drawable->resize(x, y, width, height);
+    }
+    SGWeakPtr<Drawable> _drawable;
+};
+
+Drawable::Drawable(const std::string& name) :
+    _name(name),
+    _position(0, 0),
+    _size(600, 800),
+    _offscreen(false),
+    _fullscreen(false)
+{
+}
+
+Drawable::~Drawable()
+{
+}
+
+void
+Drawable::attachSlaveCamera(SlaveCamera* slaveCamera)
+{
+    if (!slaveCamera)
+        return;
+    _slaveCameraList.push_back(slaveCamera);
+}
+
+bool
+Drawable::resize(int x, int y, int width, int height)
+{
+    unsigned numCameras = _slaveCameraList.size();
+    if (1 < numCameras)
+        return false;
+    _graphicsContext->resizedImplementation(x, y, width, height);
+    if (numCameras < 1)
+        return true;
+    _slaveCameraList.front()->setViewport(SGVec4i(0, 0, width, height));
+    return true;
+}
+    
+bool
+Drawable::realize(Viewer& viewer)
+{
+    if (_graphicsContext.valid())
+        return false;
+    _graphicsContext = _realizeImplementation(viewer);
+    if (!_graphicsContext.valid())
+        return false;
+    _graphicsContext->setResizedCallback(new _ResizedCallback(this));
+    return true;
+}
+    
+osg::GraphicsContext*
+Drawable::_realizeImplementation(Viewer& viewer)
+{
+    osg::ref_ptr<osg::GraphicsContext::Traits> traits = _getTraits(viewer);
+    return viewer.createGraphicsContext(traits.get());
+}
+    
+osg::ref_ptr<osg::GraphicsContext::Traits>
+Drawable::_getTraits(Viewer& viewer)
+{
+    osg::GraphicsContext::ScreenIdentifier screenIdentifier;
+    screenIdentifier.setScreenIdentifier(_screenIdentifier);
+    
+    osg::ref_ptr<osg::GraphicsContext::Traits> traits;
+    traits = viewer.getTraits(screenIdentifier);
+    
+    // The window name as displayed by the window manager
+    traits->windowName = getName();
+    
+    traits->x = _position[0];
+    traits->y = _position[1];
+    if (!_fullscreen) {
+        traits->width = _size[0];
+        traits->height = _size[1];
+    }
+    
+    traits->windowDecoration = !_fullscreen;
+    if (_slaveCameraList.size() <= 1)
+        traits->supportsResize = true;
+    else
+        traits->supportsResize = false;
+    traits->pbuffer = _offscreen;
+    
+    return traits;
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/Drawable.hxx b/utils/fgviewer/Drawable.hxx
new file mode 100644 (file)
index 0000000..fc448a1
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef _fgviewer_Drawable_hxx
+#define _fgviewer_Drawable_hxx
+
+#include <string>
+#include <list>
+#include <osg/GraphicsContext>
+#include <simgear/math/SGMath.hxx>
+#include <simgear/structure/SGWeakReferenced.hxx>
+
+namespace fgviewer  {
+
+class Viewer;
+class SlaveCamera;
+
+class Drawable : public SGWeakReferenced {
+public:
+    Drawable(const std::string& name);
+    virtual ~Drawable();
+    
+    const std::string& getName() const
+    { return _name; }
+    
+    virtual bool setScreenIdentifier(const std::string& screenIdentifier)
+    {
+        if (_graphicsContext.valid())
+            return false;
+        _screenIdentifier = screenIdentifier;
+        return true;
+    }
+    const std::string& getScreenIdentifier() const
+    { return _screenIdentifier; }
+    
+    virtual bool setPosition(const SGVec2i& position)
+    { _position = position; return true; }
+    const SGVec2i& getPosition() const
+    { return _position; }
+    
+    virtual bool setSize(const SGVec2i& size)
+    { _size = size; return true; }
+    const SGVec2i& getSize() const
+    { return _size; }
+    
+    virtual bool setOffscreen(bool offscreen)
+    {
+        if (_graphicsContext.valid())
+            return false;
+        _offscreen = offscreen;
+        return true;
+    }
+    bool getOffscreen() const
+    { return _offscreen; }
+    
+    virtual bool setFullscreen(bool fullscreen)
+    { _fullscreen = fullscreen; return true; }
+    bool getFullscreen() const
+    { return _fullscreen; }
+    
+    osg::GraphicsContext* getGraphicsContext()
+    { return _graphicsContext.get(); }
+
+    void attachSlaveCamera(SlaveCamera* slaveCamera);
+    
+    virtual bool resize(int x, int y, int width, int height);
+
+    bool realize(Viewer& viewer);
+
+protected:
+    virtual osg::GraphicsContext* _realizeImplementation(Viewer& viewer);
+    osg::ref_ptr<osg::GraphicsContext::Traits> _getTraits(Viewer& viewer);
+    
+private:
+    Drawable(const Drawable&);
+    Drawable& operator=(const Drawable&);
+
+    class _ResizedCallback;
+
+    /// The immutable name that is used to reference this slave camera.
+    const std::string _name;
+    std::string _screenIdentifier;
+    SGVec2i _position;
+    SGVec2i _size;
+    bool _offscreen;
+    bool _fullscreen;
+    osg::ref_ptr<osg::GraphicsContext> _graphicsContext;
+    std::list<SGSharedPtr<SlaveCamera> > _slaveCameraList;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/Frustum.hxx b/utils/fgviewer/Frustum.hxx
new file mode 100644 (file)
index 0000000..263c64e
--- /dev/null
@@ -0,0 +1,156 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef Frustum_hxx
+#define Frustum_hxx
+
+#include <cmath>
+#include <osg/Matrix>
+#include <osg/Vec2>
+#include <osg/Vec3>
+#include <simgear/math/SGMath.hxx>
+
+namespace fgviewer  {
+
+struct Frustum {
+    Frustum(const double& aspectRatio = 1) :
+        _left(-aspectRatio),
+        _right(aspectRatio),
+        _bottom(-1),
+        _top(1),
+        _near(2)
+    { }
+    Frustum(const double& left, const double& right, const double& bottom, const double& top, const double& near) :
+        _left(left),
+        _right(right),
+        _bottom(bottom),
+        _top(top),
+        _near(near)
+    { }
+    Frustum(const Frustum& frustum) :
+        _left(frustum._left),
+        _right(frustum._right),
+        _bottom(frustum._bottom),
+        _top(frustum._top),
+        _near(frustum._near)
+    { }
+
+    bool setMatrix(const osg::Matrix& matrix)
+    {
+        double zFar;
+        return matrix.getFrustum(_left, _right, _bottom, _top, _near, zFar);
+    }
+    osg::Matrix getMatrix() const
+    {
+        return getMatrix(osg::Vec2(_near, 2*_near));
+    }
+    /// Finite projection matrix
+    osg::Matrix getMatrix(const osg::Vec2& depthRange) const
+    {
+        double near = depthRange[0];
+        double far = depthRange[1];
+        /// left, right, bottom and top are rescaled by near/_near and the result is
+        /// inserted into the final equations. This rescaling factor just cancels out mostly.
+        double a00 = 2*_near/(_right - _left);
+        double a11 = 2*_near/(_top - _bottom);
+        double a20 = (_right + _left)/(_right - _left);
+        double a21 = (_top + _bottom)/(_top - _bottom);
+        double a22 = (near + far)/(near - far);
+        double a23 = -1;
+        double a32 = 2*near*far/(near - far);
+
+        return osg::Matrix(a00,   0,   0,   0,
+                             0, a11,   0,   0,
+                           a20, a21, a22, a23,
+                             0,   0, a32,   0);
+    }
+    /// Infinite projection matrix with a given near plane
+    osg::Matrix getMatrix(const double& near, const double& eps = 0) const
+    {
+        /// left, right, bottom and top are rescaled by near/_near and the result is
+        /// inserted into the final equations. This rescaling factor just cancels out mostly.
+        double a00 = 2*_near/(_right - _left);
+        double a11 = 2*_near/(_top - _bottom);
+        double a20 = (_right + _left)/(_right - _left);
+        double a21 = (_top + _bottom)/(_top - _bottom);
+        double a22 = eps - 1;
+        double a23 = -1;
+        double a32 = near*(eps - 2);
+
+        return osg::Matrix(a00,   0,   0,   0,
+                             0, a11,   0,   0,
+                           a20, a21, a22, a23,
+                             0,   0, a32,   0);
+    }
+
+    /// Return the aspect ratio of the frustum
+    double getAspectRatio() const
+    { return (_right - _left)/(_top - _bottom); }
+    void setAspectRatio(double aspectRatio)
+    {
+        double aspectScale = aspectRatio/getAspectRatio();
+        _left *= aspectScale;
+        _right *= aspectScale;
+    }
+
+    void setFieldOfViewRad(double fieldOfViewRad)
+    {
+        double fieldOfView = tan(fieldOfViewRad);
+        double aspectRatio = getAspectRatio();
+        _left = -fieldOfView*aspectRatio*0.5*_near;
+        _right = fieldOfView*aspectRatio*0.5*_near;
+        _bottom = -fieldOfView*0.5*_near;
+        _top = fieldOfView*0.5*_near;
+    }
+    void setFieldOfViewDeg(double fieldOfViewDeg)
+    { setFieldOfViewRad(SGMiscd::deg2rad(fieldOfViewDeg)); }
+
+
+    /// Translate this frustum by the given eye point offset
+    Frustum translate(const osg::Vec3& eyeOffset) const
+    {
+        double left = _left - eyeOffset[0];
+        double right = _right - eyeOffset[0];
+        double bottom = _bottom - eyeOffset[1];
+        double top = _top - eyeOffset[1];
+        double near = _near + eyeOffset[2];
+        return Frustum(left, right, bottom, top, near);
+    }
+    /// Scale this frustum around the scale center.
+    /// Gives something similar like zooming into the view.
+    Frustum scale(double scaleFactor, const osg::Vec3& scaleCenter) const
+    {
+        Frustum frustum;
+        frustum._left = scaleFactor*(_left - scaleCenter[0]) + scaleCenter[0];
+        frustum._right = scaleFactor*(_right - scaleCenter[0]) + scaleCenter[0];
+        frustum._bottom = scaleFactor*(_bottom - scaleCenter[1]) + scaleCenter[1];
+        frustum._top = scaleFactor*(_top - scaleCenter[1]) + scaleCenter[1];
+        frustum._near = scaleFactor*(_near + scaleCenter[2]) - scaleCenter[2];
+        return frustum;
+    }
+
+    // Parameters for the reference view frustum.
+    double _left;
+    double _right;
+    double _bottom;
+    double _top;
+    // Is not the real near plane. Just used to reference the other frustum parameters.
+    double _near;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLACamera.cxx b/utils/fgviewer/HLACamera.cxx
new file mode 100644 (file)
index 0000000..f78083e
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLACamera.hxx"
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include "HLACameraClass.hxx"
+
+namespace fgviewer {
+
+HLACamera::HLACamera(HLACameraClass* objectClass) :
+    HLAObjectInstance(objectClass)
+{
+}
+
+HLACamera::~HLACamera()
+{
+}
+
+void
+HLACamera::createAttributeDataElements()
+{
+    /// FIXME at some point we should not need that anymore
+    HLAObjectInstance::createAttributeDataElements();
+
+    assert(dynamic_cast<HLACameraClass*>(getObjectClass().get()));
+    HLACameraClass& objectClass = static_cast<HLACameraClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getNameIndex(), _name.getDataElement());
+    setAttributeDataElement(objectClass.getViewerIndex(), _viewer.getDataElement());
+    setAttributeDataElement(objectClass.getDrawableIndex(), _drawable.getDataElement());
+    setAttributeDataElement(objectClass.getViewportIndex(), _viewport.getDataElement());
+    setAttributeDataElement(objectClass.getPositionIndex(), _position.getDataElement());
+    setAttributeDataElement(objectClass.getOrientationIndex(), _orientation.getDataElement());
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLACamera.hxx b/utils/fgviewer/HLACamera.hxx
new file mode 100644 (file)
index 0000000..15f4d75
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLACamera_hxx
+#define HLACamera_hxx
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLACameraClass;
+
+class HLACamera : public simgear::HLAObjectInstance {
+public:
+    HLACamera(HLACameraClass* objectClass = 0);
+    virtual ~HLACamera();
+
+    virtual void createAttributeDataElements();
+
+    const std::string& getName() const
+    { return _name.getValue(); }
+    void setName(const std::string& name)
+    { _name.setValue(name); }
+
+    const std::string& getViewer() const
+    { return _viewer.getValue(); }
+    void setViewer(const std::string& viewer)
+    { _viewer.setValue(viewer); }
+
+    const std::string& getDrawable() const
+    { return _drawable.getValue(); }
+    void setDrawable(const std::string& drawable)
+    { _drawable.setValue(drawable); }
+
+    const SGVec4i& getViewport() const
+    { return _viewport.getValue(); }
+    void setViewport(const SGVec4i& viewport)
+    { _viewport.setValue(viewport); }
+
+    const SGVec3d& getPosition() const
+    { return _position.getValue(); }
+    void setPosition(const SGVec3d& position)
+    { _position.setValue(position); }
+
+    const SGQuatd& getOrientation() const
+    { return _orientation.getValue(); }
+    void setOrientation(const SGQuatd& orientation)
+    { _orientation.setValue(orientation); }
+
+    SGLocationd getLocation() const
+    { return SGLocationd(getPosition(), getOrientation()); }
+    void setLocation(const SGLocationd& location)
+    { setPosition(location.getPosition()); setOrientation(location.getOrientation()); }
+
+private:
+    simgear::HLAStringData _name;
+    simgear::HLAStringData _viewer;
+    simgear::HLAStringData _drawable;
+    simgear::HLAVec4iData _viewport;
+    simgear::HLAVec3dData _position;
+    simgear::HLAQuat3dData _orientation;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLACameraClass.cxx b/utils/fgviewer/HLACameraClass.cxx
new file mode 100644 (file)
index 0000000..044cea9
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLACameraClass.hxx"
+
+#include "HLACamera.hxx"
+
+namespace fgviewer {
+
+HLACameraClass::HLACameraClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLAObjectClass(name, federate)
+{
+}
+
+HLACameraClass::~HLACameraClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLACameraClass::createObjectInstance(const std::string& name)
+{
+    return new HLACamera(this);
+}
+
+void
+HLACameraClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    /// FIXME resolve these indices somewhere else!
+    if (_nameIndex.empty())
+        _nameIndex = getDataElementIndex("name");
+    if (_viewerIndex.empty())
+        _viewerIndex = getDataElementIndex("viewer");
+    if (_drawableIndex.empty())
+        _drawableIndex = getDataElementIndex("drawable");
+    if (_viewportIndex.empty())
+        _viewportIndex = getDataElementIndex("viewport");
+    if (_positionIndex.empty())
+        _positionIndex = getDataElementIndex("location.position");
+    if (_orientationIndex.empty())
+        _orientationIndex = getDataElementIndex("location.orientation");
+    HLAObjectClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLACameraClass.hxx b/utils/fgviewer/HLACameraClass.hxx
new file mode 100644 (file)
index 0000000..19116f4
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLACameraClass_hxx
+#define HLACameraClass_hxx
+
+#include <string>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLACameraClass : public simgear::HLAObjectClass {
+public:
+    HLACameraClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLACameraClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setNameIndex(const std::string& path)
+    { return getDataElementIndex(_nameIndex, path); }
+    const simgear::HLADataElementIndex& getNameIndex() const
+    { return _nameIndex; }
+
+    bool setViewerIndex(const std::string& path)
+    { return getDataElementIndex(_viewerIndex, path); }
+    const simgear::HLADataElementIndex& getViewerIndex() const
+    { return _viewerIndex; }
+
+    bool setDrawableIndex(const std::string& path)
+    { return getDataElementIndex(_drawableIndex, path); }
+    const simgear::HLADataElementIndex& getDrawableIndex() const
+    { return _drawableIndex; }
+
+    bool setViewportIndex(const std::string& path)
+    { return getDataElementIndex(_viewportIndex, path); }
+    const simgear::HLADataElementIndex& getViewportIndex() const
+    { return _viewportIndex; }
+
+    bool setPositionIndex(const std::string& path)
+    { return getDataElementIndex(_positionIndex, path); }
+    const simgear::HLADataElementIndex& getPositionIndex() const
+    { return _positionIndex; }
+
+    bool setOrientationIndex(const std::string& path)
+    { return getDataElementIndex(_orientationIndex, path); }
+    const simgear::HLADataElementIndex& getOrientationIndex() const
+    { return _orientationIndex; }
+
+private:
+    simgear::HLADataElementIndex _nameIndex;
+    simgear::HLADataElementIndex _viewerIndex;
+    simgear::HLADataElementIndex _drawableIndex;
+    simgear::HLADataElementIndex _viewportIndex;
+    simgear::HLADataElementIndex _positionIndex;
+    simgear::HLADataElementIndex _orientationIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLACameraManipulator.cxx b/utils/fgviewer/HLACameraManipulator.cxx
new file mode 100644 (file)
index 0000000..2aa470b
--- /dev/null
@@ -0,0 +1,248 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLACameraManipulator.hxx"
+
+#include <simgear/scene/util/OsgMath.hxx>
+#include "HLAPerspectiveViewer.hxx"
+#include "Viewer.hxx"
+
+namespace fgviewer  {
+
+HLACameraManipulator::HLACameraManipulator(HLAPerspectiveViewer* perspectiveViewer) :
+    _viewMatrix(osg::Matrixd::identity()),
+    _inverseViewMatrix(osg::Matrixd::identity()),
+    _lastMousePos(0, 0),
+    _perspectiveViewer(perspectiveViewer)
+{
+}
+
+HLACameraManipulator::HLACameraManipulator(const HLACameraManipulator& cameraManipulator, const osg::CopyOp& copyOp) :
+    osgGA::CameraManipulator(cameraManipulator, copyOp),
+    _viewMatrix(cameraManipulator._viewMatrix),
+    _inverseViewMatrix(cameraManipulator._inverseViewMatrix),
+    _lastMousePos(cameraManipulator._lastMousePos),
+    _perspectiveViewer(cameraManipulator._perspectiveViewer)
+{
+}
+
+HLACameraManipulator::~HLACameraManipulator()
+{
+}
+
+void
+HLACameraManipulator::setByMatrix(const osg::Matrixd& matrix)
+{
+}
+
+void
+HLACameraManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
+{
+}
+
+osg::Matrixd
+HLACameraManipulator::getMatrix() const
+{
+    return _viewMatrix;
+}
+
+osg::Matrixd
+HLACameraManipulator::getInverseMatrix() const
+{
+    return _inverseViewMatrix;
+}
+
+bool
+HLACameraManipulator::handle(const osgGA::GUIEventAdapter& eventAdapter, osgGA::GUIActionAdapter& actionAdapter)
+{
+    if (_handle(eventAdapter, static_cast<Viewer&>(actionAdapter)))
+        return true;
+    return osgGA::CameraManipulator::handle(eventAdapter, actionAdapter);
+}
+
+bool
+HLACameraManipulator::_handle(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
+{
+    switch (eventAdapter.getEventType()) {
+    case osgGA::GUIEventAdapter::PUSH:
+        _lastMousePos = osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized());
+        break;
+    case osgGA::GUIEventAdapter::RELEASE:
+        break;
+    case osgGA::GUIEventAdapter::DOUBLECLICK:
+        break;
+    case osgGA::GUIEventAdapter::DRAG:
+        if (!eventAdapter.getModKeyMask())
+            _rotateView(osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized()) - _lastMousePos);
+        else if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL)
+            _rotateSun(osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized()) - _lastMousePos, viewer);
+        _lastMousePos = osg::Vec2(eventAdapter.getXnormalized(), eventAdapter.getYnormalized());
+        break;
+    case osgGA::GUIEventAdapter::MOVE:
+        break;
+    case osgGA::GUIEventAdapter::SCROLL:
+        break;
+        
+    case osgGA::GUIEventAdapter::KEYDOWN:
+        _handleKeyDownEvent(eventAdapter, viewer);
+        break;
+    case osgGA::GUIEventAdapter::KEYUP:
+        _handleKeyUpEvent(eventAdapter, viewer);
+        break;
+        
+    case osgGA::GUIEventAdapter::FRAME:
+        _handleFrameEvent(viewer);
+        break;
+        
+    default:
+        break;
+    }
+    return false;
+}
+
+void
+HLACameraManipulator::_handleFrameEvent(osgGA::GUIActionAdapter& actionAdapter)
+{
+    // Note that eventAdapter.getTime() returns the reference time instead of the simulation time
+    osg::View* view = actionAdapter.asView();
+    if (!view)
+        return;
+    osg::FrameStamp* frameStamp = view->getFrameStamp();
+    if (!frameStamp)
+        return;
+    if (!_perspectiveViewer.valid())
+        return;
+
+    SGLocationd location;
+    location = _perspectiveViewer->getLocation(SGTimeStamp::fromSec(frameStamp->getSimulationTime()));
+
+    // Update the main cameras view matrix
+    _viewMatrix = osg::Matrixd::identity();
+    // transform from the simulation typical x-forward/y-right/z-down
+    // to the opengl camera system x-right/y-up/z-back
+    // _viewMatrix.postMultRotate(toOsg(SGQuatd::fromEulerDeg(90, 0, -90)));
+    _viewMatrix.postMultRotate(toOsg(SGQuatd(-0.5, -0.5, 0.5, 0.5)));
+    // the orientation of the view
+    _viewMatrix.postMultRotate(toOsg(location.getOrientation()));
+    // the position of the view
+    _viewMatrix.postMultTranslate(toOsg(location.getPosition()));
+    _inverseViewMatrix = osg::Matrixd::inverse(_viewMatrix);
+}
+
+bool
+HLACameraManipulator::_handleKeyDownEvent(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
+{
+    if (!_perspectiveViewer.valid())
+        return false;
+
+    switch (eventAdapter.getKey()) {
+    case osgGA::GUIEventAdapter::KEY_Space:
+    case osgGA::GUIEventAdapter::KEY_Home:
+        _resetView();
+        return false;
+
+    case osgGA::GUIEventAdapter::KEY_Left:
+        _incrementEyePosition(SGVec3d(-0.1, 0, 0));
+        return false;
+    case osgGA::GUIEventAdapter::KEY_Right:
+        _incrementEyePosition(SGVec3d(0.1, 0, 0));
+        return false;
+    case osgGA::GUIEventAdapter::KEY_Up:
+        if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL) {
+            _perspectiveViewer->setZoomFactor(_perspectiveViewer->getZoomFactor()*1.1);
+        } else if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT) {
+            _incrementEyePosition(SGVec3d(0, 0, 0.1));
+        } else {
+            _incrementEyePosition(SGVec3d(0, 0.1, 0));
+        }
+        return false;
+    case osgGA::GUIEventAdapter::KEY_Down:
+        if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_CTRL) {
+            _perspectiveViewer->setZoomFactor(_perspectiveViewer->getZoomFactor()/1.1);
+        } else if (eventAdapter.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT) {
+            _incrementEyePosition(SGVec3d(0, 0, -0.1));
+        } else {
+            _incrementEyePosition(SGVec3d(0, -0.1, 0));
+        }
+        return false;
+    default:
+        return false;
+    }
+}
+
+bool
+HLACameraManipulator::_handleKeyUpEvent(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer)
+{
+    return false;
+}
+
+void
+HLACameraManipulator::_incrementEyePosition(const SGVec3d& offset)
+{
+    if (!_perspectiveViewer.valid())
+        return;
+    HLAEyeTracker* eyeTracker = _perspectiveViewer->getEyeTracker();
+    if (!eyeTracker)
+        return;
+    eyeTracker->setLeftEyeOffset(eyeTracker->getLeftEyeOffset() + offset);
+    eyeTracker->setRightEyeOffset(eyeTracker->getRightEyeOffset() + offset);
+}
+
+void
+HLACameraManipulator::_resetView()
+{
+    if (!_perspectiveViewer.valid())
+        return;
+    _perspectiveViewer->setPosition(SGVec3d::zeros());
+    _perspectiveViewer->setOrientation(SGQuatd::unit());
+    _perspectiveViewer->setZoomFactor(1);
+    HLAEyeTracker* eyeTracker = _perspectiveViewer->getEyeTracker();
+    if (!eyeTracker)
+        return;
+    eyeTracker->setLeftEyeOffset(SGVec3d::zeros());
+    eyeTracker->setRightEyeOffset(SGVec3d::zeros());
+}
+
+void
+HLACameraManipulator::_rotateView(const osg::Vec2& inc)
+{
+    if (!_perspectiveViewer.valid())
+        return;
+    double zDeg, yDeg, xDeg;
+    _perspectiveViewer->getOrientation().getEulerRad(zDeg, yDeg, xDeg);
+    zDeg += inc[0];
+    yDeg += inc[1];
+    _perspectiveViewer->setOrientation(SGQuatd::fromEulerRad(zDeg, yDeg, xDeg));
+}
+
+void
+HLACameraManipulator::_rotateSun(const osg::Vec2& inc, Viewer& viewer)
+{
+    osg::Light* light = viewer.getLight();
+    if (!light)
+        return;
+    osg::Matrix m = osg::Matrix::inverse(viewer.getCamera()->getViewMatrix());
+    osg::Vec3 position(light->getPosition()[0], light->getPosition()[1], light->getPosition()[2]) ;
+    position = osg::Quat(-0.2*inc[0], osg::Matrix::transform3x3(osg::Vec3(0, 1, 0), m))*position;
+    position = osg::Quat(0.2*inc[1], osg::Matrix::transform3x3(osg::Vec3(1, 0, 0), m))*position;
+    light->setPosition(osg::Vec4(position, 0));
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLACameraManipulator.hxx b/utils/fgviewer/HLACameraManipulator.hxx
new file mode 100644 (file)
index 0000000..96161ed
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef _HLACameraManipulator_hxx
+#define _HLACameraManipulator_hxx
+
+#include <osgGA/CameraManipulator>
+#include <simgear/scene/util/OsgMath.hxx>
+#include "HLAPerspectiveViewer.hxx"
+
+namespace fgviewer  {
+
+class Viewer;
+
+class HLACameraManipulator : public osgGA::CameraManipulator {
+public:
+    HLACameraManipulator(HLAPerspectiveViewer* perspectiveViewer = 0);
+    HLACameraManipulator(const HLACameraManipulator& cameraManipulator, const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY);
+    virtual ~HLACameraManipulator();
+
+    META_Object(fgviewer, HLACameraManipulator);
+
+    virtual void setByMatrix(const osg::Matrixd& matrix);
+    virtual void setByInverseMatrix(const osg::Matrixd& matrix);
+
+    virtual osg::Matrixd getMatrix() const;
+    virtual osg::Matrixd getInverseMatrix() const;
+
+    /** Handle events, return true if handled, false otherwise. */
+    virtual bool handle(const osgGA::GUIEventAdapter& eventAdapter, osgGA::GUIActionAdapter& actionAdapter);
+
+protected:
+    bool _handle(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer);
+    void _handleFrameEvent(osgGA::GUIActionAdapter& actionAdapter);
+    bool _handleKeyDownEvent(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer);
+    bool _handleKeyUpEvent(const osgGA::GUIEventAdapter& eventAdapter, Viewer& viewer);
+    void _incrementEyePosition(const SGVec3d& offset);
+    void _resetView();
+    void _rotateView(const osg::Vec2& inc);
+    void _rotateSun(const osg::Vec2& inc, Viewer& viewer);
+
+private:
+    osg::Matrixd _viewMatrix;
+    osg::Matrixd _inverseViewMatrix;
+    osg::Vec2 _lastMousePos;
+    SGSharedPtr<HLAPerspectiveViewer> _perspectiveViewer;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLADrawable.cxx b/utils/fgviewer/HLADrawable.cxx
new file mode 100644 (file)
index 0000000..90cf31a
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLADrawable.hxx"
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include "HLADrawableClass.hxx"
+
+namespace fgviewer {
+
+HLADrawable::HLADrawable(HLADrawableClass* objectClass) :
+    HLAObjectInstance(objectClass)
+{
+}
+
+HLADrawable::~HLADrawable()
+{
+}
+
+void
+HLADrawable::createAttributeDataElements()
+{
+    /// FIXME at some point we should not need that anymore
+    HLAObjectInstance::createAttributeDataElements();
+
+    assert(dynamic_cast<HLADrawableClass*>(getObjectClass().get()));
+    HLADrawableClass& objectClass = static_cast<HLADrawableClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getNameIndex(), _name.getDataElement());
+    setAttributeDataElement(objectClass.getRendererIndex(), _renderer.getDataElement());
+    setAttributeDataElement(objectClass.getDisplayIndex(), _display.getDataElement());
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLADrawable.hxx b/utils/fgviewer/HLADrawable.hxx
new file mode 100644 (file)
index 0000000..430764f
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLADrawable_hxx
+#define HLADrawable_hxx
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLADrawableClass;
+
+class HLADrawable : public simgear::HLAObjectInstance {
+public:
+    HLADrawable(HLADrawableClass* objectClass = 0);
+    virtual ~HLADrawable();
+
+    virtual void createAttributeDataElements();
+
+    const std::string& getName() const
+    { return _name.getValue(); }
+    void setName(const std::string& name)
+    { _name.setValue(name); }
+
+    const std::string& getRenderer() const
+    { return _renderer.getValue(); }
+    void setRenderer(const std::string& renderer)
+    { _renderer.setValue(renderer); }
+
+    const std::string& getDisplay() const
+    { return _display.getValue(); }
+    void setDisplay(const std::string& display)
+    { _display.setValue(display); }
+
+private:
+    simgear::HLAStringData _name;
+    // This is normally this object reference, but here it should be sufficient to work with the name
+    // simgear::HLAObjectReferenceData<HLARenderer> _renderer;
+    simgear::HLAStringData _renderer;
+    simgear::HLAStringData _display;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLADrawableClass.cxx b/utils/fgviewer/HLADrawableClass.cxx
new file mode 100644 (file)
index 0000000..8851bb1
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLADrawableClass.hxx"
+
+#include "HLADrawable.hxx"
+
+namespace fgviewer {
+
+HLADrawableClass::HLADrawableClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLAObjectClass(name, federate)
+{
+}
+
+HLADrawableClass::~HLADrawableClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLADrawableClass::createObjectInstance(const std::string& name)
+{
+    return new HLADrawable(this);
+}
+
+void
+HLADrawableClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    /// FIXME resolve these indices somewhere else!
+    if (_nameIndex.empty())
+        _nameIndex = getDataElementIndex("name");
+    if (_rendererIndex.empty())
+        _rendererIndex = getDataElementIndex("renderer");
+    if (_displayIndex.empty())
+        _displayIndex = getDataElementIndex("display");
+    HLAObjectClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLADrawableClass.hxx b/utils/fgviewer/HLADrawableClass.hxx
new file mode 100644 (file)
index 0000000..8727a19
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLADrawableClass_hxx
+#define HLADrawableClass_hxx
+
+#include <string>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLADrawableClass : public simgear::HLAObjectClass {
+public:
+    HLADrawableClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLADrawableClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setNameIndex(const std::string& path)
+    { return getDataElementIndex(_nameIndex, path); }
+    const simgear::HLADataElementIndex& getNameIndex() const
+    { return _nameIndex; }
+
+    bool setRendererIndex(const std::string& path)
+    { return getDataElementIndex(_rendererIndex, path); }
+    const simgear::HLADataElementIndex& getRendererIndex() const
+    { return _rendererIndex; }
+
+    bool setDisplayIndex(const std::string& path)
+    { return getDataElementIndex(_displayIndex, path); }
+    const simgear::HLADataElementIndex& getDisplayIndex() const
+    { return _displayIndex; }
+
+private:
+    simgear::HLADataElementIndex _nameIndex;
+    simgear::HLADataElementIndex _rendererIndex;
+    simgear::HLADataElementIndex _displayIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAEyeTracker.cxx b/utils/fgviewer/HLAEyeTracker.cxx
new file mode 100644 (file)
index 0000000..5b2bc1d
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAEyeTracker.hxx"
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include "HLAEyeTrackerClass.hxx"
+
+namespace fgviewer {
+
+HLAEyeTracker::HLAEyeTracker(HLAEyeTrackerClass* objectClass) :
+    HLAObjectInstance(objectClass)
+{
+}
+
+HLAEyeTracker::~HLAEyeTracker()
+{
+}
+
+void
+HLAEyeTracker::createAttributeDataElements()
+{
+    /// FIXME at some point we should not need that anymore
+    HLAObjectInstance::createAttributeDataElements();
+
+    assert(dynamic_cast<HLAEyeTrackerClass*>(getObjectClass().get()));
+    HLAEyeTrackerClass& objectClass = static_cast<HLAEyeTrackerClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getLeftEyeOffsetIndex(), _leftEyeOffset.getDataElement());
+    setAttributeDataElement(objectClass.getRightEyeOffsetIndex(), _rightEyeOffset.getDataElement());
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAEyeTracker.hxx b/utils/fgviewer/HLAEyeTracker.hxx
new file mode 100644 (file)
index 0000000..9cca5cd
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAEyeTracker_hxx
+#define HLAEyeTracker_hxx
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLAEyeTrackerClass;
+
+class HLAEyeTracker : public simgear::HLAObjectInstance {
+public:
+    HLAEyeTracker(HLAEyeTrackerClass* objectClass = 0);
+    virtual ~HLAEyeTracker();
+
+    virtual void createAttributeDataElements();
+
+    const SGVec3d& getLeftEyeOffset() const
+    { return _leftEyeOffset.getValue(); }
+    void setLeftEyeOffset(const SGVec3d& leftEyeOffset)
+    { _leftEyeOffset.setValue(leftEyeOffset); }
+
+    const SGVec3d& getRightEyeOffset() const
+    { return _rightEyeOffset.getValue(); }
+    void setRightEyeOffset(const SGVec3d& rightEyeOffset)
+    { _rightEyeOffset.setValue(rightEyeOffset); }
+
+private:
+    simgear::HLAVec3dData _leftEyeOffset;
+    simgear::HLAVec3dData _rightEyeOffset;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAEyeTrackerClass.cxx b/utils/fgviewer/HLAEyeTrackerClass.cxx
new file mode 100644 (file)
index 0000000..23e27a9
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAEyeTrackerClass.hxx"
+
+#include "HLAEyeTracker.hxx"
+
+namespace fgviewer {
+
+HLAEyeTrackerClass::HLAEyeTrackerClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLAObjectClass(name, federate)
+{
+}
+
+HLAEyeTrackerClass::~HLAEyeTrackerClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLAEyeTrackerClass::createObjectInstance(const std::string& name)
+{
+    return new HLAEyeTracker(this);
+}
+
+void
+HLAEyeTrackerClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    /// FIXME resolve these indices somewhere else!
+    if (_leftEyeOffsetIndex.empty())
+        _leftEyeOffsetIndex = getDataElementIndex("leftEyeOffset");
+    if (_rightEyeOffsetIndex.empty())
+        _rightEyeOffsetIndex = getDataElementIndex("rightEyeOffset");
+    HLAObjectClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAEyeTrackerClass.hxx b/utils/fgviewer/HLAEyeTrackerClass.hxx
new file mode 100644 (file)
index 0000000..5851e17
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAEyeTrackerClass_hxx
+#define HLAEyeTrackerClass_hxx
+
+#include <string>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLAEyeTrackerClass : public simgear::HLAObjectClass {
+public:
+    HLAEyeTrackerClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLAEyeTrackerClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setLeftEyeOffsetIndex(const std::string& path)
+    { return getDataElementIndex(_leftEyeOffsetIndex, path); }
+    const simgear::HLADataElementIndex& getLeftEyeOffsetIndex() const
+    { return _leftEyeOffsetIndex; }
+
+    bool setRightEyeOffsetIndex(const std::string& path)
+    { return getDataElementIndex(_rightEyeOffsetIndex, path); }
+    const simgear::HLADataElementIndex& getRightEyeOffsetIndex() const
+    { return _rightEyeOffsetIndex; }
+
+private:
+    simgear::HLADataElementIndex _leftEyeOffsetIndex;
+    simgear::HLADataElementIndex _rightEyeOffsetIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAMPAircraft.cxx b/utils/fgviewer/HLAMPAircraft.cxx
new file mode 100644 (file)
index 0000000..51602b2
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAMPAircraft.hxx"
+
+#include "HLAMPAircraftClass.hxx"
+
+namespace fgviewer {
+
+HLAMPAircraft::HLAMPAircraft(HLASceneObjectClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate) :
+    HLASceneObject(objectClass, federate),
+    _simTimeOffset(SGLimitsd::max())
+{
+}
+
+HLAMPAircraft::~HLAMPAircraft()
+{
+}
+
+void
+HLAMPAircraft::reflectAttributeValues(const simgear::HLAIndexList& indexList, const simgear::RTIData& tag)
+{
+    HLASceneObject::reflectAttributeValues(indexList, tag);
+}
+
+void
+HLAMPAircraft::reflectAttributeValues(const simgear::HLAIndexList& indexList, const SGTimeStamp& timeStamp, const simgear::RTIData& tag)
+{
+    HLASceneObject::reflectAttributeValues(indexList, timeStamp, tag);
+}
+
+void
+HLAMPAircraft::createAttributeDataElements()
+{
+    /// FIXME at some point we should not need that anymore
+    HLASceneObject::createAttributeDataElements();
+
+    assert(dynamic_cast<HLAMPAircraftClass*>(getObjectClass().get()));
+    HLAMPAircraftClass& objectClass = static_cast<HLAMPAircraftClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getSimTimeIndex(), _simTime.getDataElement());
+    setAttributeDataElement(objectClass.getModelPathIndex(), getModelDataElement());
+}
+
+SGLocationd
+HLAMPAircraft::getLocation(const SGTimeStamp& timeStamp) const
+{
+    // FIXME: puh, is frame rate dependent. Think about something more robust ...
+    if (_lastTimeStamp != timeStamp) {
+        double simTimeOffset = timeStamp.toSecs() - _simTime.getValue();
+        if (2 < fabs(simTimeOffset - _simTimeOffset))
+            _simTimeOffset = simTimeOffset;
+        else
+            _simTimeOffset = 0.999*_simTimeOffset + 0.001*simTimeOffset;
+        _lastTimeStamp = timeStamp;
+    }
+    double dt = timeStamp.toSecs() - _simTime.getValue() - _simTimeOffset;
+    
+    SGLocationd location = HLASceneObject::getLocation(timeStamp);
+    location.eulerStepBodyVelocitiesMidOrientation(dt, _getRelativeLinearVelocity(), _getRelativeAngularVelocity());
+    return location;
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAMPAircraft.hxx b/utils/fgviewer/HLAMPAircraft.hxx
new file mode 100644 (file)
index 0000000..480470f
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAMPAircraft_hxx
+#define HLAMPAircraft_hxx
+
+#include "HLASceneObject.hxx"
+
+namespace fgviewer {
+
+class HLAMPAircraft : public HLASceneObject {
+public:
+    HLAMPAircraft(HLASceneObjectClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate);
+    virtual ~HLAMPAircraft();
+
+    virtual void reflectAttributeValues(const simgear::HLAIndexList& indexList, const simgear::RTIData& tag);
+    virtual void reflectAttributeValues(const simgear::HLAIndexList& indexList, const SGTimeStamp& timeStamp, const simgear::RTIData& tag);
+
+    virtual void createAttributeDataElements();
+
+    virtual SGLocationd getLocation(const SGTimeStamp& timeStamp) const;
+
+private:
+    mutable SGTimeStamp _lastTimeStamp;
+    mutable double _simTimeOffset;
+    simgear::HLADoubleData _simTime;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAMPAircraftClass.cxx b/utils/fgviewer/HLAMPAircraftClass.cxx
new file mode 100644 (file)
index 0000000..df528ed
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAMPAircraftClass.hxx"
+
+#include "HLAMPAircraft.hxx"
+#include "HLAViewerFederate.hxx"
+
+namespace fgviewer {
+
+HLAMPAircraftClass::HLAMPAircraftClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLASceneObjectClass(name, federate)
+{
+}
+
+HLAMPAircraftClass::~HLAMPAircraftClass()
+{
+}
+
+HLAMPAircraft*
+HLAMPAircraftClass::createObjectInstance(const std::string& name)
+{
+    return new HLAMPAircraft(this, getFederate());
+}
+
+void
+HLAMPAircraftClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    /// FIXME resolve these indices somewhere else!
+    if (_simTimeIndex.empty())
+        _simTimeIndex = getDataElementIndex("simTime");
+    if (_modelPathIndex.empty())
+        _modelPathIndex = getDataElementIndex("model.path");
+    HLASceneObjectClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAMPAircraftClass.hxx b/utils/fgviewer/HLAMPAircraftClass.hxx
new file mode 100644 (file)
index 0000000..d6b102c
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAMPAircraftClass_hxx
+#define HLAMPAircraftClass_hxx
+
+#include "HLASceneObjectClass.hxx"
+#include "HLAMPAircraft.hxx"
+
+namespace fgviewer {
+
+class HLAMPAircraftClass : public HLASceneObjectClass {
+public:
+    HLAMPAircraftClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLAMPAircraftClass();
+
+    virtual HLAMPAircraft* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setSimTimeIndex(const std::string& path)
+    { return getDataElementIndex(_simTimeIndex, path); }
+    const simgear::HLADataElementIndex& getSimTimeIndex() const
+    { return _simTimeIndex; }
+
+    bool setModelPathIndex(const std::string& path)
+    { return getDataElementIndex(_modelPathIndex, path); }
+    const simgear::HLADataElementIndex& getModelPathIndex() const
+    { return _modelPathIndex; }
+
+private:
+    simgear::HLADataElementIndex _simTimeIndex;
+    simgear::HLADataElementIndex _modelPathIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAObjectReferenceData.hxx b/utils/fgviewer/HLAObjectReferenceData.hxx
new file mode 100644 (file)
index 0000000..2b8d943
--- /dev/null
@@ -0,0 +1,176 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef HLAObjectReferenceData_hxx
+#define HLAObjectReferenceData_hxx
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/hla/HLADataElement.hxx>
+#include <simgear/hla/HLAFederate.hxx>
+
+#include "HLAProxyDataElement.hxx"
+
+namespace simgear {
+
+/// Data element that references an other object instance by its name, or object instance handle?
+/// Abstract variant that is object type independent and could be registered at the federate
+/// if the object is not found immediately and might arrive later.
+class HLAAbstractObjectReferenceDataElement : public HLAProxyDataElement {
+public:
+    // FIXME drop the federate once we have a decode/encode visitor?!
+    HLAAbstractObjectReferenceDataElement(const SGWeakPtr<HLAFederate>& federate) :
+        _federate(federate)
+    { }
+
+    virtual bool decode(HLADecodeStream& stream)
+    {
+        if (!HLAProxyDataElement::decode(stream))
+            return false;
+
+        // No change?
+        if (!_name.getDataElement()->getDirty())
+            return true;
+        _name.getDataElement()->setDirty(false);
+
+        return recheckObject();
+    }
+
+    /// Returns true if the object is correctly set
+    bool getComplete() const
+    {
+        if (HLAObjectInstance* objectInstance = _getObjectInstance()) {
+            return _name.getValue() == objectInstance->getName();
+        } else {
+            return _name.getValue().empty();
+        }
+    }
+
+    bool recheckObject()
+    {
+        HLAObjectInstance* objectInstance = _getObjectInstance();
+        if (objectInstance && _name.getValue() == objectInstance->getName())
+            return true;
+
+        if (_name.getValue().empty()) {
+            return _setObjectInstance(0);
+        } else {
+            // Get the object by its name from the federate
+            SGSharedPtr<HLAFederate> federate = _federate.lock();
+            if (!federate.valid())
+                return false;
+            SGSharedPtr<HLAObjectInstance> objectInstance;
+            objectInstance = federate->getObjectInstance(_name.getValue());
+            return _setObjectInstance(objectInstance.get());
+        }
+    }
+
+protected:
+    virtual HLAStringDataElement* _getDataElement()
+    { return _name.getDataElement(); }
+    virtual const HLAStringDataElement* _getDataElement() const
+    { return _name.getDataElement(); }
+
+    virtual HLAObjectInstance* _getObjectInstance() const = 0;
+    virtual bool _setObjectInstance(HLAObjectInstance*) = 0;
+
+    void _setName(const HLAObjectInstance* objectInstance)
+    {
+        if (objectInstance)
+            _name.setValue(objectInstance->getName());
+        else
+            _name.setValue(std::string());
+        _name.getDataElement()->setDirty(true);
+    }
+
+private:
+    HLAStringData _name;
+    SGWeakPtr<HLAFederate> _federate;
+};
+
+
+template<typename T>
+class HLAObjectReferenceDataElement : public HLAAbstractObjectReferenceDataElement {
+public:
+    // FIXME drop the federate once we have a decode/encode visitor?!
+    HLAObjectReferenceDataElement(const SGWeakPtr<HLAFederate>& federate) :
+        HLAAbstractObjectReferenceDataElement(federate)
+    { }
+
+    const SGSharedPtr<T>& getObject() const
+    { return _object; }
+    void setObject(const SGSharedPtr<T>& object)
+    {
+        if (_object == object)
+            return;
+        _setName(object.get());
+        _object = object;
+    }
+
+protected:
+    virtual HLAObjectInstance* _getObjectInstance() const
+    {
+        return _object.get();
+    }
+    virtual bool _setObjectInstance(HLAObjectInstance* objectInstance)
+    {
+        if (!objectInstance) {
+            _object.clear();
+            return true;
+        } else {
+            if (!dynamic_cast<T*>(objectInstance))
+                return false;
+            _object = static_cast<T*>(objectInstance);
+            return true;
+        }
+    }
+
+private:
+    SGSharedPtr<T> _object;
+};
+
+template<typename T>
+class HLAObjectReferenceData {
+public:
+    typedef HLAObjectReferenceDataElement<T> DataElement;
+
+    HLAObjectReferenceData(const SGWeakPtr<HLAFederate>& federate) :
+        _dataElement(new DataElement(federate))
+    { }
+
+    const HLADataElement* getDataElement() const
+    { return _dataElement.get(); }
+    HLADataElement* getDataElement()
+    { return _dataElement.get(); }
+
+    const SGSharedPtr<T>& getObject() const
+    { return _dataElement->getObject(); }
+    void setObject(const SGSharedPtr<T>& object)
+    { _dataElement->setObject(object); }
+
+    bool getComplete() const
+    { return _dataElement->getComplete(); }
+    /// FIXME this must happen in the federate by registering object references
+    /// that still want to be resolved
+    bool recheckObject() const
+    { return _dataElement->recheckObject(); }
+
+private:
+    SGSharedPtr<DataElement> _dataElement;
+};
+
+}
+
+#endif
diff --git a/utils/fgviewer/HLAOrthographicCamera.cxx b/utils/fgviewer/HLAOrthographicCamera.cxx
new file mode 100644 (file)
index 0000000..efea547
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAOrthographicCamera.hxx"
+
+#include "HLAOrthographicCameraClass.hxx"
+
+namespace fgviewer {
+
+HLAOrthographicCamera::HLAOrthographicCamera(HLAOrthographicCameraClass* objectClass) :
+    HLACamera(objectClass)
+{
+}
+
+HLAOrthographicCamera::~HLAOrthographicCamera()
+{
+}
+
+void
+HLAOrthographicCamera::createAttributeDataElements()
+{
+    HLACamera::createAttributeDataElements();
+
+    assert(dynamic_cast<HLAOrthographicCameraClass*>(getObjectClass().get()));
+    HLAOrthographicCameraClass& objectClass = static_cast<HLAOrthographicCameraClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getLeftIndex(), _left.getDataElement());
+    setAttributeDataElement(objectClass.getRightIndex(), _right.getDataElement());
+    setAttributeDataElement(objectClass.getBottomIndex(), _bottom.getDataElement());
+    setAttributeDataElement(objectClass.getTopIndex(), _top.getDataElement());
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAOrthographicCamera.hxx b/utils/fgviewer/HLAOrthographicCamera.hxx
new file mode 100644 (file)
index 0000000..1b403d3
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAOrthographicCamera_hxx
+#define HLAOrthographicCamera_hxx
+
+#include <simgear/hla/HLABasicDataElement.hxx>
+#include "HLACamera.hxx"
+
+namespace fgviewer {
+
+class HLAOrthographicCameraClass;
+
+class HLAOrthographicCamera : public HLACamera {
+public:
+    HLAOrthographicCamera(HLAOrthographicCameraClass* objectClass);
+    virtual ~HLAOrthographicCamera();
+
+    virtual void createAttributeDataElements();
+
+    double getLeft() const
+    { return _left.getValue(); }
+    void setLeft(double left)
+    { _left.setValue(left); }
+
+    double getRight() const
+    { return _right.getValue(); }
+    void setRight(double right)
+    { _right.setValue(right); }
+
+    double getBottom() const
+    { return _bottom.getValue(); }
+    void setBottom(double bottom)
+    { _bottom.setValue(bottom); }
+
+    double getTop() const
+    { return _top.getValue(); }
+    void setTop(double top)
+    { _top.setValue(top); }
+
+private:
+    simgear::HLADoubleData _left;
+    simgear::HLADoubleData _right;
+    simgear::HLADoubleData _bottom;
+    simgear::HLADoubleData _top;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAOrthographicCameraClass.cxx b/utils/fgviewer/HLAOrthographicCameraClass.cxx
new file mode 100644 (file)
index 0000000..3f2c8be
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAOrthographicCameraClass.hxx"
+
+#include "HLAOrthographicCamera.hxx"
+
+namespace fgviewer {
+
+HLAOrthographicCameraClass::HLAOrthographicCameraClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLACameraClass(name, federate)
+{
+}
+
+HLAOrthographicCameraClass::~HLAOrthographicCameraClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLAOrthographicCameraClass::createObjectInstance(const std::string& name)
+{
+    return new HLAOrthographicCamera(this);
+}
+
+void
+HLAOrthographicCameraClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    if (_leftIndex.empty())
+        _leftIndex = getDataElementIndex("projection.left");
+    if (_rightIndex.empty())
+        _rightIndex = getDataElementIndex("projection.right");
+    if (_bottomIndex.empty())
+        _bottomIndex = getDataElementIndex("projection.bottom");
+    if (_topIndex.empty())
+        _topIndex = getDataElementIndex("projection.top");
+    HLACameraClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAOrthographicCameraClass.hxx b/utils/fgviewer/HLAOrthographicCameraClass.hxx
new file mode 100644 (file)
index 0000000..1d68e44
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAOrthographicCameraClass_hxx
+#define HLAOrthographicCameraClass_hxx
+
+#include "HLACameraClass.hxx"
+
+namespace fgviewer {
+
+class HLAOrthographicCameraClass : public HLACameraClass {
+public:
+    HLAOrthographicCameraClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLAOrthographicCameraClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setLeftIndex(const std::string& path)
+    { return getDataElementIndex(_leftIndex, path); }
+    const simgear::HLADataElementIndex& getLeftIndex() const
+    { return _leftIndex; }
+
+    bool setRightIndex(const std::string& path)
+    { return getDataElementIndex(_rightIndex, path); }
+    const simgear::HLADataElementIndex& getRightIndex() const
+    { return _rightIndex; }
+
+    bool setBottomIndex(const std::string& path)
+    { return getDataElementIndex(_bottomIndex, path); }
+    const simgear::HLADataElementIndex& getBottomIndex() const
+    { return _bottomIndex; }
+
+    bool setTopIndex(const std::string& path)
+    { return getDataElementIndex(_topIndex, path); }
+    const simgear::HLADataElementIndex& getTopIndex() const
+    { return _topIndex; }
+
+private:
+    simgear::HLADataElementIndex _leftIndex;
+    simgear::HLADataElementIndex _rightIndex;
+    simgear::HLADataElementIndex _bottomIndex;
+    simgear::HLADataElementIndex _topIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAPerspectiveCamera.cxx b/utils/fgviewer/HLAPerspectiveCamera.cxx
new file mode 100644 (file)
index 0000000..2d80ba9
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAPerspectiveCamera.hxx"
+
+#include "HLAPerspectiveCameraClass.hxx"
+
+namespace fgviewer {
+
+HLAPerspectiveCamera::HLAPerspectiveCamera(HLAPerspectiveCameraClass* objectClass) :
+    HLACamera(objectClass)
+{
+}
+
+HLAPerspectiveCamera::~HLAPerspectiveCamera()
+{
+}
+
+void
+HLAPerspectiveCamera::reflectAttributeValues(const simgear::HLAIndexList& indexList, const simgear::RTIData& tag)
+{
+    HLACamera::reflectAttributeValues(indexList, tag);
+    /// Here push data to the osg viewer side
+}
+
+void
+HLAPerspectiveCamera::reflectAttributeValues(const simgear::HLAIndexList& indexList, const SGTimeStamp& timeStamp, const simgear::RTIData& tag)
+{
+    HLACamera::reflectAttributeValues(indexList, timeStamp, tag);
+    /// Here push data to the osg viewer side
+}
+
+void
+HLAPerspectiveCamera::createAttributeDataElements()
+{
+    HLACamera::createAttributeDataElements();
+
+    assert(dynamic_cast<HLAPerspectiveCameraClass*>(getObjectClass().get()));
+    HLAPerspectiveCameraClass& objectClass = static_cast<HLAPerspectiveCameraClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getLeftIndex(), _left.getDataElement());
+    setAttributeDataElement(objectClass.getRightIndex(), _right.getDataElement());
+    setAttributeDataElement(objectClass.getBottomIndex(), _bottom.getDataElement());
+    setAttributeDataElement(objectClass.getTopIndex(), _top.getDataElement());
+    setAttributeDataElement(objectClass.getDistanceIndex(), _distance.getDataElement());
+}
+
+Frustum
+HLAPerspectiveCamera::getFrustum() const
+{
+    return Frustum(getLeft(), getRight(), getBottom(), getTop(), getDistance());
+}
+
+void
+HLAPerspectiveCamera::setFrustum(const Frustum& frustum)
+{
+    setLeft(frustum._left);
+    setRight(frustum._right);
+    setBottom(frustum._bottom);
+    setTop(frustum._top);
+    setDistance(frustum._near);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAPerspectiveCamera.hxx b/utils/fgviewer/HLAPerspectiveCamera.hxx
new file mode 100644 (file)
index 0000000..2af9c0f
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAPerspectiveCamera_hxx
+#define HLAPerspectiveCamera_hxx
+
+#include <simgear/hla/HLABasicDataElement.hxx>
+#include "Frustum.hxx"
+#include "HLACamera.hxx"
+
+namespace fgviewer {
+
+class HLAPerspectiveCameraClass;
+
+class HLAPerspectiveCamera : public HLACamera {
+public:
+    HLAPerspectiveCamera(HLAPerspectiveCameraClass* objectClass);
+    virtual ~HLAPerspectiveCamera();
+
+    virtual void reflectAttributeValues(const simgear::HLAIndexList& indexList, const simgear::RTIData& tag);
+    virtual void reflectAttributeValues(const simgear::HLAIndexList& indexList, const SGTimeStamp& timeStamp, const simgear::RTIData& tag);
+
+    virtual void createAttributeDataElements();
+
+    double getLeft() const
+    { return _left.getValue(); }
+    void setLeft(double left)
+    { _left.setValue(left); }
+
+    double getRight() const
+    { return _right.getValue(); }
+    void setRight(double right)
+    { _right.setValue(right); }
+
+    double getBottom() const
+    { return _bottom.getValue(); }
+    void setBottom(double bottom)
+    { _bottom.setValue(bottom); }
+
+    double getTop() const
+    { return _top.getValue(); }
+    void setTop(double top)
+    { _top.setValue(top); }
+
+    double getDistance() const
+    { return _distance.getValue(); }
+    void setDistance(double distance)
+    { _distance.setValue(distance); }
+
+    Frustum getFrustum() const;
+    void setFrustum(const Frustum& frustum);
+
+private:
+    simgear::HLADoubleData _left;
+    simgear::HLADoubleData _right;
+    simgear::HLADoubleData _bottom;
+    simgear::HLADoubleData _top;
+    simgear::HLADoubleData _distance;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAPerspectiveCameraClass.cxx b/utils/fgviewer/HLAPerspectiveCameraClass.cxx
new file mode 100644 (file)
index 0000000..363a0d6
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAPerspectiveCameraClass.hxx"
+
+#include "HLAPerspectiveCamera.hxx"
+
+namespace fgviewer {
+
+HLAPerspectiveCameraClass::HLAPerspectiveCameraClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLACameraClass(name, federate)
+{
+}
+
+HLAPerspectiveCameraClass::~HLAPerspectiveCameraClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLAPerspectiveCameraClass::createObjectInstance(const std::string& name)
+{
+    return new HLAPerspectiveCamera(this);
+}
+
+void
+HLAPerspectiveCameraClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    if (_leftIndex.empty())
+        _leftIndex = getDataElementIndex("projection.left");
+    if (_rightIndex.empty())
+        _rightIndex = getDataElementIndex("projection.right");
+    if (_bottomIndex.empty())
+        _bottomIndex = getDataElementIndex("projection.bottom");
+    if (_topIndex.empty())
+        _topIndex = getDataElementIndex("projection.top");
+    if (_distanceIndex.empty())
+        _distanceIndex = getDataElementIndex("projection.distance");
+    HLACameraClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAPerspectiveCameraClass.hxx b/utils/fgviewer/HLAPerspectiveCameraClass.hxx
new file mode 100644 (file)
index 0000000..cc6f9bf
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAPerspectiveCameraClass_hxx
+#define HLAPerspectiveCameraClass_hxx
+
+#include "HLACameraClass.hxx"
+
+namespace fgviewer {
+
+class HLAPerspectiveCameraClass : public HLACameraClass {
+public:
+    HLAPerspectiveCameraClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLAPerspectiveCameraClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setLeftIndex(const std::string& path)
+    { return getDataElementIndex(_leftIndex, path); }
+    const simgear::HLADataElementIndex& getLeftIndex() const
+    { return _leftIndex; }
+
+    bool setRightIndex(const std::string& path)
+    { return getDataElementIndex(_rightIndex, path); }
+    const simgear::HLADataElementIndex& getRightIndex() const
+    { return _rightIndex; }
+
+    bool setBottomIndex(const std::string& path)
+    { return getDataElementIndex(_bottomIndex, path); }
+    const simgear::HLADataElementIndex& getBottomIndex() const
+    { return _bottomIndex; }
+
+    bool setTopIndex(const std::string& path)
+    { return getDataElementIndex(_topIndex, path); }
+    const simgear::HLADataElementIndex& getTopIndex() const
+    { return _topIndex; }
+
+    bool setDistanceIndex(const std::string& path)
+    { return getDataElementIndex(_distanceIndex, path); }
+    const simgear::HLADataElementIndex& getDistanceIndex() const
+    { return _distanceIndex; }
+
+private:
+    simgear::HLADataElementIndex _leftIndex;
+    simgear::HLADataElementIndex _rightIndex;
+    simgear::HLADataElementIndex _bottomIndex;
+    simgear::HLADataElementIndex _topIndex;
+    simgear::HLADataElementIndex _distanceIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAPerspectiveViewer.cxx b/utils/fgviewer/HLAPerspectiveViewer.cxx
new file mode 100644 (file)
index 0000000..37c0878
--- /dev/null
@@ -0,0 +1,118 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAPerspectiveViewer.hxx"
+
+#include "HLAPerspectiveViewerClass.hxx"
+
+namespace fgviewer {
+
+HLAPerspectiveViewer::HLAPerspectiveViewer(HLAPerspectiveViewerClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate) :
+    HLAViewer(objectClass),
+    _view(federate),
+    _zoomFactor(1),
+    _eyeTracker(federate)
+{
+}
+
+HLAPerspectiveViewer::~HLAPerspectiveViewer()
+{
+}
+
+void
+HLAPerspectiveViewer::createAttributeDataElements()
+{
+    HLAViewer::createAttributeDataElements();
+
+    assert(dynamic_cast<HLAPerspectiveViewerClass*>(getObjectClass().get()));
+    HLAPerspectiveViewerClass& objectClass = static_cast<HLAPerspectiveViewerClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getViewNameIndex(), _view.getDataElement());
+    setAttributeDataElement(objectClass.getPositionIndex(), _position.getDataElement());
+    setAttributeDataElement(objectClass.getOrientationIndex(), _orientation.getDataElement());
+    setAttributeDataElement(objectClass.getZoomFactorIndex(), _zoomFactor.getDataElement());
+    setAttributeDataElement(objectClass.getEyeTrackerNameIndex(), _eyeTracker.getDataElement());
+}
+
+const HLAView*
+HLAPerspectiveViewer::getView() const
+{
+    return _view.getObject();
+}
+
+HLAView*
+HLAPerspectiveViewer::getView()
+{
+    return _view.getObject();
+}
+
+void
+HLAPerspectiveViewer::setView(HLAView* view)
+{
+    _view.setObject(view);
+}
+
+const HLAEyeTracker*
+HLAPerspectiveViewer::getEyeTracker() const
+{
+    return _eyeTracker.getObject();
+}
+
+HLAEyeTracker*
+HLAPerspectiveViewer::getEyeTracker()
+{
+    return _eyeTracker.getObject();
+}
+
+void
+HLAPerspectiveViewer::setEyeTracker(HLAEyeTracker* eyeTracker)
+{
+    _eyeTracker.setObject(eyeTracker);
+}
+
+SGLocationd
+HLAPerspectiveViewer::getLocation(const SGTimeStamp& simTime) const
+{
+    const HLAView* view = getView();
+    if (!view)
+        return SGLocationd(getPosition(), getOrientation());
+    return view->getLocation(simTime).getAbsoluteLocation(SGLocationd(getPosition(), getOrientation()));
+}
+
+SGVec3d
+HLAPerspectiveViewer::getLeftEyeOffset() const
+{
+    const HLAEyeTracker* eyeTracker = getEyeTracker();
+    if (!eyeTracker)
+        return SGVec3d(0, 0, 0);
+    return eyeTracker->getLeftEyeOffset();
+}
+
+SGVec3d
+HLAPerspectiveViewer::getRightEyeOffset() const
+{
+    const HLAEyeTracker* eyeTracker = getEyeTracker();
+    if (!eyeTracker)
+        return SGVec3d(0, 0, 0);
+    return eyeTracker->getRightEyeOffset();
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAPerspectiveViewer.hxx b/utils/fgviewer/HLAPerspectiveViewer.hxx
new file mode 100644 (file)
index 0000000..0094e4e
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAPerspectiveViewer_hxx
+#define HLAPerspectiveViewer_hxx
+
+#include "HLAEyeTracker.hxx"
+#include "HLAObjectReferenceData.hxx"
+#include "HLAView.hxx"
+#include "HLAViewer.hxx"
+
+namespace fgviewer {
+
+class HLAPerspectiveViewerClass;
+
+class HLAPerspectiveViewer : public HLAViewer {
+public:
+    HLAPerspectiveViewer(HLAPerspectiveViewerClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate);
+    virtual ~HLAPerspectiveViewer();
+
+    virtual void createAttributeDataElements();
+
+    const HLAView* getView() const;
+    HLAView* getView();
+    void setView(HLAView* view);
+
+    const SGVec3d& getPosition() const
+    { return _position.getValue(); }
+    void setPosition(const SGVec3d& position)
+    { _position.setValue(position); }
+
+    const SGQuatd& getOrientation() const
+    { return _orientation.getValue(); }
+    void setOrientation(const SGQuatd& orientation)
+    { _orientation.setValue(orientation); }
+
+    double getZoomFactor() const
+    { return _zoomFactor.getValue(); }
+    void setZoomFactor(double zoomFactor)
+    { _zoomFactor.setValue(zoomFactor); }
+
+    const HLAEyeTracker* getEyeTracker() const;
+    HLAEyeTracker* getEyeTracker();
+    void setEyeTracker(HLAEyeTracker* eyeTracker);
+
+    SGLocationd getLocation(const SGTimeStamp& simTime) const;
+
+    SGVec3d getLeftEyeOffset() const;
+    SGVec3d getRightEyeOffset() const;
+
+private:
+    simgear::HLAObjectReferenceData<HLAView> _view;
+    simgear::HLAVec3dData _position;
+    simgear::HLAQuat3dData _orientation;
+    simgear::HLADoubleData _zoomFactor;
+    simgear::HLAObjectReferenceData<HLAEyeTracker> _eyeTracker;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAPerspectiveViewerClass.cxx b/utils/fgviewer/HLAPerspectiveViewerClass.cxx
new file mode 100644 (file)
index 0000000..9d52c8d
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAPerspectiveViewerClass.hxx"
+
+#include "HLAPerspectiveViewer.hxx"
+
+namespace fgviewer {
+
+HLAPerspectiveViewerClass::HLAPerspectiveViewerClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLAViewerClass(name, federate)
+{
+}
+
+HLAPerspectiveViewerClass::~HLAPerspectiveViewerClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLAPerspectiveViewerClass::createObjectInstance(const std::string& name)
+{
+    return new HLAPerspectiveViewer(this, getFederate());
+}
+
+void
+HLAPerspectiveViewerClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+   if (_viewNameIndex.empty())
+        _viewNameIndex = getDataElementIndex("viewName");
+   if (_positionIndex.empty())
+        _positionIndex = getDataElementIndex("location.position");
+   if (_orientationIndex.empty())
+        _orientationIndex = getDataElementIndex("location.orientation");
+   if (_zoomFactorIndex.empty())
+        _zoomFactorIndex = getDataElementIndex("zoomFactor");
+   if (_eyeTrackerNameIndex.empty())
+        _eyeTrackerNameIndex = getDataElementIndex("eyeTrackerName");
+
+    HLAViewerClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAPerspectiveViewerClass.hxx b/utils/fgviewer/HLAPerspectiveViewerClass.hxx
new file mode 100644 (file)
index 0000000..50bfc95
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAPerspectiveViewerClass_hxx
+#define HLAPerspectiveViewerClass_hxx
+
+#include "HLAViewerClass.hxx"
+
+namespace fgviewer {
+
+class HLAPerspectiveViewerClass : public HLAViewerClass {
+public:
+    HLAPerspectiveViewerClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLAPerspectiveViewerClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setViewNameIndex(const std::string& path)
+    { return getDataElementIndex(_viewNameIndex, path); }
+    const simgear::HLADataElementIndex& getViewNameIndex() const
+    { return _viewNameIndex; }
+
+    bool setPositionIndex(const std::string& path)
+    { return getDataElementIndex(_positionIndex, path); }
+    const simgear::HLADataElementIndex& getPositionIndex() const
+    { return _positionIndex; }
+
+    bool setOrientationIndex(const std::string& path)
+    { return getDataElementIndex(_orientationIndex, path); }
+    const simgear::HLADataElementIndex& getOrientationIndex() const
+    { return _orientationIndex; }
+
+    bool setZoomFactorIndex(const std::string& path)
+    { return getDataElementIndex(_zoomFactorIndex, path); }
+    const simgear::HLADataElementIndex& getZoomFactorIndex() const
+    { return _zoomFactorIndex; }
+
+    bool setEyeTrackerNameIndex(const std::string& path)
+    { return getDataElementIndex(_eyeTrackerNameIndex, path); }
+    const simgear::HLADataElementIndex& getEyeTrackerNameIndex() const
+    { return _eyeTrackerNameIndex; }
+
+private:
+    simgear::HLADataElementIndex _viewNameIndex;
+    simgear::HLADataElementIndex _positionIndex;
+    simgear::HLADataElementIndex _orientationIndex;
+    simgear::HLADataElementIndex _zoomFactorIndex;
+    simgear::HLADataElementIndex _eyeTrackerNameIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAProxyDataElement.hxx b/utils/fgviewer/HLAProxyDataElement.hxx
new file mode 100644 (file)
index 0000000..bb33979
--- /dev/null
@@ -0,0 +1,90 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef HLAProxyDataElement_hxx
+#define HLAProxyDataElement_hxx
+
+#include <simgear/hla/HLADataElement.hxx>
+
+namespace simgear {
+
+class HLAProxyDataElement : public HLADataElement {
+public:
+    virtual ~HLAProxyDataElement()
+    { }
+
+    virtual void accept(HLADataElementVisitor& visitor)
+    {
+        HLADataElement* dataElement = _getDataElement();
+        if (!dataElement)
+            return;
+        dataElement->accept(visitor);
+    }
+    virtual void accept(HLAConstDataElementVisitor& visitor) const
+    {
+        const HLADataElement* dataElement = _getDataElement();
+        if (!dataElement)
+            return;
+        dataElement->accept(visitor);
+    }
+
+    virtual bool encode(HLAEncodeStream& stream) const
+    {
+        const HLADataElement* dataElement = _getDataElement();
+        if (!dataElement)
+            return false;
+        return dataElement->encode(stream);
+    }
+    virtual bool decode(HLADecodeStream& stream)
+    {
+        HLADataElement* dataElement = _getDataElement();
+        if (!dataElement)
+            return false;
+        return dataElement->decode(stream);
+    }
+
+    virtual const HLADataType* getDataType() const
+    {
+        const HLADataElement* dataElement = _getDataElement();
+        if (!dataElement)
+            return 0;
+        return dataElement->getDataType();
+    }
+    virtual bool setDataType(const HLADataType* dataType)
+    {
+        HLADataElement* dataElement = _getDataElement();
+        if (!dataElement)
+            return false;
+        return dataElement->setDataType(dataType);
+    }
+
+protected:
+    virtual HLADataElement* _getDataElement() = 0;
+    virtual const HLADataElement* _getDataElement() const = 0;
+
+    virtual void _setStamp(Stamp* stamp)
+    {
+        HLADataElement::_setStamp(stamp);
+        HLADataElement* dataElement = _getDataElement();
+        if (!dataElement)
+            return;
+        dataElement->attachStamp(*this);
+    }
+};
+
+}
+
+#endif
diff --git a/utils/fgviewer/HLARenderer.cxx b/utils/fgviewer/HLARenderer.cxx
new file mode 100644 (file)
index 0000000..e4a84d3
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLARenderer.hxx"
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include "HLARendererClass.hxx"
+
+namespace fgviewer {
+
+HLARenderer::HLARenderer(HLARendererClass* objectClass) :
+    HLAObjectInstance(objectClass)
+{
+}
+
+HLARenderer::~HLARenderer()
+{
+}
+
+void
+HLARenderer::createAttributeDataElements()
+{
+    /// FIXME at some point we should not need that anymore
+    HLAObjectInstance::createAttributeDataElements();
+
+    assert(dynamic_cast<HLARendererClass*>(getObjectClass().get()));
+    HLARendererClass& objectClass = static_cast<HLARendererClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getNameIndex(), _name.getDataElement());
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLARenderer.hxx b/utils/fgviewer/HLARenderer.hxx
new file mode 100644 (file)
index 0000000..e25d959
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLARenderer_hxx
+#define HLARenderer_hxx
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLARendererClass;
+
+class HLARenderer : public simgear::HLAObjectInstance {
+public:
+    HLARenderer(HLARendererClass* objectClass = 0);
+    virtual ~HLARenderer();
+
+    virtual void createAttributeDataElements();
+
+private:
+    simgear::HLAStringData _name;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLARendererClass.cxx b/utils/fgviewer/HLARendererClass.cxx
new file mode 100644 (file)
index 0000000..f6761c1
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLARendererClass.hxx"
+
+#include "HLARenderer.hxx"
+
+namespace fgviewer {
+
+HLARendererClass::HLARendererClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLAObjectClass(name, federate)
+{
+}
+
+HLARendererClass::~HLARendererClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLARendererClass::createObjectInstance(const std::string& name)
+{
+    return new HLARenderer(this);
+}
+
+void
+HLARendererClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    /// FIXME resolve these indices somewhere else!
+    if (_nameIndex.empty())
+        _nameIndex = getDataElementIndex("name");
+    HLAObjectClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLARendererClass.hxx b/utils/fgviewer/HLARendererClass.hxx
new file mode 100644 (file)
index 0000000..4189a25
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLARendererClass_hxx
+#define HLARendererClass_hxx
+
+#include <string>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLARendererClass : public simgear::HLAObjectClass {
+public:
+    HLARendererClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLARendererClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setNameIndex(const std::string& path)
+    { return getDataElementIndex(_nameIndex, path); }
+    const simgear::HLADataElementIndex& getNameIndex() const
+    { return _nameIndex; }
+
+private:
+    simgear::HLADataElementIndex _nameIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLASceneObject.cxx b/utils/fgviewer/HLASceneObject.cxx
new file mode 100644 (file)
index 0000000..115e17d
--- /dev/null
@@ -0,0 +1,314 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLASceneObject.hxx"
+
+#include <osg/Transform>
+
+#include <simgear/scene/util/OsgMath.hxx>
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
+
+#include "HLASceneObjectClass.hxx"
+#include "HLAViewerFederate.hxx"
+
+namespace fgviewer {
+
+class HLASceneObject::_ModelDataElement : public simgear::HLAProxyDataElement {
+public:
+    _ModelDataElement(const SGWeakPtr<HLASceneObject>& sceneObject) :
+        _sceneObject(sceneObject)
+    { }
+    virtual ~_ModelDataElement()
+    { }
+    
+    virtual bool decode(simgear::HLADecodeStream& stream)
+    {
+        if (!HLAProxyDataElement::decode(stream))
+            return false;
+        
+        // No change?
+        if (!_name.getDataElement()->getDirty())
+            return true;
+        _name.getDataElement()->setDirty(false);
+        SGSharedPtr<HLASceneObject> sceneObject = _sceneObject.lock();
+        if (sceneObject.valid())
+            sceneObject->_setModelFileName(_name.getValue());
+        return true;
+    }
+    
+protected:
+    virtual simgear::HLAStringDataElement* _getDataElement()
+    { return _name.getDataElement(); }
+    virtual const simgear::HLAStringDataElement* _getDataElement() const
+    { return _name.getDataElement(); }
+    
+private:
+    const SGWeakPtr<HLASceneObject> _sceneObject;
+    simgear::HLAStringData _name;
+};
+
+class HLASceneObject::_Transform : public osg::Transform {
+public:
+    _Transform(const SGWeakPtr<const HLASceneObject>& sceneObject) :
+        _sceneObject(sceneObject)
+    {
+        setCullingActive(false);
+    }
+    virtual ~_Transform()
+    {
+    }
+
+    virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
+    {
+        if (!nv)
+            return false;
+        const osg::FrameStamp* frameStamp = nv->getFrameStamp();
+        if (!frameStamp)
+            return false;
+        
+        SGLocationd location = _getLocation(SGTimeStamp::fromSec(frameStamp->getSimulationTime()));
+        // the position of the view
+        matrix.preMultTranslate(toOsg(location.getPosition()));
+        // the orientation of the view
+        matrix.preMultRotate(toOsg(location.getOrientation()));
+    
+        return true;
+    }
+    virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
+    {
+        if (!nv)
+            return false;
+        const osg::FrameStamp* frameStamp = nv->getFrameStamp();
+        if (!frameStamp)
+            return false;
+        
+        SGLocationd location = _getLocation(SGTimeStamp::fromSec(frameStamp->getSimulationTime()));
+        // the position of the view
+        matrix.postMultTranslate(toOsg(-location.getPosition()));
+        // the orientation of the view
+        matrix.postMultRotate(toOsg(inverse(location.getOrientation())));
+    
+        return true;
+    }
+
+    virtual osg::BoundingSphere computeBound() const
+    {
+        return osg::BoundingSphere();
+    }
+
+private:
+    SGLocationd _getLocation(const SGTimeStamp& timeStamp) const
+    {
+        // transform from the simulation typical x-forward/y-right/z-down
+        // to the flightgear model system x-back/y-right/z-up
+        // SGQuatd simToModel = SGQuatd::fromEulerDeg(0, 180, 0);
+        SGQuatd simToModel = SGQuatd::fromRealImag(0, SGVec3d(0, 1, 0));
+
+        SGSharedPtr<const HLASceneObject> sceneObject = _sceneObject.lock();
+        if (!sceneObject.valid())
+            return SGLocationd(SGVec3d(0, 0, 0), simToModel);
+
+        // Get the cartesian location at the given time stamp from the hla object
+        SGLocationd location = sceneObject->getLocation(timeStamp);
+        location.setOrientation(location.getOrientation()*simToModel);
+
+        return location;
+    }
+
+    SGWeakPtr<const HLASceneObject> _sceneObject;
+};
+
+HLASceneObject::HLASceneObject(HLASceneObjectClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate) :
+    HLAObjectInstance(objectClass),
+    _sceneObject(federate)
+{
+    _pagedLOD = new osg::PagedLOD;
+    _pagedLOD->setRange(0, 0, 80000);
+        
+    _transform = new _Transform(this);
+    _transform->addChild(_pagedLOD.get());
+}
+
+HLASceneObject::~HLASceneObject()
+{
+    _removeFromSceneGraph();
+}
+
+void
+HLASceneObject::createAttributeDataElements()
+{
+    /// FIXME at some point we should not need that anymore
+    HLAObjectInstance::createAttributeDataElements();
+
+    assert(dynamic_cast<HLASceneObjectClass*>(getObjectClass().get()));
+    HLASceneObjectClass& objectClass = static_cast<HLASceneObjectClass&>(*getObjectClass());
+
+    simgear::HLACartesianLocation* location = new simgear::HLACartesianLocation;
+    setAttributeDataElement(objectClass.getPositionIndex(), location->getPositionDataElement());
+    setAttributeDataElement(objectClass.getOrientationIndex(), location->getOrientationDataElement());
+    setAttributeDataElement(objectClass.getAngularVelocityIndex(), location->getAngularVelocityDataElement());
+    setAttributeDataElement(objectClass.getLinearVelocityIndex(), location->getLinearVelocityDataElement());
+    _location = location;
+
+    setAttributeDataElement(objectClass.getSceneObjectNameIndex(), _sceneObject.getDataElement());
+}
+
+void
+HLASceneObject::discoverInstance(const simgear::RTIData& tag)
+{
+    HLAObjectInstance::discoverInstance(tag);
+    _addToSceneGraph();
+}
+
+void
+HLASceneObject::removeInstance(const simgear::RTIData& tag)
+{
+    _removeFromSceneGraph();
+    HLAObjectInstance::removeInstance(tag);
+}
+
+void
+HLASceneObject::registerInstance(simgear::HLAObjectClass* objectClass)
+{
+    HLAObjectInstance::registerInstance(objectClass);
+    _addToSceneGraph();
+}
+
+void
+HLASceneObject::deleteInstance(const simgear::RTIData& tag)
+{
+    _removeFromSceneGraph();
+    HLAObjectInstance::deleteInstance(tag);
+}
+
+const HLASceneObject*
+HLASceneObject::getSceneObject() const
+{
+    return _sceneObject.getObject();
+}
+
+HLASceneObject*
+HLASceneObject::getSceneObject()
+{
+    return _sceneObject.getObject();
+}
+
+void
+HLASceneObject::setSceneObject(HLASceneObject* sceneObject)
+{
+    _sceneObject.setObject(sceneObject);
+}
+
+SGLocationd
+HLASceneObject::getLocation(const SGTimeStamp& timeStamp) const
+{
+    const HLASceneObject* sceneObject = getSceneObject();
+    if (!sceneObject)
+        return _getRelativeLocation(timeStamp);
+    return sceneObject->getLocation(timeStamp).getAbsoluteLocation(_getRelativeLocation(timeStamp));
+}
+
+simgear::HLADataElement*
+HLASceneObject::getModelDataElement()
+{
+    return new _ModelDataElement(this);
+}
+
+osg::Node*
+HLASceneObject::getNode()
+{
+    return _transform.get();
+}
+
+SGLocationd
+HLASceneObject::_getRelativeLocation(const SGTimeStamp& timeStamp) const
+{
+    if (!_location.valid())
+        return SGLocationd(SGVec3d::zeros(), SGQuatd::unit());
+    return _location->getLocation(timeStamp);
+}
+
+SGVec3d
+HLASceneObject::_getRelativeAngularVelocity() const
+{
+    if (!_location.valid())
+        return SGVec3d(0, 0, 0);
+    return _location->getAngularBodyVelocity();
+}
+
+SGVec3d
+HLASceneObject::_getRelativeLinearVelocity() const
+{
+    if (!_location.valid())
+        return SGVec3d(0, 0, 0);
+    return _location->getLinearBodyVelocity();
+}
+
+void
+HLASceneObject::_setModelFileName(const std::string& fileName)
+{
+    if (0 < _pagedLOD->getNumFileNames() && fileName == _pagedLOD->getFileName(0))
+        return;
+
+    SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
+    if (federate.valid()) {
+        assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
+        HLAViewerFederate* viewerFederate = static_cast<HLAViewerFederate*>(federate.get());
+
+        osg::ref_ptr<osgDB::Options> localOptions;
+        localOptions = static_cast<osgDB::Options*>(viewerFederate->getReaderWriterOptions()->clone(osg::CopyOp()));
+        // FIXME: particle systems have some issues. Do not use them currently.
+        localOptions->setPluginStringData("SimGear::PARTICLESYSTEM", "OFF");
+        _pagedLOD->setDatabaseOptions(localOptions.get());
+    }
+
+    // Finally set the file name
+    if (unsigned numChildren = _pagedLOD->getNumChildren())
+        _pagedLOD->removeChildren(0, numChildren);
+    _pagedLOD->setFileName(0, fileName);
+}
+
+void
+HLASceneObject::_addToSceneGraph()
+{
+    SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
+    if (!federate.valid())
+        return;
+    assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
+    HLAViewerFederate* viewerFederate = static_cast<HLAViewerFederate*>(federate.get());
+
+    /// Add ourselves to the dynamic scene graph
+    viewerFederate->addDynamicModel(getNode());
+}
+
+void
+HLASceneObject::_removeFromSceneGraph()
+{
+    /// FIXME O(#SceneObjects), pool them and reuse in create
+    unsigned i = _transform->getNumParents();
+    while (i--) {
+        osg::Group* parent = _transform->getParent(i);
+        parent->removeChild(_transform.get());
+    }
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLASceneObject.hxx b/utils/fgviewer/HLASceneObject.hxx
new file mode 100644 (file)
index 0000000..f470c23
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLASceneObject_hxx
+#define HLASceneObject_hxx
+
+#include <osg/Node>
+#include <osg/PagedLOD>
+#include <osg/ref_ptr>
+
+#include <simgear/hla/HLAObjectClass.hxx>
+#include <simgear/hla/HLALocation.hxx>
+
+#include "HLAObjectReferenceData.hxx"
+
+namespace fgviewer {
+
+class HLASceneObjectClass;
+
+class HLASceneObject : public simgear::HLAObjectInstance {
+public:
+    HLASceneObject(HLASceneObjectClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate);
+    virtual ~HLASceneObject();
+
+    virtual void createAttributeDataElements();
+
+    virtual void discoverInstance(const simgear::RTIData& tag);
+    virtual void removeInstance(const simgear::RTIData& tag);
+
+    virtual void registerInstance(simgear::HLAObjectClass* objectClass);
+    virtual void deleteInstance(const simgear::RTIData& tag);
+
+    const HLASceneObject* getSceneObject() const;
+    HLASceneObject* getSceneObject();
+    void setSceneObject(HLASceneObject* sceneObject);
+
+    virtual SGLocationd getLocation(const SGTimeStamp& timeStamp) const;
+
+    simgear::HLADataElement* getModelDataElement();
+
+    osg::Node* getNode();
+
+protected:
+    SGLocationd _getRelativeLocation(const SGTimeStamp& timeStamp) const;
+    // Return the velocities of this current object without taking the referenced velocities into account
+    SGVec3d _getRelativeAngularVelocity() const;
+    SGVec3d _getRelativeLinearVelocity() const;
+
+    void _setModelFileName(const std::string& fileName);
+
+private:
+    class _ModelDataElement;
+    class _Transform;
+
+    // Add the transform node to the scenegraph
+    void _addToSceneGraph();
+    // Remove the transform node from the scenegraph
+    void _removeFromSceneGraph();
+
+    // The location of this object
+    SGSharedPtr<simgear::HLAAbstractLocation> _location;
+    // If this object is living relative to an other one, this one is non zero
+    simgear::HLAObjectReferenceData<HLASceneObject> _sceneObject;
+
+    // The top level transform node for this scene object
+    osg::ref_ptr<_Transform> _transform;
+    osg::ref_ptr<osg::PagedLOD> _pagedLOD;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLASceneObjectClass.cxx b/utils/fgviewer/HLASceneObjectClass.cxx
new file mode 100644 (file)
index 0000000..ea42902
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLASceneObjectClass.hxx"
+
+#include "HLASceneObject.hxx"
+#include "HLAViewerFederate.hxx"
+
+namespace fgviewer {
+
+HLASceneObjectClass::HLASceneObjectClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLAObjectClass(name, federate)
+{
+}
+
+HLASceneObjectClass::~HLASceneObjectClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLASceneObjectClass::createObjectInstance(const std::string& name)
+{
+    return new HLASceneObject(this, getFederate());
+}
+
+void
+HLASceneObjectClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    /// FIXME resolve these indices somewhere else!
+    if (_positionIndex.empty())
+        _positionIndex = getDataElementIndex("location.position");
+    if (_orientationIndex.empty())
+        _orientationIndex = getDataElementIndex("location.orientation");
+    if (_angularVelocityIndex.empty())
+        _angularVelocityIndex = getDataElementIndex("velocity.angular");
+    if (_linearVelocityIndex.empty())
+        _linearVelocityIndex = getDataElementIndex("velocity.linear");
+    HLAObjectClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLASceneObjectClass.hxx b/utils/fgviewer/HLASceneObjectClass.hxx
new file mode 100644 (file)
index 0000000..9ef21e5
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLASceneObjectClass_hxx
+#define HLASceneObjectClass_hxx
+
+#include <string>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLASceneObjectClass : public simgear::HLAObjectClass {
+public:
+    HLASceneObjectClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLASceneObjectClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setPositionIndex(const std::string& path)
+    { return getDataElementIndex(_positionIndex, path); }
+    const simgear::HLADataElementIndex& getPositionIndex() const
+    { return _positionIndex; }
+
+    bool setOrientationIndex(const std::string& path)
+    { return getDataElementIndex(_orientationIndex, path); }
+    const simgear::HLADataElementIndex& getOrientationIndex() const
+    { return _orientationIndex; }
+
+    bool setAngularVelocityIndex(const std::string& path)
+    { return getDataElementIndex(_angularVelocityIndex, path); }
+    const simgear::HLADataElementIndex& getAngularVelocityIndex() const
+    { return _angularVelocityIndex; }
+
+    bool setLinearVelocityIndex(const std::string& path)
+    { return getDataElementIndex(_linearVelocityIndex, path); }
+    const simgear::HLADataElementIndex& getLinearVelocityIndex() const
+    { return _linearVelocityIndex; }
+
+    /// FIXME make sure that we do not get closed reference loops at some point!
+    /// Do this in the setter of the object data element so that its not getting a runtime issue
+    bool setSceneObjectNameIndex(const std::string& path)
+    { return getDataElementIndex(_sceneObjectNameIndex, path); }
+    const simgear::HLADataElementIndex& getSceneObjectNameIndex() const
+    { return _sceneObjectNameIndex; }
+
+private:
+    /// FIXME use a location factory for that?!
+    simgear::HLADataElementIndex _positionIndex;
+    simgear::HLADataElementIndex _orientationIndex;
+
+    simgear::HLADataElementIndex _angularVelocityIndex;
+    simgear::HLADataElementIndex _linearVelocityIndex;
+
+    simgear::HLADataElementIndex _sceneObjectNameIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAView.cxx b/utils/fgviewer/HLAView.cxx
new file mode 100644 (file)
index 0000000..5854ce4
--- /dev/null
@@ -0,0 +1,135 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAView.hxx"
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include "HLAViewClass.hxx"
+#include "HLAViewerFederate.hxx"
+
+namespace fgviewer {
+
+HLAView::HLAView(HLAViewClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate) :
+    HLAObjectInstance(objectClass),
+    _sceneObject(federate)
+{
+}
+
+HLAView::~HLAView()
+{
+}
+
+void
+HLAView::createAttributeDataElements()
+{
+    /// FIXME at some point we should not need that anymore
+    HLAObjectInstance::createAttributeDataElements();
+
+    assert(dynamic_cast<HLAViewClass*>(getObjectClass().get()));
+    HLAViewClass& objectClass = static_cast<HLAViewClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getNameIndex(), _name.getDataElement());
+    setAttributeDataElement(objectClass.getPositionIndex(), _position.getDataElement());
+    setAttributeDataElement(objectClass.getOrientationIndex(), _orientation.getDataElement());
+    setAttributeDataElement(objectClass.getSceneObjectNameIndex(), _sceneObject.getDataElement());
+}
+
+void
+HLAView::discoverInstance(const simgear::RTIData& tag)
+{
+    HLAObjectInstance::discoverInstance(tag);
+
+    SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
+    if (federate.valid()) {
+        assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
+        static_cast<HLAViewerFederate*>(federate.get())->insertView(this);
+    }
+}
+
+void
+HLAView::removeInstance(const simgear::RTIData& tag)
+{
+    HLAObjectInstance::removeInstance(tag);
+
+    SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
+    if (federate.valid()) {
+        assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
+        static_cast<HLAViewerFederate*>(federate.get())->eraseView(this);
+    }
+}
+
+void
+HLAView::registerInstance(simgear::HLAObjectClass* objectClass)
+{
+    HLAObjectInstance::registerInstance(objectClass);
+
+    SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
+    if (federate.valid()) {
+        assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
+        static_cast<HLAViewerFederate*>(federate.get())->insertView(this);
+    }
+}
+
+void
+HLAView::deleteInstance(const simgear::RTIData& tag)
+{
+    SGSharedPtr<simgear::HLAFederate> federate = getFederate().lock();
+    if (federate.valid()) {
+        assert(dynamic_cast<HLAViewerFederate*>(federate.get()));
+        static_cast<HLAViewerFederate*>(federate.get())->eraseView(this);
+    }
+
+    HLAObjectInstance::deleteInstance(tag);
+}
+
+const HLASceneObject*
+HLAView::getSceneObject() const
+{
+    /// FIXME!!! The federate should track unresolved object references
+    _sceneObject.recheckObject();
+    return _sceneObject.getObject();
+}
+
+HLASceneObject*
+HLAView::getSceneObject()
+{
+    /// FIXME!!! The federate should track unresolved object references
+    _sceneObject.recheckObject();
+    return _sceneObject.getObject();
+}
+
+void
+HLAView::setSceneObject(HLASceneObject* sceneObject)
+{
+    _sceneObject.setObject(sceneObject);
+}
+
+SGLocationd
+HLAView::getLocation(const SGTimeStamp& timeStamp) const
+{
+    const HLASceneObject* sceneObject = getSceneObject();
+    SGLocationd location(getPosition(), getOrientation());
+    if (!sceneObject)
+        return location;
+    return sceneObject->getLocation(timeStamp).getAbsoluteLocation(location);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAView.hxx b/utils/fgviewer/HLAView.hxx
new file mode 100644 (file)
index 0000000..f8c11d6
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAView_hxx
+#define HLAView_hxx
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/hla/HLAObjectInstance.hxx>
+
+#include "HLAObjectReferenceData.hxx"
+#include "HLASceneObject.hxx"
+
+namespace fgviewer {
+
+class HLAViewClass;
+
+class HLAView : public simgear::HLAObjectInstance {
+public:
+    HLAView(HLAViewClass* objectClass, const SGWeakPtr<simgear::HLAFederate>& federate);
+    virtual ~HLAView();
+
+    virtual void createAttributeDataElements();
+
+    virtual void discoverInstance(const simgear::RTIData& tag);
+    virtual void removeInstance(const simgear::RTIData& tag);
+
+    virtual void registerInstance(simgear::HLAObjectClass* objectClass);
+    virtual void deleteInstance(const simgear::RTIData& tag);
+
+    const std::string& getNameAttribute() const
+    { return _name.getValue(); }
+    void setNameAttribute(const std::string& name)
+    { _name.setValue(name); }
+
+    const SGVec3d& getPosition() const
+    { return _position.getValue(); }
+    void setPosition(const SGVec3d& position)
+    { _position.setValue(position); }
+
+    const SGQuatd& getOrientation() const
+    { return _orientation.getValue(); }
+    void setOrientation(const SGQuatd& orientation)
+    { _orientation.setValue(orientation); }
+
+    const HLASceneObject* getSceneObject() const;
+    HLASceneObject* getSceneObject();
+    void setSceneObject(HLASceneObject* sceneObject);
+
+    virtual SGLocationd getLocation(const SGTimeStamp& simTime) const;
+
+private:
+    simgear::HLAStringData _name;
+
+    simgear::HLAVec3dData _position;
+    simgear::HLAQuat3dData _orientation;
+
+    simgear::HLAObjectReferenceData<HLASceneObject> _sceneObject;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAViewClass.cxx b/utils/fgviewer/HLAViewClass.cxx
new file mode 100644 (file)
index 0000000..e33caa7
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAViewClass.hxx"
+
+#include "HLAView.hxx"
+
+namespace fgviewer {
+
+HLAViewClass::HLAViewClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLAObjectClass(name, federate)
+{
+}
+
+HLAViewClass::~HLAViewClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLAViewClass::createObjectInstance(const std::string& name)
+{
+    return new HLAView(this, getFederate());
+}
+
+void
+HLAViewClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    /// FIXME resolve these indices somewhere else!
+    if (_nameIndex.empty())
+        _nameIndex = getDataElementIndex("name");
+    if (_positionIndex.empty())
+        _positionIndex = getDataElementIndex("location.position");
+    if (_orientationIndex.empty())
+        _orientationIndex = getDataElementIndex("location.orientation");
+    if (_sceneObjectNameIndex.empty())
+        _sceneObjectNameIndex = getDataElementIndex("sceneObjectName");
+    HLAObjectClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAViewClass.hxx b/utils/fgviewer/HLAViewClass.hxx
new file mode 100644 (file)
index 0000000..e57a17c
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAViewClass_hxx
+#define HLAViewClass_hxx
+
+#include <string>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLAViewClass : public simgear::HLAObjectClass {
+public:
+    HLAViewClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLAViewClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setNameIndex(const std::string& path)
+    { return getDataElementIndex(_nameIndex, path); }
+    const simgear::HLADataElementIndex& getNameIndex() const
+    { return _nameIndex; }
+
+    bool setPositionIndex(const std::string& path)
+    { return getDataElementIndex(_positionIndex, path); }
+    const simgear::HLADataElementIndex& getPositionIndex() const
+    { return _positionIndex; }
+
+    bool setOrientationIndex(const std::string& path)
+    { return getDataElementIndex(_orientationIndex, path); }
+    const simgear::HLADataElementIndex& getOrientationIndex() const
+    { return _orientationIndex; }
+
+    bool setSceneObjectNameIndex(const std::string& path)
+    { return getDataElementIndex(_sceneObjectNameIndex, path); }
+    const simgear::HLADataElementIndex& getSceneObjectNameIndex() const
+    { return _sceneObjectNameIndex; }
+
+private:
+    simgear::HLADataElementIndex _nameIndex;
+    simgear::HLADataElementIndex _positionIndex;
+    simgear::HLADataElementIndex _orientationIndex;
+    simgear::HLADataElementIndex _sceneObjectNameIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAViewer.cxx b/utils/fgviewer/HLAViewer.cxx
new file mode 100644 (file)
index 0000000..3cc6566
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAViewer.hxx"
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include "HLAViewerClass.hxx"
+
+namespace fgviewer {
+
+HLAViewer::HLAViewer(HLAViewerClass* objectClass) :
+    HLAObjectInstance(objectClass)
+{
+}
+
+HLAViewer::~HLAViewer()
+{
+}
+
+void
+HLAViewer::createAttributeDataElements()
+{
+    HLAObjectInstance::createAttributeDataElements();
+
+    assert(dynamic_cast<HLAViewerClass*>(getObjectClass().get()));
+    HLAViewerClass& objectClass = static_cast<HLAViewerClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getNameIndex(), _name.getDataElement());
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAViewer.hxx b/utils/fgviewer/HLAViewer.hxx
new file mode 100644 (file)
index 0000000..432dfed
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAViewer_hxx
+#define HLAViewer_hxx
+
+#include <simgear/hla/HLAArrayDataElement.hxx>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLAViewerClass;
+
+class HLAViewer : public simgear::HLAObjectInstance {
+public:
+    HLAViewer(HLAViewerClass* objectClass = 0);
+    virtual ~HLAViewer();
+
+    virtual void createAttributeDataElements();
+
+private:
+    simgear::HLAStringData _name;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAViewerClass.cxx b/utils/fgviewer/HLAViewerClass.cxx
new file mode 100644 (file)
index 0000000..a27484d
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAViewerClass.hxx"
+
+#include "HLAViewer.hxx"
+
+namespace fgviewer {
+
+HLAViewerClass::HLAViewerClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLAObjectClass(name, federate)
+{
+}
+
+HLAViewerClass::~HLAViewerClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLAViewerClass::createObjectInstance(const std::string& name)
+{
+    return new HLAViewer(this);
+}
+
+void
+HLAViewerClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    /// FIXME resolve these indices somewhere else!
+    if (_nameIndex.empty())
+        _nameIndex = getDataElementIndex("name");
+    HLAObjectClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAViewerClass.hxx b/utils/fgviewer/HLAViewerClass.hxx
new file mode 100644 (file)
index 0000000..110eccd
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAViewerClass_hxx
+#define HLAViewerClass_hxx
+
+#include <string>
+#include <simgear/hla/HLAObjectClass.hxx>
+
+namespace fgviewer {
+
+class HLAViewerClass : public simgear::HLAObjectClass {
+public:
+    HLAViewerClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLAViewerClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setNameIndex(const std::string& path)
+    { return getDataElementIndex(_nameIndex, path); }
+    const simgear::HLADataElementIndex& getNameIndex() const
+    { return _nameIndex; }
+
+private:
+    simgear::HLADataElementIndex _nameIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAViewerFederate.cxx b/utils/fgviewer/HLAViewerFederate.cxx
new file mode 100644 (file)
index 0000000..b2b769e
--- /dev/null
@@ -0,0 +1,253 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAViewerFederate.hxx"
+
+#include <osg/Group>
+#include <osgDB/Options>
+
+#include "HLAEyeTrackerClass.hxx"
+#include "HLAMPAircraftClass.hxx"
+#include "HLAPerspectiveViewer.hxx"
+#include "HLAPerspectiveViewerClass.hxx"
+#include "HLASceneObjectClass.hxx"
+#include "HLAView.hxx"
+#include "HLAViewClass.hxx"
+#include "Viewer.hxx"
+
+namespace fgviewer {
+
+HLAViewerFederate::HLAViewerFederate() :
+    _group(new osg::Group)
+{
+}
+
+HLAViewerFederate::~HLAViewerFederate()
+{
+}
+
+const HLAPerspectiveViewer*
+HLAViewerFederate::getViewer() const
+{
+    return _perspectiveViewer.get();
+}
+
+HLAPerspectiveViewer*
+HLAViewerFederate::getViewer()
+{
+    return _perspectiveViewer.get();
+}
+
+void
+HLAViewerFederate::setViewer(HLAPerspectiveViewer* perspectiveViewer)
+{
+    if (_perspectiveViewer.get() == perspectiveViewer)
+        return;
+    _perspectiveViewer = perspectiveViewer;
+}
+
+const HLAView*
+HLAViewerFederate::getView() const
+{
+    if (!_perspectiveViewer.valid())
+        return 0;
+    return _perspectiveViewer->getView();
+}
+
+HLAView*
+HLAViewerFederate::getView()
+{
+    if (!_perspectiveViewer.valid())
+        return 0;
+    return _perspectiveViewer->getView();
+}
+
+void
+HLAViewerFederate::setView(HLAView* view)
+{
+    if (!_perspectiveViewer.valid())
+        return;
+    return _perspectiveViewer->setView(view);
+}
+
+simgear::HLAObjectClass*
+HLAViewerFederate::createObjectClass(const std::string& name)
+{
+    if (name == "FGView") {
+        _viewClass = new HLAViewClass(name, this);
+        return _viewClass.get();
+    } else if (name == "FGPerspectiveViewer") {
+        _perspectiveViewerClass = new HLAPerspectiveViewerClass(name, this);
+        return _perspectiveViewerClass.get();
+    // } else if (name == "FGOrthographicViewer") {
+    //     _orthographicViewerClass = new HLAOrthograpicViewerClass(name, this);
+    //     return _orthographicViewerClass.get();
+    } else if (name == "FGEyeTracker") {
+        return new HLAEyeTrackerClass(name, this);
+    // } else if (name == "FGPerspectiveCamera") {
+    //     _perspectiveCameraClass = new HLAPerspectiveCameraClass(name, this);
+    //     return _perspectiveCameraClass.get();
+    // } else if (name == "FGOrthographicCamera") {
+    //     _orthographicCameraClass = new HLAOrthographicCameraClass(name, this);
+    //     return _orthographicCameraClass.get();
+    // } else if (name == "FGWindowDrawable") {
+    //     _windowDrawableClass = new HLAWindowDrawableClass(name, this);
+    //     return _windowDrawableClass.get();
+    // } else if (name == "FGRenderer") {
+    //     _rendererClass = new HLARendererClass(name, this);
+    //     return _rendererClass.get();
+    }
+    /// Classes for model type objects.
+    else if (name == "FGSceneObject") {
+        return new HLASceneObjectClass(name, this);
+    } else if (name == "MPAircraft") {
+        return new HLAMPAircraftClass(name, this);
+    }
+    /// Do not subscribe to anything else
+    else {
+        return 0;
+    }
+}
+
+bool
+HLAViewerFederate::init()
+{
+    if (!HLAFederate::init())
+        return false;
+    
+    if (!_perspectiveViewerClass.valid())
+        return false;
+    if (!_viewClass.valid())
+        return false;
+    
+    // Create a viewer ...
+    _perspectiveViewer = new HLAPerspectiveViewer(_perspectiveViewerClass.get(), this);
+    _perspectiveViewer->registerInstance(_perspectiveViewerClass.get());
+    // ... with a nice view
+    _defaultView = new HLAView(_viewClass.get(), this);
+    _defaultView->registerInstance(_viewClass.get());
+    _perspectiveViewer->setView(_defaultView.get());
+    
+    return true;
+}
+
+bool
+HLAViewerFederate::update()
+{
+    // if (_view.valid())
+    //     _view->updateAttributeValues(simgear::RTIData("frame"));
+    if (_perspectiveViewer.valid())
+        _perspectiveViewer->updateAttributeValues(simgear::RTIData("frame"));
+
+    // Just go ahead as far as possible.
+    // This is just fine for a viewer.
+    return HLAFederate::timeAdvanceAvailable();
+}
+
+bool
+HLAViewerFederate::shutdown()
+{
+    if (_defaultView.valid())
+        _defaultView->deleteInstance(simgear::RTIData("shutdown"));
+    _defaultView.clear();
+
+    if (_perspectiveViewer.valid())
+        _perspectiveViewer->deleteInstance(simgear::RTIData("shutdown"));
+    _perspectiveViewer.clear();
+
+    _group->removeChildren(0, _group->getNumChildren());
+
+    return HLAFederate::shutdown();
+}
+
+osg::Node*
+HLAViewerFederate::getDynamicModelNode()
+{
+    return _group.get();
+}
+
+void
+HLAViewerFederate::addDynamicModel(osg::Node* node)
+{
+    /// FIXME can do something more intelligent like a dequeue
+    /// when returning here something to identify the entry, removal is about O(1)
+    _group->addChild(node);
+}
+
+void
+HLAViewerFederate::removeDynamicModel(osg::Node* node)
+{
+    _group->removeChild(node);
+}
+
+osg::ref_ptr<const osgDB::Options>
+HLAViewerFederate::getReaderWriterOptions() const
+{
+    // Cannot use the thread safe variant of the observed_ptr methods here since the
+    // viewer is currently allocated on the stack.
+    if (!_viewer.valid())
+        return osg::ref_ptr<const osgDB::Options>();
+    return _viewer->getReaderWriterOptions();
+}
+
+void
+HLAViewerFederate::attachToViewer(Viewer* viewer)
+{
+    if (!viewer) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLAViewerFederate::attachToViewer(): Ignoring zero viewer!");
+        return;
+    }
+    if (_viewer.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "HLAViewerFederate::attachToViewer(): Not attaching a second viewer!");
+        return;
+    }
+    _viewer = viewer;
+    _viewer->insertSceneData(getDynamicModelNode());
+}
+
+void
+HLAViewerFederate::insertView(HLAView* view)
+{
+    _viewList.push_back(view);
+    /// FIXME not always
+    setView(view);
+}
+
+void
+HLAViewerFederate::eraseView(HLAView* view)
+{
+    //// FIXME store the iterator!!!!
+    for (ViewList::iterator i = _viewList.begin(); i != _viewList.end(); ++i) {
+        if (i->get() != view)
+            continue;
+        _viewList.erase(i);
+        break;
+    }
+    if (getView() == view) {
+        if (_viewList.empty()) {
+            setView(_defaultView.get());
+        } else {
+            setView(_viewList.back().get());
+        }
+    }
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAViewerFederate.hxx b/utils/fgviewer/HLAViewerFederate.hxx
new file mode 100644 (file)
index 0000000..9f66dfc
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAViewerFederate_hxx
+#define HLAViewerFederate_hxx
+
+#include <osg/ref_ptr>
+#include <osg/observer_ptr>
+#include <osg/Group>
+#include <osg/Node>
+#include <osgDB/Options>
+
+#include <simgear/hla/HLAFederate.hxx>
+
+#include "HLASceneObjectClass.hxx"
+#include "HLAView.hxx"
+#include "HLAViewClass.hxx"
+#include "HLAPerspectiveViewer.hxx"
+#include "HLAPerspectiveViewerClass.hxx"
+#include "HLAMPAircraftClass.hxx"
+
+namespace fgviewer {
+
+class Viewer;
+
+class HLAViewerFederate : public simgear::HLAFederate {
+public:
+    HLAViewerFederate();
+    virtual ~HLAViewerFederate();
+
+    const HLAPerspectiveViewer* getViewer() const;
+    HLAPerspectiveViewer* getViewer();
+    void setViewer(HLAPerspectiveViewer* viewer);
+
+    const HLAView* getView() const;
+    HLAView* getView();
+    void setView(HLAView* view);
+
+    virtual simgear::HLAObjectClass* createObjectClass(const std::string& name);
+
+    virtual bool init();
+    virtual bool update();
+    virtual bool shutdown();
+
+    /// The node containing all the dynamic models attached to this viewer
+    osg::Node* getDynamicModelNode();
+    void addDynamicModel(osg::Node* node);
+    void removeDynamicModel(osg::Node* node);
+
+    /// Dynamic models use this options struct for loading/paging
+    osg::ref_ptr<const osgDB::Options> getReaderWriterOptions() const;
+
+    /// Called by the viewer.
+    void attachToViewer(Viewer* viewer);
+
+    /// Temporary application management
+    void insertView(HLAView* view);
+    void eraseView(HLAView* view);
+
+private:
+    /// Explicitly known object classes
+    SGSharedPtr<HLAPerspectiveViewerClass> _perspectiveViewerClass;
+    SGSharedPtr<HLAViewClass> _viewClass;
+
+    /// The perspective viewer of this viewer federate. FIXME: also allow orthographic viewers for instruments!
+    SGSharedPtr<HLAPerspectiveViewer> _perspectiveViewer;
+
+    /// The default absolute view
+    SGSharedPtr<HLAView> _defaultView;
+
+    /// A list of all available views
+    typedef std::list<SGSharedPtr<HLAView> > ViewList;
+    ViewList _viewList;
+
+    /// The openscenegraphs side of this component
+    osg::ref_ptr<osg::Group> _group;
+
+    /// The backward reference to the viewer
+    osg::observer_ptr<Viewer> _viewer;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAWindowDrawable.cxx b/utils/fgviewer/HLAWindowDrawable.cxx
new file mode 100644 (file)
index 0000000..409553c
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAWindowDrawable.hxx"
+
+#include "HLAWindowDrawableClass.hxx"
+
+namespace fgviewer {
+
+HLAWindowDrawable::HLAWindowDrawable(HLAWindowDrawableClass* objectClass) :
+    HLADrawable(objectClass)
+{
+}
+
+HLAWindowDrawable::~HLAWindowDrawable()
+{
+}
+
+void
+HLAWindowDrawable::createAttributeDataElements()
+{
+    HLADrawable::createAttributeDataElements();
+
+    assert(dynamic_cast<HLAWindowDrawableClass*>(getObjectClass().get()));
+    HLAWindowDrawableClass& objectClass = static_cast<HLAWindowDrawableClass&>(*getObjectClass());
+
+    setAttributeDataElement(objectClass.getFullscreenIndex(), _fullscreen.getDataElement());
+    setAttributeDataElement(objectClass.getPositionIndex(), _position.getDataElement());
+    setAttributeDataElement(objectClass.getSizeIndex(), _size.getDataElement());
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAWindowDrawable.hxx b/utils/fgviewer/HLAWindowDrawable.hxx
new file mode 100644 (file)
index 0000000..4ab1f56
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAWindowDrawable_hxx
+#define HLAWindowDrawable_hxx
+
+#include <simgear/hla/HLABasicDataElement.hxx>
+#include "HLADrawable.hxx"
+
+namespace fgviewer {
+
+class HLAWindowDrawableClass;
+
+class HLAWindowDrawable : public HLADrawable {
+public:
+    HLAWindowDrawable(HLAWindowDrawableClass* objectClass = 0);
+    virtual ~HLAWindowDrawable();
+
+    virtual void createAttributeDataElements();
+
+    bool getFullscreen() const
+    { return _fullscreen.getValue(); }
+    void setFullscreen(bool fullscreen)
+    { _fullscreen.setValue(fullscreen); }
+
+    const SGVec2i& getPosition() const
+    { return _position.getValue(); }
+    void setPosition(const SGVec2i& position)
+    { _position.setValue(position); }
+
+    const SGVec2i& getSize() const
+    { return _size.getValue(); }
+    void setSize(const SGVec2i& size)
+    { _size.setValue(size); }
+
+private:
+    simgear::HLABoolData _fullscreen;
+    simgear::HLAVec2iData _position;
+    simgear::HLAVec2iData _size;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/HLAWindowDrawableClass.cxx b/utils/fgviewer/HLAWindowDrawableClass.cxx
new file mode 100644 (file)
index 0000000..5a13c57
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "HLAWindowDrawableClass.hxx"
+
+#include "HLAWindowDrawable.hxx"
+
+namespace fgviewer {
+
+HLAWindowDrawableClass::HLAWindowDrawableClass(const std::string& name, simgear::HLAFederate* federate) :
+    HLADrawableClass(name, federate)
+{
+}
+
+HLAWindowDrawableClass::~HLAWindowDrawableClass()
+{
+}
+
+simgear::HLAObjectInstance*
+HLAWindowDrawableClass::createObjectInstance(const std::string& name)
+{
+    return new HLAWindowDrawable(this);
+}
+
+void
+HLAWindowDrawableClass::createAttributeDataElements(simgear::HLAObjectInstance& objectInstance)
+{
+    if (_fullscreenIndex.empty())
+        _fullscreenIndex = getDataElementIndex("fullscreen");
+    if (_positionIndex.empty())
+        _positionIndex = getDataElementIndex("position");
+    if (_sizeIndex.empty())
+        _sizeIndex = getDataElementIndex("size");
+    HLADrawableClass::createAttributeDataElements(objectInstance);
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/HLAWindowDrawableClass.hxx b/utils/fgviewer/HLAWindowDrawableClass.hxx
new file mode 100644 (file)
index 0000000..84d9c3e
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef HLAWindowDrawableClass_hxx
+#define HLAWindowDrawableClass_hxx
+
+#include "HLADrawableClass.hxx"
+
+namespace fgviewer {
+
+class HLAWindowDrawableClass : public HLADrawableClass {
+public:
+    HLAWindowDrawableClass(const std::string& name, simgear::HLAFederate* federate);
+    virtual ~HLAWindowDrawableClass();
+
+    /// Create a new instance of this class.
+    virtual simgear::HLAObjectInstance* createObjectInstance(const std::string& name);
+
+    virtual void createAttributeDataElements(simgear::HLAObjectInstance& objectInstance);
+
+    bool setFullscreenIndex(const std::string& path)
+    { return getDataElementIndex(_fullscreenIndex, path); }
+    const simgear::HLADataElementIndex& getFullscreenIndex() const
+    { return _fullscreenIndex; }
+
+    bool setPositionIndex(const std::string& path)
+    { return getDataElementIndex(_positionIndex, path); }
+    const simgear::HLADataElementIndex& getPositionIndex() const
+    { return _positionIndex; }
+
+    bool setSizeIndex(const std::string& path)
+    { return getDataElementIndex(_sizeIndex, path); }
+    const simgear::HLADataElementIndex& getSizeIndex() const
+    { return _sizeIndex; }
+
+private:
+    simgear::HLADataElementIndex _fullscreenIndex;
+    simgear::HLADataElementIndex _positionIndex;
+    simgear::HLADataElementIndex _sizeIndex;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/MEncoderCaptureOperation.hxx b/utils/fgviewer/MEncoderCaptureOperation.hxx
new file mode 100644 (file)
index 0000000..0519965
--- /dev/null
@@ -0,0 +1,134 @@
+// MEncoderCaptureOperation.hxx -- capture video stream into mencoder
+//
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef MEncoderCaptureOperation_HXX
+#define MEncoderCaptureOperation_HXX
+
+#include <cstdio>
+#include <sstream>
+#include <string>
+
+#include <osgViewer/ViewerEventHandlers>
+
+/// Class to capture into a pipe driven mencoder.
+/// To integrate this into a viewer:
+///  MEncoderCaptureOperation* mencoderCaptureOperation = new MEncoderCaptureOperation("/tmp/fgviewer.avi", 60);
+///  osgViewer::ScreenCaptureHandler* c = new osgViewer::ScreenCaptureHandler(mencoderCaptureOperation, -1);
+///  viewer.addEventHandler(c);
+///  c->startCapture();
+
+namespace fgviewer {
+
+class MEncoderCaptureOperation : public osgViewer::ScreenCaptureHandler::CaptureOperation {
+public:
+    MEncoderCaptureOperation(const std::string& fileName = "video.avi", unsigned fps = 30) :
+        _fps(fps),
+        _fileName(fileName),
+        _options("-ovc lavc"),
+        _file(0),
+        _width(-1),
+        _height(-1)
+    { }
+    virtual ~MEncoderCaptureOperation()
+    { _close(); }
+
+    const std::string& getFileName() const
+    { return _fileName; }
+    void setFileName(const std::string& fileName)
+    { _fileName = fileName; }
+
+    unsigned getFramesPerSecond() const
+    { return _fps; }
+    void setFramesPerSecond(unsigned fps)
+    { _fps = fps; }
+
+    const std::string& getOptions() const
+    { return _options; }
+    void setOptions(const std::string& options)
+    { _options = options; }
+
+    virtual void operator()(const osg::Image& image, const unsigned int)
+    {
+        // Delay any action until we have a valid image
+        if (!image.valid())
+            return;
+
+        // Ensure an open file
+        if (!_file) {
+            // If the video was already opened and we got any error,
+            // do not reopen with the same name.
+            if (0 < _width)
+                return;
+            _width = image.s();
+            _height = image.t();
+            if (!_open())
+                return;
+        }
+        // Ensure we did not change dimensions
+        if (image.s() != _width)
+            return;
+        if (image.t() != _height)
+            return;
+
+        // Write upside down flipped image
+        for (int row = _height - 1; 0 <= row; --row) {
+            size_t ret = fwrite(image.data(0, row), 1, image.getRowSizeInBytes(), _file);
+            if (ret != image.getRowSizeInBytes())
+                return;
+        }
+    }
+
+private:
+    bool _open()
+    {
+        if (_file)
+            return false;
+        /// FIXME improve: adapt format to the format we get from the image
+        std::stringstream ss;
+        ss << "mencoder - -demuxer rawvideo -rawvideo fps="
+           << _fps << ":w=" << _width << ":h=" << _height
+           << ":format=rgb24 -o " << _fileName << " " << _options;
+#ifdef _WIN32
+        _file = popen(ss.str().c_str(), "wb");
+#else
+        _file = popen(ss.str().c_str(), "w");
+#endif
+        return _file != 0;
+    }
+    void _close()
+    {
+        if (!_file)
+            return;
+        pclose(_file);
+        _file = 0;
+    }
+
+    /// Externally given:
+    unsigned _fps;
+    std::string _fileName;
+    std::string _options;
+
+    /// Internal determined
+    FILE* _file;
+    int _width;
+    int _height;
+};
+
+}
+
+#endif
diff --git a/utils/fgviewer/Renderer.cxx b/utils/fgviewer/Renderer.cxx
new file mode 100644 (file)
index 0000000..600bd68
--- /dev/null
@@ -0,0 +1,121 @@
+// Viewer.hxx -- alternative flightgear viewer application
+//
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "Renderer.hxx"
+
+#include <osgViewer/Renderer>
+#include <simgear/scene/material/EffectCullVisitor.hxx>
+
+#include "Drawable.hxx"
+#include "Viewer.hxx"
+#include "SlaveCamera.hxx"
+
+namespace fgviewer  {
+
+// FIXME I understand why we currently need this, but this seems like
+// weird to require an own cull visitor.
+static void installCullVisitor(osg::Camera& camera)
+{
+    osgViewer::Renderer* renderer = static_cast<osgViewer::Renderer*>(camera.getRenderer());
+    for (int i = 0; i < 2; ++i) {
+        osgUtil::SceneView* sceneView = renderer->getSceneView(i);
+        osg::ref_ptr<osgUtil::CullVisitor::Identifier> identifier;
+
+        identifier = sceneView->getCullVisitor()->getIdentifier();
+        sceneView->setCullVisitor(new simgear::EffectCullVisitor);
+        sceneView->getCullVisitor()->setIdentifier(identifier.get());
+
+        identifier = sceneView->getCullVisitorLeft()->getIdentifier();
+        sceneView->setCullVisitorLeft(sceneView->getCullVisitor()->clone());
+        sceneView->getCullVisitorLeft()->setIdentifier(identifier.get());
+
+        identifier = sceneView->getCullVisitorRight()->getIdentifier();
+        sceneView->setCullVisitorRight(sceneView->getCullVisitor()->clone());
+        sceneView->getCullVisitorRight()->setIdentifier(identifier.get());
+    }
+}
+
+class Renderer::_SlaveCamera : public SlaveCamera {
+public:
+    _SlaveCamera(const std::string& name) :
+        SlaveCamera(name)
+    { 
+    }
+    virtual ~_SlaveCamera()
+    {
+    }
+    virtual osg::Camera* _realizeImplementation(Viewer& viewer)
+    {
+        osg::Camera* camera = SlaveCamera::_realizeImplementation(viewer);
+        if (!camera)
+            return 0;
+
+        camera->addChild(viewer.getSceneDataGroup());
+
+        viewer.addSlave(camera, osg::Matrix::identity(), getViewOffset(), false /*useMastersSceneData*/);
+        installCullVisitor(*camera);
+    
+        return camera;
+    }
+    virtual bool _updateImplementation(Viewer& viewer)
+    {
+        getCamera()->setViewMatrix(getEffectiveViewOffset(viewer));
+        getCamera()->setProjectionMatrix(getEffectiveFrustum(viewer).getMatrix(osg::Vec2(10, 8e4)));
+        return SlaveCamera::_updateImplementation(viewer);
+    }
+};
+
+Renderer::Renderer()
+{
+}
+
+Renderer::~Renderer()
+{
+}
+
+Drawable*
+Renderer::createDrawable(Viewer&, const std::string& name)
+{
+    return new Drawable(name);
+}
+
+SlaveCamera*
+Renderer::createSlaveCamera(Viewer&, const std::string& name)
+{
+    return new _SlaveCamera(name);
+}
+
+bool
+Renderer::realize(Viewer& viewer)
+{
+    if (!viewer.realizeDrawables())
+        return false;
+    return viewer.realizeSlaveCameras();
+}
+
+bool
+Renderer::update(Viewer& viewer)
+{
+    return viewer.updateSlaveCameras();
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/Renderer.hxx b/utils/fgviewer/Renderer.hxx
new file mode 100644 (file)
index 0000000..40d7e5d
--- /dev/null
@@ -0,0 +1,52 @@
+// Viewer.hxx -- alternative flightgear viewer application
+//
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef _FGVIEWER_RENDERER_HXX
+#define _FGVIEWER_RENDERER_HXX
+
+#include <string>
+#include <simgear/structure/SGWeakReferenced.hxx>
+
+namespace fgviewer  {
+
+class Drawable;
+class Viewer;
+class SlaveCamera;
+
+/// Default renderer, doing fixed function work
+class Renderer : public SGWeakReferenced {
+public:
+    Renderer();
+    virtual ~Renderer();
+
+    virtual Drawable* createDrawable(Viewer& viewer, const std::string& name);
+    virtual SlaveCamera* createSlaveCamera(Viewer& viewer, const std::string& name);
+
+    virtual bool realize(Viewer& viewer);
+    virtual bool update(Viewer& viewer);
+
+private:
+    Renderer(const Renderer&);
+    Renderer& operator=(const Renderer&);
+
+    class _SlaveCamera;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/SlaveCamera.cxx b/utils/fgviewer/SlaveCamera.cxx
new file mode 100644 (file)
index 0000000..41fc516
--- /dev/null
@@ -0,0 +1,349 @@
+// Viewer.hxx -- alternative flightgear viewer application
+//
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "SlaveCamera.hxx"
+
+#include <simgear/scene/util/OsgMath.hxx>
+
+#include "Viewer.hxx"
+
+#ifdef FG_HAVE_HLA
+#include "HLAViewerFederate.hxx"    
+#include "HLAPerspectiveViewer.hxx"    
+#endif
+
+namespace fgviewer  {
+
+class NoUpdateCallback : public osg::NodeCallback {
+public:
+    virtual ~NoUpdateCallback()
+    { }
+    virtual void operator()(osg::Node* node, osg::NodeVisitor* nodeVisitor)
+    { }
+};
+
+SlaveCamera::SlaveCamera(const std::string& name) :
+    _name(name),
+    _viewport(new osg::Viewport())
+{
+    _referencePointMap["lowerLeft"] = osg::Vec2(-1, -1);
+    _referencePointMap["lowerRight"] = osg::Vec2(1, -1);
+    _referencePointMap["upperRight"] = osg::Vec2(1, 1);
+    _referencePointMap["upperLeft"] = osg::Vec2(-1, 1);
+}
+
+SlaveCamera::~SlaveCamera()
+{
+}
+
+bool
+SlaveCamera::setDrawableName(const std::string& drawableName)
+{
+    if (_camera.valid())
+        return false;
+    _drawableName = drawableName;
+    return true;
+}
+
+bool
+SlaveCamera::setViewport(const SGVec4i& viewport)
+{
+    _viewport->setViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+    _frustum.setAspectRatio(getAspectRatio());
+    return true;
+}
+
+bool
+SlaveCamera::setViewOffset(const osg::Matrix& viewOffset)
+{
+    _viewOffset = viewOffset;
+    return true;
+}
+
+bool
+SlaveCamera::setViewOffsetDeg(double headingDeg, double pitchDeg, double rollDeg)
+{
+    osg::Matrix viewOffset = osg::Matrix::identity();
+    viewOffset.postMultRotate(osg::Quat(SGMiscd::deg2rad(headingDeg), osg::Vec3(0, 1, 0)));
+    viewOffset.postMultRotate(osg::Quat(SGMiscd::deg2rad(pitchDeg), osg::Vec3(-1, 0, 0)));
+    viewOffset.postMultRotate(osg::Quat(SGMiscd::deg2rad(rollDeg), osg::Vec3(0, 0, 1)));
+    return setViewOffset(viewOffset);
+}
+
+bool
+SlaveCamera::setFrustum(const Frustum& frustum)
+{
+    _frustum = frustum;
+    return true;
+}
+
+void
+SlaveCamera::setFustumByFieldOfViewDeg(double fieldOfViewDeg)
+{
+    Frustum frustum(getAspectRatio());
+    frustum.setFieldOfViewDeg(fieldOfViewDeg);
+    setFrustum(frustum);
+}
+
+bool
+SlaveCamera::setRelativeFrustum(const std::string names[2], const SlaveCamera& referenceCameraData,
+                                const std::string referenceNames[2])
+{
+    // Track the way from one projection space to the other:
+    // We want
+    //  P = T2*S*T*P0
+    // where P0 is the projection template sensible for the given window size,
+    // S a scale matrix and T is a translation matrix.
+    // We need to determine T and S so that the reference points in the parents
+    // projection space match the two reference points in this cameras projection space.
+    
+    // Starting from the parents camera projection space, we get into this cameras
+    // projection space by the transform matrix:
+    //  P*R*inv(pP*pR) = T2*S*T*P0*R*inv(pP*pR)
+    // So, at first compute that matrix without T2*S*T and determine S and T* from that
+    
+    // The initial projeciton matrix to build upon
+    osg::Matrix P = Frustum(getAspectRatio()).getMatrix();
+
+    osg::Matrix R = getViewOffset();
+    osg::Matrix pP = referenceCameraData.getFrustum().getMatrix();
+    osg::Matrix pR = referenceCameraData.getViewOffset();
+    
+    // Transform from the reference cameras projection space into this cameras eye space.
+    osg::Matrix pPtoEye = osg::Matrix::inverse(pR*pP)*R;
+    
+    osg::Vec2 pRef[2] = {
+        referenceCameraData.getProjectionReferencePoint(referenceNames[0]),
+        referenceCameraData.getProjectionReferencePoint(referenceNames[1])
+    };
+    
+    // The first reference point transformed to this cameras projection space
+    osg::Vec3d pRefInThis0 = P.preMult(pPtoEye.preMult(osg::Vec3d(pRef[0], 1)));
+    // Translate this proejction matrix so that the first reference point is at the origin
+    P.postMultTranslate(-pRefInThis0);
+    
+    // Transform the second reference point and get the scaling correct.
+    osg::Vec3d pRefInThis1 = P.preMult(pPtoEye.preMult(osg::Vec3d(pRef[1], 1)));
+    double s = osg::Vec2d(pRefInThis1[0], pRefInThis1[1]).length();
+    if (s <= std::numeric_limits<double>::min())
+        return false;
+    osg::Vec2 ref[2] = {
+        getProjectionReferencePoint(names[0]),
+        getProjectionReferencePoint(names[1])
+    };
+    s = (ref[0] - ref[1]).length()/s;
+    P.postMultScale(osg::Vec3d(s, s, 1));
+    
+    // The first reference point still maps to the origin in this projection space.
+    // Translate the origin to the desired first reference point.
+    P.postMultTranslate(osg::Vec3d(ref[0], 1));
+    
+    // Now osg::Matrix::inverse(pR*pP)*R*P should map pRef[i] exactly onto ref[i] for i = 0, 1.
+    // Note that osg::Matrix::inverse(pR*pP)*R*P should exactly map pRef[0] at the near plane
+    // to ref[0] at the near plane. The far plane is not taken care of.
+    
+    Frustum frustum;
+    if (!frustum.setMatrix(P))
+        return false;
+
+    return setFrustum(frustum);
+}
+
+void
+SlaveCamera::setProjectionReferencePoint(const std::string& name, const osg::Vec2& point)
+{
+    _referencePointMap[name] = point;
+}
+
+osg::Vec2
+SlaveCamera::getProjectionReferencePoint(const std::string& name) const
+{
+    NameReferencePointMap::const_iterator i = _referencePointMap.find(name);
+    if (i != _referencePointMap.end())
+        return i->second;
+    return osg::Vec2(0, 0);
+}
+
+void
+SlaveCamera::setMonitorProjectionReferences(double width, double height,
+                                            double bezelTop, double bezelBottom,
+                                            double bezelLeft, double bezelRight)
+{
+    double left = 1 + 2*bezelLeft/width;
+    double right = 1 + 2*bezelRight/width;
+    
+    double bottom = 1 + 2*bezelBottom/height;
+    double top = 1 + 2*bezelTop/height;
+
+    setProjectionReferencePoint("lowerLeft", osg::Vec2(-left, -bottom));
+    setProjectionReferencePoint("lowerRight", osg::Vec2(right, -bottom));
+    setProjectionReferencePoint("upperRight", osg::Vec2(right, top));
+    setProjectionReferencePoint("upperLeft", osg::Vec2(-left, top));
+}
+   
+osg::Vec3
+SlaveCamera::getLeftEyeOffset(const Viewer& viewer) const
+{
+#ifdef FG_HAVE_HLA
+    const HLAViewerFederate* viewerFederate = viewer.getViewerFederate();
+    if (!viewerFederate)
+        return osg::Vec3(0, 0, 0);
+    const HLAPerspectiveViewer* perspectiveViewer = viewerFederate->getViewer();
+    if (!perspectiveViewer)
+        return osg::Vec3(0, 0, 0);
+    return toOsg(perspectiveViewer->getLeftEyeOffset());
+#else
+    return osg::Vec3(0, 0, 0);
+#endif
+}
+
+osg::Vec3
+SlaveCamera::getRightEyeOffset(const Viewer& viewer) const
+{
+#ifdef FG_HAVE_HLA
+    const HLAViewerFederate* viewerFederate = viewer.getViewerFederate();
+    if (!viewerFederate)
+        return osg::Vec3(0, 0, 0);
+    const HLAPerspectiveViewer* perspectiveViewer = viewerFederate->getViewer();
+    if (!perspectiveViewer)
+        return osg::Vec3(0, 0, 0);
+    return toOsg(perspectiveViewer->getRightEyeOffset());
+#else
+    return osg::Vec3(0, 0, 0);
+#endif
+}
+
+double
+SlaveCamera::getZoomFactor(const Viewer& viewer) const
+{
+#ifdef FG_HAVE_HLA
+    const HLAViewerFederate* viewerFederate = viewer.getViewerFederate();
+    if (!viewerFederate)
+        return 1;
+    const HLAPerspectiveViewer* perspectiveViewer = viewerFederate->getViewer();
+    if (!perspectiveViewer)
+        return 1;
+    return perspectiveViewer->getZoomFactor();
+#else
+    return 1;
+#endif
+}
+
+osg::Matrix
+SlaveCamera::getEffectiveViewOffset(const Viewer& viewer) const
+{
+    // The eye offset in the master cameras coordinates.
+    osg::Vec3 eyeOffset = getLeftEyeOffset(viewer);
+
+    // Transform the eye offset into this slaves coordinates
+    eyeOffset = eyeOffset*getViewOffset();
+    
+    // The slaves view matrix is composed of the master matrix
+    osg::Matrix viewOffset = viewer.getCamera()->getViewMatrix();
+    // ... its view offset ...
+    viewOffset.postMult(getViewOffset());
+    // ... and the inverse of the eye offset that is required
+    // to keep the world at the same position wrt the projection walls
+    viewOffset.postMultTranslate(-eyeOffset);
+    return viewOffset;
+}
+
+Frustum
+SlaveCamera::getEffectiveFrustum(const Viewer& viewer) const
+{
+    // The eye offset in the master cameras coordinates.
+    osg::Vec3 eyeOffset = getLeftEyeOffset(viewer);
+    
+    // Transform the eye offset into this slaves coordinates
+    eyeOffset = eyeOffset*getViewOffset();
+    
+    /// FIXME read that from external
+    osg::Vec3 zoomScaleCenter(0, 0, -1);
+    double zoomFactor = getZoomFactor(viewer);
+    
+    /// Transform into the local cameras orientation.
+    zoomScaleCenter = getViewOffset().preMult(zoomScaleCenter);
+
+    // The unmodified frustum
+    Frustum frustum = getFrustum();
+
+    // For unresized views this is a noop
+    frustum.setAspectRatio(getAspectRatio());
+
+    // need to correct this for the eye position within the projection system
+    frustum.translate(-eyeOffset);
+
+    // Scale the whole geometric extent of the projection surfaces by the zoom factor
+    frustum.scale(1/zoomFactor, zoomScaleCenter);
+    
+    return frustum;
+}
+
+bool
+SlaveCamera::realize(Viewer& viewer)
+{
+    if (_camera.valid())
+        return false;
+    _camera = _realizeImplementation(viewer);
+    return _camera.valid();
+}
+    
+bool
+SlaveCamera::update(Viewer& viewer)
+{
+    return _updateImplementation(viewer);
+}
+    
+osg::Camera*
+SlaveCamera::_realizeImplementation(Viewer& viewer)
+{
+    Drawable* drawable = viewer.getDrawable(_drawableName);
+    if (!drawable)
+        return 0;
+    osg::GraphicsContext* graphicsContext = drawable->getGraphicsContext();
+    if (!graphicsContext)
+        return 0;
+
+    osg::Camera* camera = new osg::Camera;
+    camera->setName(getName());
+    camera->setGraphicsContext(graphicsContext);
+    camera->setViewport(_viewport.get());
+    camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
+    
+    // Not seriously consider someting different
+    camera->setDrawBuffer(GL_BACK);
+    camera->setReadBuffer(GL_BACK);
+
+    camera->setUpdateCallback(new NoUpdateCallback);
+    
+    return camera;
+}
+
+bool
+SlaveCamera::_updateImplementation(Viewer& viewer)
+{
+    if (!_camera.valid())
+        return false;
+    return true;
+}
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/SlaveCamera.hxx b/utils/fgviewer/SlaveCamera.hxx
new file mode 100644 (file)
index 0000000..8ef1e10
--- /dev/null
@@ -0,0 +1,114 @@
+// Viewer.hxx -- alternative flightgear viewer application
+//
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef _fgviewer_SlaveCamera_hxx
+#define _fgviewer_SlaveCamera_hxx
+
+#include <string>
+#include <osg/Camera>
+#include <simgear/math/SGMath.hxx>
+#include <simgear/structure/SGWeakReferenced.hxx>
+
+#include "Frustum.hxx"
+
+namespace fgviewer  {
+
+class Viewer;
+
+class SlaveCamera : public SGWeakReferenced {
+public:
+    SlaveCamera(const std::string& name);
+    virtual ~SlaveCamera();
+    
+    const std::string& getName() const
+    { return _name; }
+
+    /// The drawable this camera renders to
+    bool setDrawableName(const std::string& drawableName);
+    const std::string& getDrawableName() const
+    { return _drawableName; }
+    
+    /// The viewport into the above drawable
+    virtual bool setViewport(const SGVec4i& viewport);
+    SGVec4i getViewport() const
+    { return SGVec4i(_viewport->x(), _viewport->y(), _viewport->width(), _viewport->height()); }
+    double getAspectRatio() const
+    { return _viewport->aspectRatio(); }
+    
+    /// The view offset, usually an orientation offset
+    virtual bool setViewOffset(const osg::Matrix& viewOffset);
+    const osg::Matrix& getViewOffset() const
+    { return _viewOffset; }
+    bool setViewOffsetDeg(double headingDeg, double pitchDeg, double rollDeg);
+    
+    /// The frustum for this camera
+    virtual bool setFrustum(const Frustum& frustum);
+    const Frustum& getFrustum() const
+    { return _frustum; }
+    void setFustumByFieldOfViewDeg(double fieldOfViewDeg);
+    bool setRelativeFrustum(const std::string names[2], const SlaveCamera& referenceCameraData,
+                            const std::string referenceNames[2]);
+
+    /// For relative cameras configure the reference points that should match
+    void setProjectionReferencePoint(const std::string& name, const osg::Vec2& point);
+    osg::Vec2 getProjectionReferencePoint(const std::string& name) const;
+    /// Set the reference points for a monitor configuration
+    void setMonitorProjectionReferences(double width, double height,
+                                        double bezelTop, double bezelBottom,
+                                        double bezelLeft, double bezelRight);
+
+    /// Access parameters of this view/camera
+    osg::Vec3 getLeftEyeOffset(const Viewer& viewer) const;
+    osg::Vec3 getRightEyeOffset(const Viewer& viewer) const;
+    double getZoomFactor(const Viewer& viewer) const;
+    osg::Matrix getEffectiveViewOffset(const Viewer& viewer) const;
+    Frustum getEffectiveFrustum(const Viewer& viewer) const;
+
+    /// The top level camera holding the context
+    osg::Camera* getCamera()
+    { return _camera.get(); }
+    
+    /// Top level entry points
+    bool realize(Viewer& viewer);
+    bool update(Viewer& viewer);
+    
+protected:
+    virtual osg::Camera* _realizeImplementation(Viewer& viewer);
+    virtual bool _updateImplementation(Viewer& viewer);
+    
+private:
+    SlaveCamera(const SlaveCamera&);
+    SlaveCamera& operator=(const SlaveCamera&);
+
+    /// The immutable name that is used to reference this slave camera.
+    const std::string _name;
+    std::string _drawableName;
+    osg::ref_ptr<osg::Viewport> _viewport;
+    osg::Matrix _viewOffset;
+    Frustum _frustum;
+    /// The camera that is attached to the slave and that has a context attached.
+    osg::ref_ptr<osg::Camera> _camera;
+
+    /// For relative views, the named reference points in the projection space
+    typedef std::map<std::string, osg::Vec2> NameReferencePointMap;
+    NameReferencePointMap _referencePointMap;
+};
+
+} // namespace fgviewer
+
+#endif
diff --git a/utils/fgviewer/Viewer.cxx b/utils/fgviewer/Viewer.cxx
new file mode 100644 (file)
index 0000000..090de9e
--- /dev/null
@@ -0,0 +1,763 @@
+// Viewer.cxx -- alternative flightgear viewer application
+//
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "Viewer.hxx"
+
+#include <osg/ArgumentParser>
+#include <osg/ProxyNode>
+#include <osg/PagedLOD>
+#include <osgDB/ReadFile>
+
+#ifdef __linux__
+#include <X11/Xlib.h>
+#include <osgViewer/api/X11/GraphicsWindowX11>
+#endif
+
+#include "MEncoderCaptureOperation.hxx"
+
+namespace fgviewer  {
+
+Viewer::Viewer(osg::ArgumentParser& arguments) :
+    osgViewer::Viewer(arguments),
+    _sceneDataGroup(new osg::Group),
+    _timeIncrement(SGTimeStamp::fromSec(0)),
+    _simTime(SGTimeStamp::fromSec(0))
+{
+    /// Careful: this method really assigns the sceneDataGroup to all cameras!
+    /// FIXME the 'useMasterScene' flag at the slave is able to get around that!!!
+    osgViewer::Viewer::setSceneData(_sceneDataGroup.get());
+    /// The only changed default that is renderer independent ...
+    getCamera()->setClearColor(osg::Vec4(0, 0, 0, 0));
+}
+
+Viewer::~Viewer()
+{
+    stopThreading();
+
+#ifdef FG_HAVE_HLA
+    if (_viewerFederate.valid())
+        _viewerFederate->shutdown();
+    _viewerFederate = 0;
+#endif
+}
+
+bool
+Viewer::readCameraConfig(const SGPropertyNode& viewerNode)
+{
+    // Collect and realize all windows
+    for (int i = 0; i < viewerNode.nChildren(); ++i) {
+        // FIXME support window, fullscreen, offscreen
+        const SGPropertyNode* windowNode = viewerNode.getChild(i);
+        if (!windowNode || windowNode->getNameString() != "window")
+            continue;
+
+        std::string name = windowNode->getStringValue("name", "");
+        if (name.empty()) {
+            SG_LOG(SG_VIEW, SG_ALERT, "Ignoring unnamed window!");
+            return false;
+        }
+
+        Drawable* drawable = getOrCreateDrawable(name);
+
+        osg::GraphicsContext::ScreenIdentifier screenIdentifier;
+        screenIdentifier = getScreenIdentifier(windowNode->getStringValue("display", ""));
+        drawable->setScreenIdentifier(screenIdentifier.displayName());
+
+        if (windowNode->getBoolValue("fullscreen", false)) {
+            osg::GraphicsContext::ScreenSettings screenSettings;
+            screenSettings = getScreenSettings(screenIdentifier);
+            drawable->setPosition(SGVec2i(0, 0));
+            drawable->setSize(SGVec2i(screenSettings.width, screenSettings.height));
+            drawable->setFullscreen(true);
+            drawable->setOffscreen(false);
+
+        } else if (windowNode->getBoolValue("video", false)) {
+            drawable->setPosition(SGVec2i(0, 0));
+            SGVec2i size;
+            size[0] = windowNode->getIntValue("geometry/width", 1366);
+            size[1] = windowNode->getIntValue("geometry/height", 768);
+            drawable->setSize(size);
+            drawable->setFullscreen(true);
+            drawable->setOffscreen(true);
+
+            std::string outputFile = windowNode->getStringValue("output-file", "fgviewer.avi");
+            unsigned fps = windowNode->getIntValue("frames-per-second", 30);
+
+            /// This is the case for the video writers, have a fixed time increment
+            _timeIncrement = SGTimeStamp::fromSec(1.0/fps);
+
+            MEncoderCaptureOperation* captureOperation;
+            captureOperation = new MEncoderCaptureOperation(outputFile, fps);
+            osgViewer::ScreenCaptureHandler* captureHandler;
+            captureHandler = new osgViewer::ScreenCaptureHandler(captureOperation, -1);
+            addEventHandler(captureHandler);
+            captureHandler->startCapture();
+
+        } else {
+
+            SGVec2i position;
+            position[0] = windowNode->getIntValue("geometry/x", 0);
+            position[1] = windowNode->getIntValue("geometry/y", 0);
+            drawable->setPosition(position);
+            SGVec2i size;
+            size[0] = windowNode->getIntValue("geometry/width", 1366);
+            size[1] = windowNode->getIntValue("geometry/height", 768);
+            drawable->setSize(size);
+            drawable->setFullscreen(false);
+            drawable->setOffscreen(false);
+        }
+    }
+
+    for (int i = 0; i < viewerNode.nChildren(); ++i) {
+        const SGPropertyNode* cameraNode = viewerNode.getChild(i);
+        if (!cameraNode || cameraNode->getNameString() != "camera")
+            continue;
+
+        std::string name = cameraNode->getStringValue("name", "");
+        if (name.empty()) {
+            SG_LOG(SG_VIEW, SG_ALERT, "Camera configuration needs a name!");
+            return false;
+        }
+
+        SlaveCamera* slaveCamera = getOrCreateSlaveCamera(name);
+
+        std::string drawableName = cameraNode->getStringValue("window", "");
+        if (drawableName.empty()) {
+            SG_LOG(SG_VIEW, SG_ALERT, "Camera configuration needs an assigned window!");
+            return false;
+        }
+        Drawable* drawable = getDrawable(drawableName);
+        if (!drawable) {
+            SG_LOG(SG_VIEW, SG_ALERT, "Camera configuration \"" << name << "\" needs a drawable configured!");
+            return false;
+        }
+        slaveCamera->setDrawableName(drawableName);
+        drawable->attachSlaveCamera(slaveCamera);
+
+        SGVec2i size = drawable->getSize();
+        SGVec4i viewport(0, 0, size[0], size[1]);
+        viewport[0] = cameraNode->getIntValue("viewport/x", viewport[0]);
+        viewport[1] = cameraNode->getIntValue("viewport/y", viewport[1]);
+        viewport[2] = cameraNode->getIntValue("viewport/width", viewport[2]);
+        viewport[3] = cameraNode->getIntValue("viewport/height", viewport[3]);
+        slaveCamera->setViewport(viewport);
+
+        double headingDeg = cameraNode->getDoubleValue("view-offset/heading-deg", 0);
+        double pitchDeg = cameraNode->getDoubleValue("view-offset/pitch-deg", 0);
+        double rollDeg = cameraNode->getDoubleValue("view-offset/roll-deg", 0);
+        slaveCamera->setViewOffsetDeg(headingDeg, pitchDeg, rollDeg);
+
+        // Care for the reference points
+        if (const SGPropertyNode* referencePointsNode = cameraNode->getNode("reference-points")) {
+            for (int j = 0; j < referencePointsNode->nChildren(); ++j) {
+                const SGPropertyNode* referencePointNode = cameraNode->getNode("reference-point");
+                if (!referencePointNode)
+                    continue;
+                std::string name = referencePointNode->getStringValue("name", "");
+                if (name.empty())
+                    continue;
+                osg::Vec2 point;
+                point[0] = referencePointNode->getDoubleValue("x", 0);
+                point[1] = referencePointNode->getDoubleValue("y", 0);
+                slaveCamera->setProjectionReferencePoint(name, point);
+            }
+        }
+        // Define 4 reference points by monitor dimensions
+        else if (const SGPropertyNode* physicalDimensionsNode = cameraNode->getNode("physical-dimensions")) {
+            double physicalWidth = physicalDimensionsNode->getDoubleValue("width", viewport[2]);
+            double physicalHeight = physicalDimensionsNode->getDoubleValue("height", viewport[3]);
+            if (const SGPropertyNode* bezelNode = physicalDimensionsNode->getNode("bezel")) {
+                double bezelHeightTop = bezelNode->getDoubleValue("top", 0);
+                double bezelHeightBottom = bezelNode->getDoubleValue("bottom", 0);
+                double bezelWidthLeft = bezelNode->getDoubleValue("left", 0);
+                double bezelWidthRight = bezelNode->getDoubleValue("right", 0);
+                slaveCamera->setMonitorProjectionReferences(physicalWidth, physicalHeight,
+                                                            bezelHeightTop, bezelHeightBottom,
+                                                            bezelWidthLeft, bezelWidthRight);
+            }
+        }
+
+        // The frustum node takes precedence, as this is the most explicit one.
+        if (const SGPropertyNode* frustumNode = cameraNode->getNode("frustum")) {
+            Frustum frustum(slaveCamera->getAspectRatio());
+            frustum._near = frustumNode->getDoubleValue("near", frustum._near);
+            frustum._left = frustumNode->getDoubleValue("left", frustum._left);
+            frustum._right = frustumNode->getDoubleValue("right", frustum._right);
+            frustum._bottom = frustumNode->getDoubleValue("bottom", frustum._bottom);
+            frustum._top = frustumNode->getDoubleValue("top", frustum._top);
+            slaveCamera->setFrustum(frustum);
+
+        } else if (const SGPropertyNode* perspectiveNode = cameraNode->getNode("perspective")) {
+            double fieldOfViewDeg = perspectiveNode->getDoubleValue("field-of-view-deg", 55);
+            slaveCamera->setFustumByFieldOfViewDeg(fieldOfViewDeg);
+
+        } else if (const SGPropertyNode* monitorNode = cameraNode->getNode("monitor")) {
+
+            std::string referenceCameraName;
+            std::string names[2];
+            std::string referenceNames[2];
+
+            // FIXME??!!
+            if (const SGPropertyNode* leftOfNode = monitorNode->getNode("left-of")) {
+                referenceCameraName = leftOfNode->getStringValue("");
+                names[0] = "lowerRight";
+                referenceNames[0] = "lowerLeft";
+                names[1] = "upperRight";
+                referenceNames[1] = "upperLeft";
+            } else if (const SGPropertyNode* rightOfNode = monitorNode->getNode("right-of")) {
+                referenceCameraName = rightOfNode->getStringValue("");
+                names[0] = "lowerLeft";
+                referenceNames[0] = "lowerRight";
+                names[1] = "upperLeft";
+                referenceNames[1] = "upperRight";
+            } else if (const SGPropertyNode* aboveNode = monitorNode->getNode("above")) {
+                referenceCameraName = aboveNode->getStringValue("");
+                names[0] = "lowerLeft";
+                referenceNames[0] = "upperLeft";
+                names[1] = "lowerRight";
+                referenceNames[1] = "upperRight";
+            } else if (const SGPropertyNode* belowNode = monitorNode->getNode("below")) {
+                referenceCameraName = belowNode->getStringValue("");
+                names[0] = "upperLeft";
+                referenceNames[0] = "lowerLeft";
+                names[1] = "upperRight";
+                referenceNames[1] = "lowerRight";
+            } else {
+                // names[0] = ;
+                // referenceNames[0] = ;
+                // names[1] = ;
+                // referenceNames[1] = ;
+            }
+
+            // If we finally found a set of reference points that should match,
+            // then create a relative frustum matching these references
+            if (SlaveCamera* referenceSlaveCamera = getSlaveCamera(referenceCameraName)) {
+                slaveCamera->setRelativeFrustum(names, *referenceSlaveCamera, referenceNames);
+            } else {
+                SG_LOG(SG_VIEW, SG_ALERT, "Unable to find reference camera \"" << referenceCameraName
+                       << "\" for camera \"" << name << "\"!");
+            }
+        } else {
+            // Set a proper default taking the current aspect ratio into account
+            slaveCamera->setFustumByFieldOfViewDeg(55);
+        }
+    }
+
+    return true;
+}
+
+void
+Viewer::setupDefaultCameraConfigIfUnset()
+{
+    if (getNumDrawables() || getNumSlaveCameras())
+        return;
+
+    osg::GraphicsContext::ScreenIdentifier screenIdentifier;
+    screenIdentifier = getDefaultScreenIdentifier();
+
+    Drawable* drawable = getOrCreateDrawable("fgviewer");
+    drawable->setScreenIdentifier(screenIdentifier.displayName());
+    drawable->setPosition(SGVec2i(0, 0));
+    SGVec2i size(800, 600);
+    drawable->setSize(size);
+    drawable->setFullscreen(false);
+    drawable->setOffscreen(false);
+
+    SlaveCamera* slaveCamera = getOrCreateSlaveCamera(drawable->getName());
+    slaveCamera->setDrawableName(drawable->getName());
+    drawable->attachSlaveCamera(slaveCamera);
+    slaveCamera->setViewport(SGVec4i(0, 0, size[0], size[1]));
+    slaveCamera->setViewOffset(osg::Matrix::identity());
+    slaveCamera->setFustumByFieldOfViewDeg(55);
+}
+
+bool
+Viewer::readConfiguration(const std::string&)
+{
+    return false;
+}
+
+void
+Viewer::setRenderer(Renderer* renderer)
+{
+    if (!renderer) {
+        SG_LOG(SG_VIEW, SG_ALERT, "Viewer::setRenderer(): Setting the renderer to zero is not supported!");
+        return;
+    }
+    if (_renderer.valid()) {
+        SG_LOG(SG_VIEW, SG_ALERT, "Viewer::setRenderer(): Setting the renderer twice is not supported!");
+        return;
+    }
+    _renderer = renderer;
+}
+
+Renderer*
+Viewer::getRenderer()
+{
+    return _renderer.get();
+}
+
+Drawable*
+Viewer::getOrCreateDrawable(const std::string& name)
+{
+    Drawable* drawable = getDrawable(name);
+    if (drawable)
+        return drawable;
+    if (!_renderer.valid())
+        return 0;
+    drawable = _renderer->createDrawable(*this, name);
+    if (!drawable)
+        return 0;
+    _drawableVector.push_back(drawable);
+    return drawable;
+}
+
+Drawable*
+Viewer::getDrawable(const std::string& name)
+{
+    return getDrawable(getDrawableIndex(name));
+}
+
+unsigned
+Viewer::getDrawableIndex(const std::string& name)
+{
+    for (DrawableVector::size_type i = 0; i < _drawableVector.size(); ++i) {
+        if (_drawableVector[i]->getName() == name)
+            return i;
+    }
+    return ~0u;
+}
+
+Drawable*
+Viewer::getDrawable(unsigned index)
+{
+    if (_drawableVector.size() <= index)
+        return 0;
+    return _drawableVector[index].get();
+}
+
+unsigned
+Viewer::getNumDrawables() const
+{
+    return _drawableVector.size();
+}
+
+SlaveCamera*
+Viewer::getOrCreateSlaveCamera(const std::string& name)
+{
+    SlaveCamera* slaveCamera = getSlaveCamera(name);
+    if (slaveCamera)
+        return slaveCamera;
+    if (!_renderer.valid())
+        return 0;
+    slaveCamera = _renderer->createSlaveCamera(*this, name);
+    if (!slaveCamera)
+        return 0;
+    _slaveCameraVector.push_back(slaveCamera);
+    return slaveCamera;
+}
+
+SlaveCamera*
+Viewer::getSlaveCamera(const std::string& name)
+{
+    return getSlaveCamera(getSlaveCameraIndex(name));
+}
+
+unsigned
+Viewer::getSlaveCameraIndex(const std::string& name)
+{
+    for (SlaveCameraVector::size_type i = 0; i < _slaveCameraVector.size(); ++i) {
+        if (_slaveCameraVector[i]->getName() == name)
+            return i;
+    }
+    return ~0u;
+}
+
+SlaveCamera*
+Viewer::getSlaveCamera(unsigned index)
+{
+    if (_slaveCameraVector.size() <= index)
+        return 0;
+    return _slaveCameraVector[index].get();
+}
+
+unsigned
+Viewer::getNumSlaveCameras() const
+{
+    return _slaveCameraVector.size();
+}
+
+void
+Viewer::realize()
+{
+    if (isRealized())
+        return;
+
+    if (!_renderer.valid())
+        return;
+
+    // Setup a default config if there is none
+    setupDefaultCameraConfigIfUnset();
+
+    // Realize
+    if (!_renderer->realize(*this)) {
+        SG_LOG(SG_VIEW, SG_ALERT, "Renderer::realize() failed!");
+        return;
+    }
+
+    osgViewer::Viewer::realize();
+}
+
+bool
+Viewer::realizeDrawables()
+{
+    for (DrawableVector::iterator i = _drawableVector.begin(); i != _drawableVector.end(); ++i) {
+        if (!(*i)->realize(*this)) {
+            SG_LOG(SG_VIEW, SG_ALERT, "Unable to realize drawable \"" << (*i)->getName() << "\"!");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool
+Viewer::realizeSlaveCameras()
+{
+    for (SlaveCameraVector::iterator i = _slaveCameraVector.begin(); i != _slaveCameraVector.end(); ++i) {
+        if (!(*i)->realize(*this)) {
+            SG_LOG(SG_VIEW, SG_ALERT, "Unable to realize camera \"" << (*i)->getName() << "\"!");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void
+Viewer::advance(double)
+{
+    if (_timeIncrement == SGTimeStamp::fromSec(0)) {
+        // Flightgears current scheme - could be improoved
+        _simTime = SGTimeStamp::now();
+    } else {
+        // Giving an explicit time increment makes sense in presence
+        // of the video capture where we need deterministic
+        // frame times and object positions for each picture.
+        _simTime += _timeIncrement;
+    }
+
+    // This sets the frame stamps simulation time to simTime
+    // and schedules a frame event
+    osgViewer::Viewer::advance(_simTime.toSecs());
+}
+
+void
+Viewer::updateTraversal()
+{
+#ifdef FG_HAVE_HLA
+    if (_viewerFederate.valid()) {
+        if (_timeIncrement == SGTimeStamp::fromSec(0)) {
+            if (!_viewerFederate->timeAdvanceAvailable()) {
+                SG_LOG(SG_NETWORK, SG_ALERT, "Got error from federate update!");
+                _viewerFederate->shutdown();
+                _viewerFederate = 0;
+            }
+        } else {
+            osg::FrameStamp* frameStamp = getViewerFrameStamp();
+            SGTimeStamp timeStamp = SGTimeStamp::fromSec(frameStamp->getSimulationTime());
+            if (!_viewerFederate->timeAdvance(timeStamp)) {
+                SG_LOG(SG_NETWORK, SG_ALERT, "Got error from federate update!");
+                _viewerFederate->shutdown();
+                _viewerFederate = 0;
+            }
+        }
+    }
+#endif
+
+    osgViewer::Viewer::updateTraversal();
+
+    if (!_renderer->update(*this)) {
+        SG_LOG(SG_VIEW, SG_ALERT, "Renderer::update() failed!");
+    }
+}
+
+bool
+Viewer::updateSlaveCameras()
+{
+    for (SlaveCameraVector::iterator i = _slaveCameraVector.begin(); i != _slaveCameraVector.end(); ++i) {
+        if (!(*i)->update(*this)) {
+            SG_LOG(SG_VIEW, SG_ALERT, "SlaveCamera::update() failed!");
+            return false;
+        }
+    }
+    return true;
+}
+
+void
+Viewer::setReaderWriterOptions(simgear::SGReaderWriterOptions* readerWriterOptions)
+{
+    _readerWriterOptions = readerWriterOptions;
+}
+
+simgear::SGReaderWriterOptions*
+Viewer::getReaderWriterOptions()
+{
+    return _readerWriterOptions.get();
+}
+
+void
+Viewer::setSceneData(osg::Node* node)
+{
+    _sceneDataGroup->removeChildren(0, _sceneDataGroup->getNumChildren());
+    insertSceneData(node);
+}
+
+void
+Viewer::insertSceneData(osg::Node* node)
+{
+    _sceneDataGroup->addChild(node);
+}
+
+bool
+Viewer::insertSceneData(const std::string& fileName, const osgDB::Options* options)
+{
+#if 0
+    osg::ProxyNode* proxyNode = new osg::ProxyNode;
+    if (options)
+        proxyNode->setDatabaseOptions(options->clone(osg::CopyOp()));
+    else
+        proxyNode->setDatabaseOptions(_readerWriterOptions->clone(osg::CopyOp()));
+    proxyNode->setFileName(0, fileName);
+    insertSceneData(proxyNode);
+    return true;
+#else
+    osg::ref_ptr<osg::Node> node = osgDB::readRefNodeFile(fileName, options);
+    if (!node.valid())
+        return false;
+    insertSceneData(node.get());
+    return true;
+#endif
+}
+
+osg::Group*
+Viewer::getSceneDataGroup()
+{
+    return _sceneDataGroup.get();
+}
+
+class Viewer::_PurgeLevelOfDetailNodesVisitor : public osg::NodeVisitor {
+public:
+    _PurgeLevelOfDetailNodesVisitor() :
+        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
+    { }
+    virtual ~_PurgeLevelOfDetailNodesVisitor()
+    { }
+  
+    virtual void apply(osg::ProxyNode& node)
+    {
+        for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+            if (node.getFileName(i).empty())
+                continue;
+            node.removeChildren(i, node.getNumChildren() - i);
+            break;
+        }
+
+        osg::NodeVisitor::apply(static_cast<osg::Group&>(node));
+    }
+    virtual void apply(osg::PagedLOD& node)
+    {
+        for (unsigned i = 0; i < node.getNumChildren(); ++i) {
+            if (node.getFileName(i).empty())
+                continue;
+            node.removeChildren(i, node.getNumChildren() - i);
+            break;
+        }
+
+        osg::NodeVisitor::apply(static_cast<osg::Group&>(node));
+    }
+};
+
+void
+Viewer::purgeLevelOfDetailNodes()
+{
+    _PurgeLevelOfDetailNodesVisitor purgeLevelOfDetailNodesVisitor;
+    _sceneDataGroup->accept(purgeLevelOfDetailNodesVisitor);
+}
+
+osg::GraphicsContext::ScreenIdentifier
+Viewer::getDefaultScreenIdentifier()
+{
+    osg::GraphicsContext::ScreenIdentifier screenIdentifier;
+    screenIdentifier.readDISPLAY();
+    if (screenIdentifier.displayNum < 0)
+        screenIdentifier.displayNum = 0;
+    if (screenIdentifier.screenNum < 0)
+        screenIdentifier.screenNum = 0;
+    return screenIdentifier;
+}
+
+osg::GraphicsContext::ScreenIdentifier
+Viewer::getScreenIdentifier(const std::string& display)
+{
+    osg::GraphicsContext::ScreenIdentifier screenIdentifier;
+    screenIdentifier.setScreenIdentifier(display);
+
+    osg::GraphicsContext::ScreenIdentifier defaultScreenIdentifier;
+    defaultScreenIdentifier = getDefaultScreenIdentifier();
+    if (screenIdentifier.hostName.empty())
+        screenIdentifier.hostName = defaultScreenIdentifier.hostName;
+    if (screenIdentifier.displayNum < 0)
+        screenIdentifier.displayNum = defaultScreenIdentifier.displayNum;
+    if (screenIdentifier.screenNum < 0)
+        screenIdentifier.screenNum = defaultScreenIdentifier.screenNum;
+    
+    return screenIdentifier;
+}
+
+osg::GraphicsContext::ScreenSettings
+Viewer::getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier)
+{
+    osg::GraphicsContext::ScreenSettings screenSettings;
+
+    osg::GraphicsContext::WindowingSystemInterface* wsi;
+    wsi = osg::GraphicsContext::getWindowingSystemInterface();
+    if (!wsi) {
+        SG_LOG(SG_VIEW, SG_ALERT, "No windowing system interface defined!");
+        return screenSettings;
+    }
+
+    wsi->getScreenSettings(screenIdentifier, screenSettings);
+    return screenSettings;
+}
+
+osg::GraphicsContext::Traits*
+Viewer::getTraits(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier)
+{
+    osg::DisplaySettings* ds = _displaySettings.get();
+    if (!ds)
+        ds = osg::DisplaySettings::instance().get();
+
+    osg::GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits(ds);
+
+    traits->hostName = screenIdentifier.hostName;
+    traits->displayNum = screenIdentifier.displayNum;
+    traits->screenNum = screenIdentifier.screenNum;
+            
+    // not seriously consider something different
+    traits->doubleBuffer = true;
+
+    osg::GraphicsContext::ScreenSettings screenSettings;
+    screenSettings = getScreenSettings(screenIdentifier);
+
+    traits->x = 0;
+    traits->y = 0;
+    traits->width = screenSettings.width;
+    traits->height = screenSettings.height;
+
+    return traits;
+}
+
+#ifdef __linux__
+class Viewer::_ResetScreenSaverSwapCallback : public osg::GraphicsContext::SwapCallback {
+public:
+    _ResetScreenSaverSwapCallback() :
+        _timeStamp(SGTimeStamp::fromSec(0))
+    {
+    }
+    virtual ~_ResetScreenSaverSwapCallback()
+    {
+    }
+    virtual void swapBuffersImplementation(osg::GraphicsContext* graphicsContext)
+    {
+        graphicsContext->swapBuffersImplementation();
+
+        // This callback must be attached to this type of graphics context
+        assert(dynamic_cast<osgViewer::GraphicsWindowX11*>(graphicsContext));
+
+        // Reset the screen saver every 10 seconds
+        SGTimeStamp timeStamp = SGTimeStamp::now();
+        if (timeStamp < _timeStamp)
+            return;
+        _timeStamp = timeStamp + SGTimeStamp::fromSec(10);
+        // Obviously runs in the draw thread. Thus, use the draw display.
+        XResetScreenSaver(static_cast<osgViewer::GraphicsWindowX11*>(graphicsContext)->getDisplay());
+    }
+private:
+    SGTimeStamp _timeStamp;
+};
+#endif
+
+osg::GraphicsContext*
+Viewer::createGraphicsContext(osg::GraphicsContext::Traits* traits)
+{
+    osg::GraphicsContext::WindowingSystemInterface* wsi;
+    wsi = osg::GraphicsContext::getWindowingSystemInterface();
+    if (!wsi) {
+        SG_LOG(SG_VIEW, SG_ALERT, "No windowing system interface defined!");
+        return 0;
+    }
+
+    osg::GraphicsContext* graphicsContext = wsi->createGraphicsContext(traits);
+    if (!graphicsContext) {
+        SG_LOG(SG_VIEW, SG_ALERT, "Unable to create window \"" << traits->windowName << "\"!");
+        return 0;
+    }
+
+#ifdef __linux__
+    if (dynamic_cast<osgViewer::GraphicsWindowX11*>(graphicsContext))
+        graphicsContext->setSwapCallback(new _ResetScreenSaverSwapCallback);
+#endif
+
+    return graphicsContext;
+}
+
+#ifdef FG_HAVE_HLA
+const HLAViewerFederate*
+Viewer::getViewerFederate() const
+{
+    return _viewerFederate.get();
+}
+
+HLAViewerFederate*
+Viewer::getViewerFederate()
+{
+    return _viewerFederate.get();
+}
+
+void
+Viewer::setViewerFederate(HLAViewerFederate* viewerFederate)
+{
+    if (!viewerFederate) {
+        SG_LOG(SG_VIEW, SG_ALERT, "Viewer::setViewerFederate(): Setting the viewer federate to zero is not supported!");
+        return;
+    }
+    if (_viewerFederate.valid()) {
+        SG_LOG(SG_VIEW, SG_ALERT, "Viewer::setViewerFederate(): Setting the viewer federate twice is not supported!");
+        return;
+    }
+    _viewerFederate = viewerFederate;
+    _viewerFederate->attachToViewer(this);
+}
+#endif
+
+} // namespace fgviewer
diff --git a/utils/fgviewer/Viewer.hxx b/utils/fgviewer/Viewer.hxx
new file mode 100644 (file)
index 0000000..9503c44
--- /dev/null
@@ -0,0 +1,158 @@
+// Viewer.hxx -- alternative flightgear viewer application
+//
+// Copyright (C) 2009 - 2012  Mathias Froehlich
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifndef _FGVIEWER_VIEWER_HXX
+#define _FGVIEWER_VIEWER_HXX
+
+#include <osg/ArgumentParser>
+#include <osgViewer/Viewer>
+
+#include <simgear/math/SGMath.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
+#include <simgear/timing/timestamp.hxx>
+#include <simgear/props/props.hxx>
+
+#include "Drawable.hxx"
+#include "Frustum.hxx"
+#include "Renderer.hxx"
+#include "SlaveCamera.hxx"
+
+#ifdef FG_HAVE_HLA
+#include "HLAViewerFederate.hxx"    
+#endif
+
+namespace fgviewer  {
+
+class Viewer : public osgViewer::Viewer {
+public:
+    Viewer(osg::ArgumentParser& arguments);
+    virtual ~Viewer();
+
+    bool readCameraConfig(const SGPropertyNode& viewerNode);
+    void setupDefaultCameraConfigIfUnset();
+    /// Short circuit osg config files.
+    virtual bool readConfiguration(const std::string& filename);
+
+    /// Callback class that cares for the camera and drawable setup
+    void setRenderer(Renderer* renderer);
+    Renderer* getRenderer();
+
+    /// Access and create drawables
+    Drawable* getOrCreateDrawable(const std::string& name);
+    Drawable* getDrawable(const std::string& name);
+    unsigned getDrawableIndex(const std::string& name);
+    Drawable* getDrawable(unsigned index);
+    unsigned getNumDrawables() const;
+
+    /// Access and create slave cameras
+    SlaveCamera* getOrCreateSlaveCamera(const std::string& name);
+    SlaveCamera* getSlaveCamera(const std::string& name);
+    unsigned getSlaveCameraIndex(const std::string& name);
+    SlaveCamera* getSlaveCamera(unsigned index);
+    unsigned getNumSlaveCameras() const;
+
+    /// Realize the contexts and attach the cameras there
+    virtual void realize();
+    bool realizeDrawables();
+    bool realizeSlaveCameras();
+
+    /// exec methods
+    virtual void advance(double simTime);
+    virtual void updateTraversal();
+    bool updateSlaveCameras();
+
+    /// Store this per viewer instead of global.
+    void setReaderWriterOptions(simgear::SGReaderWriterOptions* readerWriterOptions);
+    simgear::SGReaderWriterOptions* getReaderWriterOptions();
+
+    /// Puts the scene data under the renderer.
+    /// Replaces the whole renderer independent scene.
+    virtual void setSceneData(osg::Node* node);
+
+    /// Adds the scene node to the global scene
+    /// Use this to add something to the displayed scene.
+    void insertSceneData(osg::Node* node);
+    bool insertSceneData(const std::string& fileName, const osgDB::Options* options = 0);
+    /// Return the scene data group.
+    osg::Group* getSceneDataGroup();
+
+    /// Traverse the scenegraph and throw out all child nodes that can be loaded again.
+    void purgeLevelOfDetailNodes();
+
+    /// Return a default screen identifier. Under UNIX the default DISPLAY environment variable.
+    static osg::GraphicsContext::ScreenIdentifier getDefaultScreenIdentifier();
+    /// Interpret the given display. Is mergend with the default screen identifier.
+    static osg::GraphicsContext::ScreenIdentifier getScreenIdentifier(const std::string& display);
+    /// Return screen settings, mostly the resolution of the given screen.
+    osg::GraphicsContext::ScreenSettings getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier);
+    /// Return traits struct for the given screen identifier. The size and position is already set up for a fullscreen window.
+    osg::GraphicsContext::Traits* getTraits(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier);
+    /// Helper to create an new graphics context from traits.
+    osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits);
+
+#ifdef FG_HAVE_HLA
+    /// The federate if configured, can only be set once
+    const HLAViewerFederate* getViewerFederate() const;
+    HLAViewerFederate* getViewerFederate();
+    void setViewerFederate(HLAViewerFederate* viewerFederate);
+#endif
+
+private:
+    Viewer(const Viewer&);
+    Viewer& operator=(const Viewer&);
+
+    /// Unload all lod's
+    class _PurgeLevelOfDetailNodesVisitor;
+#ifdef __linux__
+    /// Under linux make sure that the screen saver does not jump in
+    class _ResetScreenSaverSwapCallback;
+#endif
+
+    /// The renderer used to setup the higher level camera/scenegraph structure
+    SGSharedPtr<Renderer> _renderer;
+
+    /// The drawables managed by this viewer.
+    typedef std::vector<SGSharedPtr<Drawable> > DrawableVector;
+    DrawableVector _drawableVector;
+
+    /// The slave cameras for this viewer.
+    /// Since we support more complex renderers, we can not only use osg::View::Slave.
+    typedef std::vector<SGSharedPtr<SlaveCamera> > SlaveCameraVector;
+    SlaveCameraVector _slaveCameraVector;
+
+    /// The top level options struct
+    osg::ref_ptr<simgear::SGReaderWriterOptions> _readerWriterOptions;
+  
+    /// The top level scenegraph structure that is used for drawing
+    osg::ref_ptr<osg::Group> _sceneDataGroup;
+
+    /// Stores the time increment for each frame.
+    /// If zero, the time advance is done to the current real time.
+    SGTimeStamp _timeIncrement;
+    /// The current simulation time of the viewer
+    SGTimeStamp _simTime;
+
+#ifdef FG_HAVE_HLA
+    /// The federate if configured
+    SGSharedPtr<HLAViewerFederate> _viewerFederate;
+#endif
+};
+
+} // namespace fgviewer
+
+#endif
index a23336dab3df08a9b9217acf79de2b572c115b21..1e96dc46b5c53481662bb28286aa476517eadee7 100644 (file)
 #include <config.h>
 #endif
 
-#include <iostream>
-#include <cstdlib>
-
 #include <osg/ArgumentParser>
-#include <osg/Fog>
 #include <osgDB/ReadFile>
-#include <osgViewer/Viewer>
 #include <osgViewer/ViewerEventHandlers>
-#include <osgViewer/Renderer>
 #include <osgGA/KeySwitchMatrixManipulator>
 #include <osgGA/StateSetManipulator>
 #include <osgGA/TrackballManipulator>
@@ -38,7 +32,6 @@
 
 #include <simgear/props/props.hxx>
 #include <simgear/props/props_io.hxx>
-#include <simgear/scene/material/EffectCullVisitor.hxx>
 #include <simgear/scene/material/matlib.hxx>
 #include <simgear/scene/util/SGReaderWriterOptions.hxx>
 #include <simgear/scene/util/SGSceneFeatures.hxx>
 #include <simgear/scene/model/ModelRegistry.hxx>
 #include <simgear/misc/ResourceManager.hxx>
 
+#include "Renderer.hxx"
+#include "Viewer.hxx"
+
+#ifdef FG_HAVE_HLA
+#include "HLACameraManipulator.hxx"
+#include "HLAViewerFederate.hxx"
+#endif
+
+
 int
 main(int argc, char** argv)
 {
@@ -55,6 +57,9 @@ main(int argc, char** argv)
     // FIXME implement a flightgear similar argument parser into simgear and use this one
     osg::ArgumentParser arguments(&argc, argv);
 
+    logbuf::set_log_classes(SG_ALL);
+    logbuf::set_log_priority(SG_ALERT);
+
     std::string fg_root;
     if (arguments.read("--fg-root", fg_root)) {
     } else if (const char *fg_root_env = std::getenv("FG_ROOT")) {
@@ -101,10 +106,39 @@ main(int argc, char** argv)
         props->setStringValue(prop, value);
     }
 
+    std::string renderer;
+    while (arguments.read("--renderer", renderer));
+
+    if (arguments.read("--hla")) {
+        props->setStringValue("hla/federate/federation", "rti:///FlightGear");
+    }
+    std::string federation;
+    if (arguments.read("--federation", federation)) {
+        props->setStringValue("hla/federate/federation", federation);
+    }
+
     /// Start setting up the viewer windows and start feeding them.
 
     // construct the viewer.
-    osgViewer::Viewer viewer(arguments);
+    fgviewer::Viewer viewer(arguments);
+
+    if (renderer.empty()) {
+        // Currently just the defautl renderer. More to come.
+        viewer.setRenderer(new fgviewer::Renderer);
+        
+    } else {
+        SG_LOG(SG_GENERAL, SG_ALERT, "Unknown renderer configuration \"" << renderer
+               << "\" given on the command line.");
+        return EXIT_FAILURE;
+    }
+
+    // A viewer configuration
+    if (const SGPropertyNode* viewerNode = props->getChild("viewer")) {
+        if (!viewer.readCameraConfig(*viewerNode)) {
+            SG_LOG(SG_GENERAL, SG_ALERT, "Reading camera configuration failed.");
+            return EXIT_FAILURE;
+        }
+    }
 
     // set up the camera manipulators.
     osgGA::KeySwitchMatrixManipulator* keyswitchManipulator;
@@ -122,7 +156,7 @@ main(int argc, char** argv)
     viewer.setCameraManipulator(keyswitchManipulator);
 
     // Usefull stats
-    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
+    viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getSceneDataGroup()->getOrCreateStateSet()));
     viewer.addEventHandler(new osgViewer::HelpHandler);
     viewer.addEventHandler(new osgViewer::StatsHandler);
     viewer.addEventHandler(new osgViewer::ThreadingHandler);
@@ -130,14 +164,6 @@ main(int argc, char** argv)
     viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
     viewer.addEventHandler(new osgViewer::WindowSizeHandler);
 
-    // Sigh, we need our own cull visitor ...
-    osg::Camera* camera = viewer.getCamera();
-    osgViewer::Renderer* renderer = static_cast<osgViewer::Renderer*>(camera->getRenderer());
-    for (int j = 0; j < 2; ++j) {
-        osgUtil::SceneView* sceneView = renderer->getSceneView(j);
-        sceneView->setCullVisitor(new simgear::EffectCullVisitor);
-    }
-
     // We want on demand database paging
     viewer.setDatabasePager(new osgDB::DatabasePager);
     viewer.getDatabasePager()->setUpThreads(1, 1);
@@ -177,11 +203,42 @@ main(int argc, char** argv)
     options->setPluginStringData("SimGear::FG_ROOT", fg_root);
     // Omit building bounding volume trees, as the viewer will not run a simulation
     options->setPluginStringData("SimGear::BOUNDINGVOLUMES", "OFF");
+    viewer.setReaderWriterOptions(options.get());
 
     // Here, all arguments are processed
     arguments.reportRemainingOptionsAsUnrecognized();
     arguments.writeErrorMessages(std::cerr);
 
+    if (props->getNode("hla/federate/federation")) {
+#if !defined FG_HAVE_HLA
+        SG_LOG(SG_GENERAL, SG_ALERT, "Unable to enter HLA/RTI viewer mode: HLA/RTI disabled at compile time.");
+#else
+        const SGPropertyNode* federateNode = props->getNode("hla/federate");
+        
+        SGSharedPtr<fgviewer::HLAViewerFederate> viewerFederate;
+        viewerFederate = new fgviewer::HLAViewerFederate;
+        viewerFederate->setVersion(federateNode->getStringValue("version", "RTI13"));
+        // viewerFederate->setConnectArguments(federateNode->getStringValue("connect-arguments", ""));
+        viewerFederate->setFederateType(federateNode->getStringValue("type", "ViewerFederate"));
+        viewerFederate->setFederateName(federateNode->getStringValue("name", ""));
+        viewerFederate->setFederationExecutionName(federateNode->getStringValue("federation", ""));
+        std::string objectModel;
+        objectModel = federateNode->getStringValue("federation-object-model", "HLA/fg-local-fom.xml");
+        if (SGPath(objectModel).isRelative()) {
+            SGPath path = fg_root;
+            path.append(objectModel);
+            objectModel = path.str();
+        }
+        viewerFederate->setFederationObjectModel(objectModel);
+
+        if (!viewerFederate->init()) {
+            SG_LOG(SG_NETWORK, SG_ALERT, "Got error from federate init!");
+        } else {
+            viewer.setViewerFederate(viewerFederate.get());
+            viewer.setCameraManipulator(new fgviewer::HLACameraManipulator(viewerFederate->getViewer()));
+        }
+#endif
+    }
 
     /// Read the model files that are configured.
 
@@ -203,7 +260,10 @@ main(int argc, char** argv)
     }
 
     // pass the loaded scene graph to the viewer.
-    viewer.setSceneData(loadedModel.get());
+    viewer.insertSceneData(loadedModel.get());
+
+    // Note that this does not affect the hla camera manipulator
+    viewer.home();
 
     return viewer.run();
 }