20,741
edits
m (→Roadmap: add original proof-of-concept patches for future reference (should probably use bugman's collapsible template?)) |
|||
Line 20: | Line 20: | ||
* Missile/payload views | * Missile/payload views | ||
* Prototyping/testing HUDs or PFDs requiring synthetic terrain to work properly | * Prototyping/testing HUDs or PFDs requiring synthetic terrain to work properly | ||
== Proof of Concept == | |||
{{Note|This is based on code originally provided by F-JJTH, and subsequently reworked by Icecode GL and Hooray back in 2016}} | |||
SimGear: | |||
<syntaxhighlight lang="diff"> | |||
diff --git a/simgear/canvas/CanvasSystemAdapter.hxx b/simgear/canvas/CanvasSystemAdapter.hxx | |||
index 43b3f780..0fb62170 100644 | |||
--- a/simgear/canvas/CanvasSystemAdapter.hxx | |||
+++ b/simgear/canvas/CanvasSystemAdapter.hxx | |||
@@ -35,11 +35,13 @@ namespace canvas | |||
virtual ~SystemAdapter() {} | |||
virtual FontPtr getFont(const std::string& name) const = 0; | |||
- virtual void addCamera(osg::Camera* camera) const = 0; | |||
+ virtual void addCamera(osg::Camera* camera, bool useSceneData = false) const = 0; | |||
virtual void removeCamera(osg::Camera* camera) const = 0; | |||
virtual osg::ref_ptr<osg::Image> getImage(const std::string& path) const = 0; | |||
+ virtual osg::Node* getModel(const std::string& path) const = 0; | |||
virtual SGSubsystem* getSubsystem(const std::string& name) const = 0; | |||
virtual HTTP::Client* getHTTPClient() const = 0; | |||
+ virtual osg::Matrix getViewMatrix(int view_number, double dt) const = 0; | |||
}; | |||
} // namespace canvas | |||
diff --git a/simgear/canvas/canvas_fwd.hxx b/simgear/canvas/canvas_fwd.hxx | |||
index 3b1b4646..97e9bd64 100644 | |||
--- a/simgear/canvas/canvas_fwd.hxx | |||
+++ b/simgear/canvas/canvas_fwd.hxx | |||
@@ -24,6 +24,7 @@ | |||
#include <osg/ref_ptr> | |||
#include <osgText/Font> | |||
+#include <osg/Node> | |||
#include <boost/function.hpp> | |||
#include <boost/shared_ptr.hpp> | |||
diff --git a/simgear/canvas/elements/CMakeLists.txt b/simgear/canvas/elements/CMakeLists.txt | |||
index 2b537c0c..4eb1e955 100644 | |||
--- a/simgear/canvas/elements/CMakeLists.txt | |||
+++ b/simgear/canvas/elements/CMakeLists.txt | |||
@@ -7,6 +7,7 @@ set(HEADERS | |||
CanvasMap.hxx | |||
CanvasPath.hxx | |||
CanvasText.hxx | |||
+ CanvasView.hxx | |||
) | |||
set(DETAIL_HEADERS | |||
@@ -20,6 +21,7 @@ set(SOURCES | |||
CanvasMap.cxx | |||
CanvasPath.cxx | |||
CanvasText.cxx | |||
+ CanvasView.cxx | |||
) | |||
simgear_scene_component(canvas-elements canvas/elements "${SOURCES}" "${HEADERS}") | |||
@@ -28,4 +30,4 @@ simgear_component(canvas-elements/detail canvas/elements/detail "" "${DETAIL_HEA | |||
add_boost_test(canvas_element | |||
SOURCES canvas_element_test.cpp | |||
LIBRARIES ${TEST_LIBS} | |||
-) | |||
\ No newline at end of file | |||
+) | |||
diff --git a/simgear/canvas/elements/CanvasGroup.cxx b/simgear/canvas/elements/CanvasGroup.cxx | |||
index c753c2e2..6cec072f 100644 | |||
--- a/simgear/canvas/elements/CanvasGroup.cxx | |||
+++ b/simgear/canvas/elements/CanvasGroup.cxx | |||
@@ -23,6 +23,7 @@ | |||
#include "CanvasMap.hxx" | |||
#include "CanvasPath.hxx" | |||
#include "CanvasText.hxx" | |||
+#include "CanvasView.hxx" | |||
#include <simgear/canvas/CanvasEventVisitor.hxx> | |||
#include <simgear/canvas/events/MouseEvent.hxx> | |||
@@ -66,6 +67,7 @@ namespace canvas | |||
add<Map >(_child_factories); | |||
add<Path >(_child_factories); | |||
add<Text >(_child_factories); | |||
+ add<View >(_child_factories); | |||
} | |||
//---------------------------------------------------------------------------- | |||
diff --git a/simgear/canvas/elements/CanvasView.cxx b/simgear/canvas/elements/CanvasView.cxx | |||
new file mode 100644 | |||
index 00000000..502e82d7 | |||
--- /dev/null | |||
+++ b/simgear/canvas/elements/CanvasView.cxx | |||
@@ -0,0 +1,91 @@ | |||
+#include <simgear/canvas/Canvas.hxx> | |||
+#include <simgear/canvas/CanvasMgr.hxx> | |||
+#include <simgear/canvas/CanvasSystemAdapter.hxx> | |||
+ | |||
+#include <simgear/scene/util/OsgMath.hxx> | |||
+ | |||
+#include "CanvasView.hxx" | |||
+ | |||
+#include <iostream> | |||
+#include <osg/io_utils> | |||
+ | |||
+namespace simgear | |||
+{ | |||
+namespace canvas | |||
+{ | |||
+ | |||
+const std::string View::TYPE_NAME = "view"; | |||
+ | |||
+void View::staticInit() | |||
+{ | |||
+ if ( isInit<View>() ) | |||
+ return; | |||
+} | |||
+ | |||
+View::View( const CanvasWeakPtr& canvas, | |||
+ const SGPropertyNode_ptr& node, | |||
+ const Style& parent_style, | |||
+ ElementWeakPtr parent ) : | |||
+ Element(canvas, node, parent_style, parent), | |||
+ _width(512), | |||
+ _height(512) | |||
+{ | |||
+ staticInit(); | |||
+ | |||
+ _texture = new osg::Texture2D; | |||
+ _texture->setDataVariance(osg::Object::DYNAMIC); | |||
+ _texture->setTextureSize(_width, _height); | |||
+ _texture->setInternalFormat(GL_RGBA); | |||
+ _texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); | |||
+ _texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR); | |||
+ | |||
+ _camera = new osg::Camera; | |||
+ _camera->setDataVariance(osg::Object::DYNAMIC); | |||
+ _camera->setViewport(0, 0, _width, _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, osg::Camera::FRAME_BUFFER); | |||
+ _camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); | |||
+ double aspect_ratio = (double)_width / _height; | |||
+ _camera->setProjectionMatrixAsPerspective(85.0, aspect_ratio, 0.1, 120000.0); | |||
+ | |||
+ _camera->attach(osg::Camera::COLOR_BUFFER, _texture.get()); | |||
+ | |||
+ if (Canvas::getSystemAdapter()) | |||
+ Canvas::getSystemAdapter()->addCamera(_camera.get(), true); | |||
+ | |||
+ _quad = osg::createTexturedQuadGeometry(osg::Vec3(0.0, 0.0, 0.0), | |||
+ osg::Vec3(_width, 0.0, 0.0), | |||
+ osg::Vec3(0.0, _height, 0.0), | |||
+ // In Canvas (0,0) is the top left corner, while in OSG/OpenGL | |||
+ // it's the bottom left corner. | |||
+ 0.0, 1.0, 1.0, 0.0); | |||
+ _quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, _texture.get(), osg::StateAttribute::ON); | |||
+ | |||
+ setDrawable(_quad.get()); | |||
+} | |||
+ | |||
+View::~View() | |||
+{ | |||
+ if( _camera.valid() && Canvas::getSystemAdapter() ) | |||
+ Canvas::getSystemAdapter()->removeCamera(_camera.get()); | |||
+ _camera.release(); | |||
+ _texture.release(); | |||
+} | |||
+ | |||
+void View::update(double dt) | |||
+{ | |||
+ osg::Matrix view_matrix = Canvas::getSystemAdapter()->getViewMatrix(0, dt); | |||
+ _camera->setViewMatrix(view_matrix); | |||
+ | |||
+ Element::update(dt); | |||
+} | |||
+ | |||
+void View::resize(int width, int height) | |||
+{ | |||
+ | |||
+} | |||
+ | |||
+} // namespace canvas | |||
+} // namespace simgear | |||
diff --git a/simgear/canvas/elements/CanvasView.hxx b/simgear/canvas/elements/CanvasView.hxx | |||
new file mode 100644 | |||
index 00000000..8cb3cc49 | |||
--- /dev/null | |||
+++ b/simgear/canvas/elements/CanvasView.hxx | |||
@@ -0,0 +1,39 @@ | |||
+#ifndef CANVAS_VIEW_HXX_ | |||
+#define CANVAS_VIEW_HXX_ | |||
+ | |||
+#include "CanvasElement.hxx" | |||
+ | |||
+namespace simgear | |||
+{ | |||
+namespace canvas | |||
+{ | |||
+ | |||
+class View : public Element { | |||
+public: | |||
+ static const std::string TYPE_NAME; | |||
+ static void staticInit(); | |||
+ | |||
+ View( const CanvasWeakPtr& canvas, | |||
+ const SGPropertyNode_ptr& node, | |||
+ const Style& parent_style = Style(), | |||
+ ElementWeakPtr parent = 0 ); | |||
+ virtual ~View(); | |||
+ | |||
+ virtual void update(double dt); | |||
+ | |||
+ virtual void resize(int width, int height); | |||
+ | |||
+protected: | |||
+ | |||
+ osg::ref_ptr<osg::Camera> _camera; | |||
+ osg::ref_ptr<osg::Texture2D> _texture; | |||
+ | |||
+ osg::ref_ptr<osg::Geometry> _quad; | |||
+ | |||
+ int _width, _height; | |||
+}; | |||
+ | |||
+} // namespace canvas | |||
+} // namespace simgear | |||
+ | |||
+#endif // CANVAS_VIEW_HXX_ | |||
</syntaxhighlight> | |||
FlightGear | |||
<syntaxhighlight lang="diff"> diff --git a/src/Canvas/FGCanvasSystemAdapter.cxx b/src/Canvas/FGCanvasSystemAdapter.cxx | |||
index 72b20747e..9e04dbd14 100644 | |||
--- a/src/Canvas/FGCanvasSystemAdapter.cxx | |||
+++ b/src/Canvas/FGCanvasSystemAdapter.cxx | |||
@@ -23,9 +23,18 @@ | |||
#include <Network/HTTPClient.hxx> | |||
#include <Viewer/renderer.hxx> | |||
+ | |||
+#include <Viewer/view.hxx> | |||
+#include <Viewer/viewmgr.hxx> | |||
+#include <simgear/scene/util/OsgMath.hxx> | |||
+ | |||
+ | |||
+ | |||
#include <osgDB/ReadFile> | |||
#include <stdexcept> | |||
+#include <simgear/scene/model/modellib.hxx> | |||
+ | |||
namespace canvas | |||
{ | |||
//---------------------------------------------------------------------------- | |||
@@ -64,9 +73,9 @@ namespace canvas | |||
} | |||
//---------------------------------------------------------------------------- | |||
- void FGCanvasSystemAdapter::addCamera(osg::Camera* camera) const | |||
+ void FGCanvasSystemAdapter::addCamera(osg::Camera* camera, bool useSceneData) const | |||
{ | |||
- globals->get_renderer()->addCamera(camera, false); | |||
+ globals->get_renderer()->addCamera(camera, useSceneData); | |||
} | |||
//---------------------------------------------------------------------------- | |||
@@ -100,6 +109,46 @@ namespace canvas | |||
return 0; | |||
} | |||
+ //---------------------------------------------------------------------------- | |||
+ // From http://wiki.flightgear.org/Howto:Extending_Canvas_to_support_rendering_3D_models#Extending_FGCanvasSystemAdapter | |||
+ osg::Node* FGCanvasSystemAdapter::getModel(const std::string& path) const | |||
+ { | |||
+ const char *model_path = "Models/Geometry/glider.ac"; | |||
+ SGPath p(SGPath::fromUtf8(path)); | |||
+ | |||
+ if( p.isAbsolute() ) | |||
+ { | |||
+ SGPath valid_path = fgValidatePath(p, false); | |||
+ if( !valid_path.isNull() ) | |||
+ try { | |||
+ std::string fullPath = simgear::SGModelLib::findDataFile(valid_path.local8BitStr()); | |||
+ osg::Node * object = simgear::SGModelLib::loadDeferredModel(fullPath, globals->get_props()); | |||
+ return object; | |||
+ } catch (const sg_throwable& t) { | |||
+ SG_LOG(SG_IO, SG_ALERT, "Error loading " << model_path << ":\n " << t.getFormattedMessage() << t.getOrigin()); | |||
+ return 0; | |||
+ } // error loading from absolute path | |||
+ SG_LOG(SG_IO, SG_ALERT, "canvas::Model: reading '" << path << "' denied"); | |||
+ } // absolute path handling | |||
+ else | |||
+ { | |||
+ SGPath tpath = globals->resolve_resource_path(path); | |||
+ if( !tpath.isNull() ) | |||
+ try { | |||
+ std::string fullPath = simgear::SGModelLib::findDataFile(path.c_str()); | |||
+ osg::Node * object = simgear::SGModelLib::loadDeferredModel(fullPath, globals->get_props()); | |||
+ return object; | |||
+ } catch (const sg_throwable& t) { | |||
+ SG_LOG(SG_IO, SG_ALERT, "Error loading " << model_path << ":\n " << t.getFormattedMessage() << t.getOrigin()); | |||
+ return 0; | |||
+ } // error loading from relative path | |||
+ | |||
+ SG_LOG(SG_IO, SG_ALERT, "canvas::Model: No such model: '" << path << "'"); | |||
+ } // relative path handling | |||
+ | |||
+ return 0; | |||
+ } | |||
+ | |||
//---------------------------------------------------------------------------- | |||
SGSubsystem* | |||
FGCanvasSystemAdapter::getSubsystem(const std::string& name) const | |||
@@ -121,4 +170,16 @@ namespace canvas | |||
return 0; | |||
} | |||
+ osg::Matrix FGCanvasSystemAdapter::getViewMatrix(int view_number, double dt) const | |||
+ { | |||
+ flightgear::View *view = globals->get_viewmgr()->get_view(view_number); | |||
+ 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()) ); | |||
+ | |||
+ return viewMatrix; | |||
+ } | |||
+ | |||
} | |||
diff --git a/src/Canvas/FGCanvasSystemAdapter.hxx b/src/Canvas/FGCanvasSystemAdapter.hxx | |||
index 4c1fd6210..24ececb41 100644 | |||
--- a/src/Canvas/FGCanvasSystemAdapter.hxx | |||
+++ b/src/Canvas/FGCanvasSystemAdapter.hxx | |||
@@ -28,11 +28,13 @@ namespace canvas | |||
{ | |||
public: | |||
virtual simgear::canvas::FontPtr getFont(const std::string& name) const; | |||
- virtual void addCamera(osg::Camera* camera) const; | |||
+ virtual void addCamera(osg::Camera* camera, bool useSceneData = false) const; | |||
virtual void removeCamera(osg::Camera* camera) const; | |||
virtual osg::ref_ptr<osg::Image> getImage(const std::string& path) const; | |||
+ virtual osg::Node* getModel(const std::string& path) const; | |||
virtual SGSubsystem* getSubsystem(const std::string& name) const; | |||
virtual simgear::HTTP::Client* getHTTPClient() const; | |||
+ virtual osg::Matrix getViewMatrix(int view_number, double dt) const; | |||
}; | |||
} | |||
diff --git a/src/Viewer/renderer.cxx b/src/Viewer/renderer.cxx | |||
index d9e8f351f..b9b3fc6a0 100644 | |||
--- a/src/Viewer/renderer.cxx | |||
+++ b/src/Viewer/renderer.cxx | |||
@@ -1845,6 +1845,8 @@ FGRenderer::setEventHandler(FGEventHandler* eventHandler_) | |||
void | |||
FGRenderer::addCamera(osg::Camera* camera, bool useSceneData) | |||
{ | |||
+ if (useSceneData) | |||
+ camera->addChild(globals->get_scenery()->get_scene_graph()); | |||
_viewerSceneRoot->addChild(camera); | |||
} | |||
</syntaxhighlight> | |||
<syntaxhighlight lang="diff">diff --git a/Nasal/canvas/api.nas b/Nasal/canvas/api.nas | |||
index 3f7f5a17..433a41f9 100644 | |||
--- a/Nasal/canvas/api.nas | |||
+++ b/Nasal/canvas/api.nas | |||
@@ -1132,10 +1132,10 @@ var Image = { | |||
} | |||
}; | |||
-var Model = { | |||
+var View = { | |||
new: func(ghost) | |||
{ | |||
- return {parents: [Model, Element.new(ghost)]}; | |||
+ return {parents: [View, Element.new(ghost)]}; | |||
}, | |||
}; | |||
@@ -1146,7 +1146,7 @@ Group._element_factories = { | |||
"text": Text.new, | |||
"path": Path.new, | |||
"image": Image.new, | |||
- "model": Model.new | |||
+ "view": View.new | |||
}; | |||
# Canvas | |||
</syntaxhighlight> | |||
== Roadmap == | == Roadmap == |