
This is the camera view I am referring to. Right now, everything there including the tail cam, gear cam, left wing and right wing views are completely black

Can anyone help?
Thank you and cheers!
Hooray wrote:we've had a number of discussions about possibly supporting camera views as Canvas elements, this isn't currently supported. At some point, this will probably be added, because it would simplify quite a bit of existing code (especially the view manager, and the way camera groups are set up) - however, the corresponding C++ predates Canvas by many years, so it would involve a bit of work.
But we've had a number of aircraft developers, who would also require this functionality for implementing mirrors and/or tailcam views rendered to instruments, or FLIR-type views. All of these wouuld be possible to support once the view manager is refactored such that it can render views to a new Canvas::Element - possibly in combination with supporting effects/shaders per element.
We've several building blocks for this in place already - but we've also seen people getting stuck while working on #1, simply because our existing way of using OSG is not particularly well-suited for having truly independent camera views - for a more technical explanantion, I'd suggest to check out: http://wiki.flightgear.org/CompositeViewer_Support
Given how FlightGear has evolved over time, not just regarding effects/shaders, but also complementary efforts like deferred rendering (via rembrandt), we'll probably see cameras (and maybe individual rendering stages) exposed as Canvases, so that there's a well-defined interface for hooking up custom effects/shaders to each stage in the pipeline - Zan's newcamera work demonstrates just how much flexibility can be accomplished this way, basically schemes like Rembrandt could then be entirely maintained in XML/effects and shader (fgdata) space.
android wrote in Sat Aug 30, 2014 10:13 am:So there's no solution to fix this?
Hooray wrote in Sat Aug 30, 2014 11:04 am:android wrote in Sat Aug 30, 2014 10:13 am:So there's no solution to fix this?
Thus, in the meantime you could file a feature request linking to your thread here so that other people interested in similar features can leave a vote or provide feedback.
wlbragg wrote in Tue Oct 14, 2014 3:59 am:Would this view be like a cam located inside the wheel well that points at the gear to see their state?
Hooray wrote:www2 wrote in Fri Oct 16, 2015 11:01 pm:Hooray any idea how loan to wait for this is add in canvas (with custom render options)?
Well, we can already render an arbitrary number of nested canvases (i.e. one canvas rendering another canvas, which is basically the requirement for window-in-window (pip) setups):
Equally, we have code/patches that extend the CanvasElement base class to add support for effects/shaders. As far as I am aware, this hasn't yet been incorporated - http://wiki.flightgear.org/Canvas_Devel ... 2F_Shaders
As has been said previously, the proper way to support "cameras" via Canvas is using CompositeViewer, which does require a re-architecting of several parts of FG: http://wiki.flightgear.org/CompositeViewer_Support
Given the current state of things, that seems at least another 3-4 release cycles away.
So, short of that, the only thing that we can currently support with reasonable effort is "slaved views" (as per $FG_ROOT/Docs/README.multiscreen).
That would not require too much in terms of coding, because the code is already there - in fact, CameraGroup.cxx already contains a RTT/FBO (render-to-texture) implementation that renders slaved views to an offscreen context. This is also how Rembrandt buffers are set up behind the scenes.
So basically, the code is there, it would need to be extracted/genralized and turned into a CanvasElement, and possibly integrated with the existing view manager code.
And then, there also is Zan's newcameras branch, which exposes rendering stages (passes) to XML/property tree space, so that individual stages are made accessible to shaders/effects.
Thus, most of the code is there, it is mainly a matter of integrating things, i.e. that would require someone able to build SG/FG from source, familiar with C++ and willing/able to work through some OSG tutorials/docs to make this work: http://wiki.flightgear.org/Canvas_Devel ... ng_Cameras
On the other hand, Canvas is/was primarily about exposing 2D rendering to fgdata space, so that fgdata developers could incorporatedevelop and maintain 2D rendering related features without having to be core developers (core development being an obvious bottleneck, as well as having significant barrier to entry).
In other words, people would need to be convinced that they want to let Canvas evolve beyond the 2D use-case, i.e. by allowing effects/shaders per element, but also to let Cameras be created/controlled easily.
Personally, I do believe that this is a worthwhile thing to aim for, as it would help unify (and simplify) most RTT/FBO handling in SG/FG, and make this available to people like Thorsten who have a track record of doing really fancy, unprecedented stuff, with this flexibility.
Equally, there are tons of use-cases where aircraft/scenery developers may want to set up custom cameras (A380 tail cam, space shuttle) and render those to an offscreen texture (e.g. GUI dialog and/or MFD screen).
It is true that "slaved views" are kinda limited at the moment, but they are also comparatively easy to set up, so I think that supporting slaved camera views via Canvas could be a good way to bootstrap/boost this development and pave the way for CompositeViewer adoption/integration in the future.
However, right now I am not aware of anybody working towards this.
Ironically, this gives a lot of momentum to poweroftwo's osgEarth effort, because that can already support independent viewers/cameras, and it would be pretty straightforward to render an osgEarth camera/map to a Canvas texture and use that elsewhere (GUI dialog/MFD screen etc).
However, currently, I am inclined to state that Canvas is falling victim to its own success, i.e. the way people (early-adopters) are using it is hugely problematic and does not scale at all.
So we really need to stop documenting certain APIs and instead provide a single scalable extension mechanism, i.e. registering new features as dedicated Canvas Elements implemented in Nasal space, and registered with the CanvasGroup helper - absent that, the situation with Canvas contributions is likely to approach exactly the dilemma we're seeing with most Nasal spaghetti code, which is unmaintainable and is begging to be rewritten/ported from scratch.
Which is simply because most aircraft developers are only interested in a single use-case (usually their own aircraft/instrument), and they don't care about long-term potential and maintenance, i.e. there are now tons of Canvas based features that would be useful in theory, but which are implemented in a fashion that renders them non-reusable elsewhere: http://wiki.flightgear.org/Canvas_Devel ... FlightGear
So at the moment, I am not too thrilled to add too many new features to Canvas, until this is solved - because we're seeing so much Nasal/Canvas code that is simply a dead-end due to the way it is structured, i.e. it won't be able to benefit from future optimizations short of a major rewrite or tons of 1:1 support by people familiar with the Canvas system. Which is why I am convinced that we need to stop implementing useful functionality using the existing approach, and instead adopt one that is CanvasElement-centric, where useful instruments, widgets, MFDs would be registered as custom elements implemented in Nasal space (via cppbind sub-classing).
If we don't do that, we will continue to see cool Canvas features implemented as spaghetti code monsters that reflect badly upon Nasal and Canvas due to lack of of design, and performance.
Hooray wrote:www2 wrote in Sat Oct 17, 2015 10:29 am:Hooray i mean render camera views in canvas (e.g. tail cam in a aircraft)
tail cams are slaved cameras, so could be using code that already exists in FG, which would need to be integrated with the Canvas system, to be exposed as a dedicated Canvas element (kinda like the view manager rendering everything to a texture/osg::Geode).
There's window setup/handling code in CameraGroup.cxx which sets up these slaved views and renders the whole thing to a osg::TextureRectangle, which is pretty much what needs to be extracted and integrated with a new "CanvasCamera" element - the boilerplate for which can be seen at: http://wiki.flightgear.org/Canvas_Devel ... ew_Element
So the CameraGroup code is in $FG_SRC/Viewer/CameraGroup.cxx, where you can find a buildCamera() routine that builds a camera using a property node read from an XML file, as per $FG_ROOT/Docs/README.multiscreen: http://sourceforge.net/p/flightgear/fli ... p.cxx#l798
The whole RTT/FBO texture setup can be seen here: http://sourceforge.net/p/flightgear/fli ... p.cxx#l994
That code would be redundant in the Canvas context, i.e. could be replaced by a Canvas FBO instead.
The next step would then be wrapping the whole thing in a CanvasCamera and exposing the corresponding view parameters as properties (propertyObject) so that slaved cameras can be controlled via Canvas.
Otherwise, there is only very little else needed, because the CanvasMgr would handle updating the Camera, and render everything to the texture that you specified.
Hooray wrote:trouble946 wrote in Fri Oct 16, 2015 6:58 am:The multiscreen readme only shows how to set up multiple screens in flight gear but to show different views e.g. Cockpit & helicopter no read me file shows that.
Any ideas on how
Here's an example setting up multiple views on a single screen using several slaved (offset) views:
http://wiki.flightgear.org/FlightGear_W ... r#Approach
http://wiki.flightgear.org/Howto:Config ... ew_windows
Also see: http://wiki.flightgear.org/index.php/FS ... dering.xml
F-JJTH wrote:Hi Hooray,
I looked at the forum and I see you often take the example of Zan camera as the top of the feature to get in FG.
In fact I implemented this feature more than 1 year ago. Here is the patch:
- Code: Select all
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
It works with default rendering and Rembrandt if I remember correctly.
If you read a bit the code you will understand how it works:
- On 3D side you just need to assign the texture "Aircraft/Instruments/Textures/camera-display.rgb" to the object you want display the camera
- On FG side, you must create a <camera-display> instrument in your instrumentation.xml
- All views defined by the aircraft author are available in the display
- You can control the camera position/orientation by modifying the property tree /sim/view[n]/ ...
Best regards,
Clément
As simple as that,
Users browsing this forum: No registered users and 0 guests