|
|
| Line 118: |
Line 118: |
| |script_version = 0.40 | | |script_version = 0.40 |
| }}</ref> | | }}</ref> |
|
| |
|
| |
| {{collapsible script
| |
| | type = C++ diff
| |
| | title = Proof of concept implementing slaved camera views rendering to a FBO/RTT
| |
| | script = From 9637fb0ac157d3df21feb60b279a7c8ccb8adf57 Mon Sep 17 00:00:00 2001
| |
| From: =?UTF-8?q?Cl=C3=A9ment=20de=20l=27Hamaide?= <cl-----e---ma----ez@hotmail.fr>
| |
| Date: Tue, 23 Feb 2016 21:42:11 +0100
| |
| Subject: [PATCH] Implement CameraDisplay instrument
| |
|
| |
| ---
| |
| src/Cockpit/CMakeLists.txt | 4 +-
| |
| src/Cockpit/CameraDisplay.cxx | 239 +++++++++++++++++++++++++++++++++
| |
| src/Cockpit/CameraDisplay.hxx | 73 ++++++++++
| |
| src/Cockpit/cockpitDisplayManager.cxx | 6 +-
| |
| src/Instrumentation/instrument_mgr.cxx | 3 +-
| |
| 5 files changed, 322 insertions(+), 3 deletions(-)
| |
| create mode 100644 src/Cockpit/CameraDisplay.cxx
| |
| create mode 100644 src/Cockpit/CameraDisplay.hxx
| |
|
| |
| diff --git a/src/Cockpit/CMakeLists.txt b/src/Cockpit/CMakeLists.txt
| |
| index 42b03ba..6d722ea 100644
| |
| --- a/src/Cockpit/CMakeLists.txt
| |
| +++ b/src/Cockpit/CMakeLists.txt
| |
| @@ -11,6 +11,7 @@ set(SOURCES
| |
| render_area_2d.cxx
| |
| wxradar.cxx
| |
| NavDisplay.cxx
| |
| + CameraDisplay.cxx
| |
| )
| |
|
| |
| set(HEADERS
| |
| @@ -24,7 +25,8 @@ set(HEADERS
| |
| render_area_2d.hxx
| |
| wxradar.hxx
| |
| NavDisplay.hxx
| |
| + CameraDisplay.hxx
| |
| )
| |
|
| |
|
| |
| -flightgear_component(Cockpit "${SOURCES}" "${HEADERS}")
| |
| \ No newline at end of file
| |
| +flightgear_component(Cockpit "${SOURCES}" "${HEADERS}")
| |
| diff --git a/src/Cockpit/CameraDisplay.cxx b/src/Cockpit/CameraDisplay.cxx
| |
| new file mode 100644
| |
| index 0000000..51c1d0a
| |
| --- /dev/null
| |
| +++ b/src/Cockpit/CameraDisplay.cxx
| |
| @@ -0,0 +1,239 @@
| |
| +// camera display texture
| |
| +//
| |
| +// Written by Clément de l'Hamaide
| |
| +//
| |
| +//
| |
| +// 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 <osg/ImageStream>
| |
| +
| |
| +#include <Main/fg_props.hxx>
| |
| +#include <Viewer/viewmgr.hxx>
| |
| +#include <Scenery/scenery.hxx>
| |
| +#include <Viewer/renderer.hxx>
| |
| +
| |
| +#include <simgear/scene/material/EffectGeode.hxx>
| |
| +#include <simgear/scene/util/OsgMath.hxx>
| |
| +
| |
| +#include "CameraDisplay.hxx"
| |
| +#include "panel.hxx"
| |
| +
| |
| +
| |
| +
| |
| +class FindAndReplaceStaticTextureVisitor : public osg::NodeVisitor
| |
| +{
| |
| + public:
| |
| + FindAndReplaceStaticTextureVisitor( const char* name, osg::Texture2D* new_texture ) :
| |
| + osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
| |
| + _tex_name( osgDB::getSimpleFileName(name) ),
| |
| + _new_texture(new_texture)
| |
| + {}
| |
| +
| |
| + virtual void apply(osg::Geode& node)
| |
| + {
| |
| + simgear::EffectGeode* eg = dynamic_cast<simgear::EffectGeode*>(&node);
| |
| + if( !eg )
| |
| + return;
| |
| + simgear::Effect* eff = eg->getEffect();
| |
| + if (!eff)
| |
| + return;
| |
| + osg::StateSet* ss = eff->getDefaultStateSet();
| |
| + if( !ss )
| |
| + return;
| |
| +
| |
| + for( size_t unit = 0; unit < ss->getNumTextureAttributeLists(); ++unit ) {
| |
| + osg::Texture2D* tex = dynamic_cast<osg::Texture2D*>( ss->getTextureAttribute(unit, osg::StateAttribute::TEXTURE) );
| |
| + if( !tex || !tex->getImage() || tex == _new_texture )
| |
| + continue;
| |
| +
| |
| + if( !_tex_name.empty() ) {
| |
| + std::string tex_name = tex->getImage()->getFileName();
| |
| + std::string tex_name_simple = osgDB::getSimpleFileName(tex_name);
| |
| + if( !osgDB::equalCaseInsensitive(_tex_name, tex_name_simple) )
| |
| + continue;
| |
| + }
| |
| +
| |
| + // insert a new group between the geode an it's parent which overrides the texture
| |
| + osg::ref_ptr<osg::Group> group = new osg::Group;
| |
| + group->setName("canvas texture group");
| |
| + group->addChild(eg);
| |
| + osg::ref_ptr<osg::Group> parent = node.getParent(0);
| |
| + parent->removeChild(eg);
| |
| + parent->addChild(group);
| |
| +
| |
| + osg::StateSet* stateSet = group->getOrCreateStateSet();
| |
| + stateSet->setTextureAttribute( unit, _new_texture, osg::StateAttribute::OVERRIDE );
| |
| + stateSet->setTextureMode( unit, GL_TEXTURE_2D, osg::StateAttribute::ON );
| |
| +
| |
| + SG_LOG(SG_INSTR, SG_DEBUG, "CameraDislay: replaced texture '" << _tex_name << "'" << " for object '" << parent->getName() << "'");
| |
| + return;
| |
| + }
| |
| + }
| |
| +
| |
| + protected:
| |
| + std::string _tex_name;
| |
| + osg::Texture2D *_new_texture;
| |
| +};
| |
| +
| |
| +
| |
| +
| |
| +CameraDisplay::CameraDisplay(SGPropertyNode *node) :
| |
| + _num(node->getIntValue("number", 0)),
| |
| + _viewNum(node->getIntValue("view-number", 0)),
| |
| + _enabled(true),
| |
| + _initialized(false),
| |
| + _name(node->getStringValue("name", "cd")),
| |
| + _texturePath(node->getStringValue("texture-path",
| |
| + "Aircraft/Instruments/Textures/camera-display.rgb"))
| |
| +{}
| |
| +
| |
| +
| |
| +CameraDisplay::~CameraDisplay()
| |
| +{
| |
| + if( !_initialized )
| |
| + return;
| |
| +}
| |
| +
| |
| +
| |
| +void CameraDisplay::bind()
| |
| +{
| |
| + _instrument_node = fgGetNode("/instrumentation/camera-display", _num, true);
| |
| + _name_node = _instrument_node->getChild( "name", 0, true);
| |
| + _texture_node = _instrument_node->getChild( "texture", 0, true);
| |
| + _enabled_node = _instrument_node->getChild( "enabled", 0, true );
| |
| + _view_node = _instrument_node->getChild( "view-number", 0, true );
| |
| +
| |
| + _view_node->setIntValue(_viewNum);
| |
| + _name_node->setStringValue(_name);
| |
| + _enabled_node->setBoolValue(_enabled);
| |
| + _texture_node->setStringValue(_texturePath);
| |
| +
| |
| + _view_node->addChangeListener(this);
| |
| + _enabled_node->addChangeListener(this);
| |
| +}
| |
| +
| |
| +
| |
| +void CameraDisplay::init()
| |
| +{
| |
| + if(_initialized)
| |
| + return;
| |
| +
| |
| + if ( !fgGetNode("/sim/view", _viewNum, false) ) {
| |
| + SG_LOG(SG_INSTR, SG_DEBUG, "CameraDisplay: can't find view-number " << _viewNum);
| |
| + return;
| |
| + }
| |
| +
| |
| + std::string path = _texture_node->getStringValue();
| |
| + SGPath tpath = globals->resolve_aircraft_path( path );
| |
| + if (!tpath.exists()) {
| |
| + SG_LOG(SG_INSTR, SG_WARN, "CameraDisplay: display texture not found:" << path);
| |
| + return;
| |
| + }
| |
| +
| |
| + _initialized = true;
| |
| +}
| |
| +
| |
| +
| |
| +void CameraDisplay::postinit()
| |
| +{
| |
| + if( !_initialized )
| |
| + return;
| |
| +
| |
| + setView( _view_node->getIntValue() );
| |
| +
| |
| + //TODO: setup an osg::Texture
| |
| + // setup an osg::Camera
| |
| + // attach the osg::Camera to the osg::Texture2D
| |
| + // in a way the camera draw on the osg::Texture2D
| |
| + // attach the osg::Texture2D to the 3D model
| |
| + // in a way the current 3D model texture being replaced by the osg::Texure2D
| |
| +#if 1
| |
| + int tex_width = 512, tex_height = 512;
| |
| + _texture = new osg::Texture2D;
| |
| + _texture->setTextureSize( tex_width, tex_height );
| |
| + _texture->setInternalFormat( GL_RGBA );
| |
| + _texture->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR );
| |
| + _texture->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );
| |
| +
| |
| + FindAndReplaceStaticTextureVisitor ftv( _texture_node->getStringValue(), _texture.get() );
| |
| + globals->get_scenery()->get_aircraft_branch()->accept(ftv);
| |
| +
| |
| + _camera = new osg::Camera;
| |
| + _camera->setViewport( 0, 0, tex_width, tex_height );
| |
| + _camera->setClearColor( osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) );
| |
| + _camera->setClearMask( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
| |
| + _camera->setRenderOrder( osg::Camera::PRE_RENDER );
| |
| + _camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
| |
| + _camera->attach( osg::Camera::COLOR_BUFFER, _texture.get() );
| |
| + _camera->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
| |
| + _camera->addChild( globals->get_scenery()->get_scene_graph() );
| |
| + _camera->setProjectionMatrixAsPerspective(/*fov*/ 85.0, /*ratio*/ 1.88, /*near*/ 0.1, /*far*/ 120000.0);
| |
| + globals->get_renderer()->addCamera(_camera, false);
| |
| +#endif
| |
| +}
| |
| +
| |
| +
| |
| +void CameraDisplay::update(double dt)
| |
| +{
| |
| + if( !_initialized || !_enabled )
| |
| + return;
| |
| +#if 1
| |
| + if( _view != globals->get_current_view() )
| |
| + _view->update(dt);
| |
| +
| |
| + osg::Vec3f position( toOsg(_view->getViewPosition()) );
| |
| + osg::Quat orientation( toOsg(_view->getViewOrientation()) );
| |
| + osg::Matrix viewMatrix( osg::Matrix::translate(-position) * osg::Matrix::rotate(orientation.inverse()) );
| |
| +
| |
| + _camera->setViewMatrix( viewMatrix );
| |
| +#endif
| |
| +}
| |
| +
| |
| +
| |
| +void CameraDisplay::valueChanged(SGPropertyNode *node)
| |
| +{
| |
| + if(!_initialized)
| |
| + return;
| |
| +
| |
| + if (node == _enabled_node) {
| |
| + _enabled = node->getBoolValue();
| |
| + return;
| |
| + }
| |
| +
| |
| + if (node == _view_node) {
| |
| + _view = globals->get_viewmgr()->get_view( node->getIntValue() );
| |
| + setView( node->getIntValue() );
| |
| + return;
| |
| + }
| |
| +}
| |
| +
| |
| +
| |
| +void CameraDisplay::setView(int v)
| |
| +{
| |
| + std::vector<SGPropertyNode_ptr> viewList = fgGetNode("/sim", true)->getChildren("view");
| |
| + for (unsigned int i = 0; i < viewList.size(); i++) {
| |
| + if( viewList[i]->getIndex() == v ) {
| |
| + _view = globals->get_viewmgr()->get_view(i);
| |
| + break;
| |
| + }
| |
| + }
| |
| +}
| |
| +
| |
| diff --git a/src/Cockpit/CameraDisplay.hxx b/src/Cockpit/CameraDisplay.hxx
| |
| new file mode 100644
| |
| index 0000000..69e432a
| |
| --- /dev/null
| |
| +++ b/src/Cockpit/CameraDisplay.hxx
| |
| @@ -0,0 +1,73 @@
| |
| +// camera display texture
| |
| +//
| |
| +// Written by Clément de l'Hamaide
| |
| +//
| |
| +//
| |
| +// 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 _INST_CAMDISPLAY_HXX
| |
| +#define _INST_CAMDISPLAY_HXX
| |
| +
| |
| +#include <Viewer/view.hxx>
| |
| +
| |
| +#include "od_gauge.hxx"
| |
| +
| |
| +/*
| |
| + * CameraDisplay class
| |
| + *
| |
| + * A subsystem instrument who reproduces a camera and its display
| |
| + */
| |
| +
| |
| +class CameraDisplay : public SGSubsystem, public SGPropertyChangeListener
| |
| +{
| |
| + public:
| |
| + CameraDisplay(SGPropertyNode *node);
| |
| + virtual ~CameraDisplay();
| |
| +
| |
| + virtual void bind();
| |
| + virtual void init();
| |
| + virtual void postinit();
| |
| + virtual void update(double dt);
| |
| + virtual void valueChanged(SGPropertyNode *node);
| |
| +
| |
| + void setView(int v);
| |
| +
| |
| + protected:
| |
| +
| |
| +
| |
| + private:
| |
| + int _num;
| |
| + int _viewNum;
| |
| + bool _enabled;
| |
| + bool _initialized;
| |
| + FGODGauge *_odg;
| |
| + std::string _name;
| |
| + std::string _texturePath;
| |
| + flightgear::View *_view;
| |
| + SGPropertyNode_ptr _name_node;
| |
| + SGPropertyNode_ptr _view_node;
| |
| + SGPropertyNode_ptr _enabled_node;
| |
| + SGPropertyNode_ptr _texture_node;
| |
| + SGPropertyNode_ptr _instrument_node;
| |
| + osg::ref_ptr<osg::Camera> _camera;
| |
| + osg::ref_ptr<osg::Texture2D> _texture;
| |
| + osg::Matrix _viewMatrix;
| |
| + /*osg::Camera *_camera;
| |
| + osg::Texture2D *_texture;*/
| |
| +};
| |
| +
| |
| +#endif
| |
| diff --git a/src/Cockpit/cockpitDisplayManager.cxx b/src/Cockpit/cockpitDisplayManager.cxx
| |
| index 18e6e7d..0a46ff8 100644
| |
| --- a/src/Cockpit/cockpitDisplayManager.cxx
| |
| +++ b/src/Cockpit/cockpitDisplayManager.cxx
| |
| @@ -37,6 +37,7 @@
| |
| #include "NavDisplay.hxx"
| |
| #include "groundradar.hxx"
| |
| #include "wxradar.hxx"
| |
| +#include "CameraDisplay.hxx"
| |
|
| |
| namespace flightgear
| |
| {
| |
| @@ -112,7 +113,10 @@ bool CockpitDisplayManager::build (SGPropertyNode* config_props)
| |
|
| |
| } else if ( name == "navigation-display" ) {
| |
| set_subsystem( id, new NavDisplay( node ) );
| |
| -
| |
| +
| |
| + } else if ( name == "camera-display" ) {
| |
| + set_subsystem( id, new CameraDisplay( node ) );
| |
| +
| |
| } else {
| |
| // probably a regular instrument
| |
| continue;
| |
| diff --git a/src/Instrumentation/instrument_mgr.cxx b/src/Instrumentation/instrument_mgr.cxx
| |
| index 751f6c7..3bd1dfa 100644
| |
| --- a/src/Instrumentation/instrument_mgr.cxx
| |
| +++ b/src/Instrumentation/instrument_mgr.cxx
| |
| @@ -209,7 +209,8 @@ bool FGInstrumentMgr::build (SGPropertyNode* config_props)
| |
| } else if (( name == "groundradar" ) ||
| |
| ( name == "radar" ) ||
| |
| ( name == "air-ground-radar" ) ||
| |
| - ( name == "navigation-display" ))
| |
| + ( name == "navigation-display" ) ||
| |
| + ( name == "camera-display" ))
| |
| {
| |
| // these instruments are handled by the CockpitDisplayManager
| |
| // catch them here so we can still warn about bogus names in
| |
| --
| |
| 1.9.1
| |
| | lang = diff
| |
| }}
| |
|
| |
|
| === G1000 & MapStructure improvements === | | === G1000 & MapStructure improvements === |