diff --git a/CMakeLists.txt b/CMakeLists.txt index fb8998570..2d7b9e934 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,7 +191,6 @@ option(ENABLE_FGQCANVAS "Set to ON to build the Qt-based remote canvas applicat option(ENABLE_DEMCONVERT "Set to ON to build the dem conversion tool (default)" ON) option(ENABLE_HID_INPUT "Set to ON to build HID-based input code" ${EVENT_INPUT_DEFAULT}) option(ENABLE_PLIB_JOYSTICK "Set to ON to enable legacy joystick code (default)" ON) -option(ENABLE_COMPOSITOR "Set to ON to enable the Compositor-based Viewer" OFF) option(ENABLE_SWIFT "Set to ON to build the swift module" ON) diff --git a/src/GUI/LauncherMainWindow.cxx b/src/GUI/LauncherMainWindow.cxx index 4b28f3de0..e09d6a264 100755 --- a/src/GUI/LauncherMainWindow.cxx +++ b/src/GUI/LauncherMainWindow.cxx @@ -125,11 +125,7 @@ LauncherMainWindow::LauncherMainWindow(bool inSimMode) : QQuickView() ctx->setContextProperty("_addOns", addOnsCtl); } -#if defined(ENABLE_COMPOSITOR) ctx->setContextProperty("_haveCompositor", true); -#else - ctx->setContextProperty("_haveCompositor", false); -#endif auto weatherScenariosModel = new flightgear::WeatherScenariosModel(this); ctx->setContextProperty("_weatherScenarios", weatherScenariosModel); diff --git a/src/Include/config_cmake.h.in b/src/Include/config_cmake.h.in index a0dadcb74..55bc924dc 100644 --- a/src/Include/config_cmake.h.in +++ b/src/Include/config_cmake.h.in @@ -69,8 +69,6 @@ #cmakedefine HAVE_QRC_TRANSLATIONS -#cmakedefine ENABLE_COMPOSITOR - #cmakedefine ENABLE_SWIFT #cmakedefine HAVE_SENTRY diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index 552572a52..ecd2a1a95 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -134,17 +134,6 @@ public: } }; -class CompositorEffectsProvider : public simgear::ResourceProvider { -public: - CompositorEffectsProvider() : - simgear::ResourceProvider(simgear::ResourceManager::PRIORITY_NORMAL) { - } - SGPath resolve(const std::string &aResource, SGPath&) const override { - const SGPath p = globals->get_fg_root() / "Compositor" / aResource; - return p.exists() ? p : SGPath(); - } -}; - //////////////////////////////////////////////////////////////////////// // Implementation of FGGlobals. //////////////////////////////////////////////////////////////////////// @@ -176,9 +165,6 @@ FGGlobals::FGGlobals() : resMgr->addProvider(new AircraftResourceProvider()); resMgr->addProvider(new CurrentAircraftDirProvider()); resMgr->addProvider(new flightgear::addons::ResourceProvider()); -#ifdef ENABLE_COMPOSITOR - resMgr->addProvider(new CompositorEffectsProvider()); -#endif initProperties(); } diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 0861bdc29..4d5d5a7ca 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -250,12 +250,6 @@ void fgSetDefaults () v->setValueReadOnly("build-id", JENKINS_BUILD_ID); v->setValueReadOnly("hla-support", bool(FG_HAVE_HLA)); v->setValueReadOnly("build-type", FG_BUILD_TYPE); -#ifdef ENABLE_COMPOSITOR - static constexpr bool compositor_support = true; -#else - static constexpr bool compositor_support = false; -#endif - v->setValueReadOnly("compositor-support", compositor_support); char* envp = ::getenv( "http_proxy" ); if( envp != nullptr ) diff --git a/src/Scenery/redout.cxx b/src/Scenery/redout.cxx index 1555a3305..7c6113b76 100644 --- a/src/Scenery/redout.cxx +++ b/src/Scenery/redout.cxx @@ -81,6 +81,7 @@ osg::Node* FGCreateRedoutNode() stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); stateSet->setAttribute(new osg::Depth(osg::Depth::ALWAYS, 0, 1, false)); stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + stateSet->setRenderBinDetails(1000, "RenderBin"); osg::Vec3Array* vertexArray = new osg::Vec3Array; vertexArray->push_back(osg::Vec3(-1, -1, 0)); @@ -101,7 +102,7 @@ osg::Node* FGCreateRedoutNode() camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); camera->setProjectionMatrix(osg::Matrix::ortho2D(-1, 1, -1, 1)); camera->setViewMatrix(osg::Matrix::identity()); - camera->setRenderOrder(osg::Camera::POST_RENDER, 99); + camera->setRenderOrder(osg::Camera::NESTED_RENDER); camera->setClearMask(0); camera->setAllowEventFocus(false); camera->setCullingActive(false); diff --git a/src/Viewer/CMakeLists.txt b/src/Viewer/CMakeLists.txt index 2a4bcede4..5e8330d67 100644 --- a/src/Viewer/CMakeLists.txt +++ b/src/Viewer/CMakeLists.txt @@ -1,12 +1,14 @@ include(FlightGearComponent) set(SOURCES + CameraGroup.cxx FGEventHandler.cxx WindowBuilder.cxx WindowSystemAdapter.cxx fg_os_osgviewer.cxx fgviewer.cxx ViewPropertyEvaluator.cxx + renderer.cxx splash.cxx view.cxx viewmgr.cxx @@ -36,12 +38,4 @@ if (YES) list(APPEND SOURCES PUICamera.cxx) endif() -if (ENABLE_COMPOSITOR) - list(APPEND SOURCES CameraGroup_compositor.cxx renderer_compositor.cxx) - list(APPEND HEADERS CameraGroup_compositor.hxx renderer_compositor.hxx) -else () - list(APPEND SOURCES CameraGroup_legacy.cxx renderer_legacy.cxx renderingpipeline.cxx) - list(APPEND HEADERS CameraGroup_legacy.hxx renderer_legacy.hxx renderingpipeline.hxx) -endif() - flightgear_component(Viewer "${SOURCES}" "${HEADERS}") diff --git a/src/Viewer/CameraGroup_compositor.cxx b/src/Viewer/CameraGroup.cxx similarity index 100% rename from src/Viewer/CameraGroup_compositor.cxx rename to src/Viewer/CameraGroup.cxx diff --git a/src/Viewer/CameraGroup.hxx b/src/Viewer/CameraGroup.hxx index 14347b9e4..cd1111ef4 100644 --- a/src/Viewer/CameraGroup.hxx +++ b/src/Viewer/CameraGroup.hxx @@ -1,14 +1,241 @@ -#ifndef COMMON_CAMERAGROUP_HXX -#define COMMON_CAMERAGROUP_HXX +// Copyright (C) 2008 Tim Moore +// +// 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 CAMERAGROUP_HXX +#define CAMERAGROUP_HXX 1 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace osg +{ +class Camera; +} + +namespace osgViewer +{ +class Viewer; +} + +class SGPropertyNode; + +namespace flightgear +{ + +class CameraGroupListener; +class GraphicsWindow; + +/** A wrapper around osg::Camera that contains some extra information. + */ +struct CameraInfo : public osg::Referenced +{ + /** properties of a camera. + */ + enum Flags + { + VIEW_ABSOLUTE = 0x1, /**< The camera view is absolute, not + relative to the master camera. */ + PROJECTION_ABSOLUTE = 0x2, /**< The projection is absolute. */ + ORTHO = 0x4, /**< The projection is orthographic */ + GUI = 0x8, /**< Camera draws the GUI. */ + DO_INTERSECTION_TEST = 0x10,/**< scene intersection tests this + camera. */ + FIXED_NEAR_FAR = 0x20, /**< take the near far values in the + projection for real. */ + ENABLE_MASTER_ZOOM = 0x40 /**< Can apply the zoom algorithm. */ + }; + + CameraInfo(unsigned flags_) : + flags(flags_), + physicalWidth(0), physicalHeight(0), bezelHeightTop(0), + bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0), + relativeCameraParent(0) { } + /** The name as given in the config file. + */ + std::string name; + /** Properties of the camera. @see CameraGroup::Flags. + */ + unsigned flags; + /** Physical size parameters. + */ + double physicalWidth; + double physicalHeight; + double bezelHeightTop; + double bezelHeightBottom; + double bezelWidthLeft; + double bezelWidthRight; + /** Non-owning reference to the parent camera for relative camera + * configurations. + */ + const CameraInfo *relativeCameraParent; + /** The reference points in the parents projection space. + */ + osg::Vec2d parentReference[2]; + /** The reference points in the current projection space. + */ + osg::Vec2d thisReference[2]; + /** View offset from the viewer master camera. + */ + osg::Matrix viewOffset; + /** Projection offset from the viewer master camera. + */ + osg::Matrix projOffset; + /** Current view and projection matrices for this camera. + * They are only used by other child cameras through relativeCameraParent + * so they can avoid recalculating them. + */ + osg::Matrix viewMatrix, projMatrix; + /** The Compositor used to manage the pipeline of this camera. + */ + osg::ref_ptr compositor; +}; + +class CameraGroup : public osg::Referenced +{ +public: + /** Create a camera group associated with an osgViewer::Viewer. + * @param viewer the viewer + */ + CameraGroup(osgViewer::Viewer* viewer); + virtual ~CameraGroup(); + + /** Set the default CameraGroup, which is the only one that + * matters at this time. + * @param group the group to set. + */ + static void buildDefaultGroup(osgViewer::Viewer* viewer); + static void setDefault(CameraGroup* group) { _defaultGroup = group; } + /** Get the default CameraGroup. + * @return the default camera group. + */ + static CameraGroup* getDefault() { return _defaultGroup.get(); } + /** Get the camera group's Viewer. + * @return the viewer + */ + osgViewer::Viewer* getViewer() { return _viewer.get(); } + /** Create an osg::Camera from a property node and add it to the + * camera group. + * @param cameraNode the property node. + * @return a CameraInfo object for the camera. + */ + void buildCamera(SGPropertyNode* cameraNode); + /** Create a camera from properties that will draw the GUI and add + * it to the camera group. + * @param cameraNode the property node. This can be 0, in which + * case a default GUI camera is created. + * @param window the GraphicsWindow to use for the GUI camera. If + * this is 0, the window is determined from the property node. + * @return a CameraInfo object for the GUI camera. + */ + void buildGUICamera(SGPropertyNode* cameraNode, + GraphicsWindow* window = 0); + /** Update the view for the camera group. + * @param position the world position of the view + * @param orientation the world orientation of the view. + */ + void update(const osg::Vec3d& position, + const osg::Quat& orientation); + /** Set the parameters of the viewer's master camera. This won't + * affect cameras that have CameraFlags::PROJECTION_ABSOLUTE set. + * XXX Should znear and zfar be settable? + * @param vfov the vertical field of view angle + * @param aspectRatio the master camera's aspect ratio. This + * doesn't actually change the viewport, but should reflect the + * current viewport. + */ + void setCameraParameters(float vfov, float aspectRatio); + /** Update camera properties after a resize event. + */ + void resized(); + + void buildDistortionCamera(const SGPropertyNode* psNode, + osg::Camera* camera); + /** + * get aspect ratio of master camera's viewport + */ + double getMasterAspectRatio() const; + + CameraInfo *getGUICamera() const; + +protected: + friend CameraGroupListener; + friend bool computeIntersections(const CameraGroup* cgroup, + const osg::Vec2d& windowPos, + osgUtil::LineSegmentIntersector::Intersections& + intersections); + + typedef std::vector> CameraList; + CameraList _cameras; + osg::ref_ptr _viewer; + static osg::ref_ptr _defaultGroup; + std::unique_ptr _listener; + + // Near, far for the master camera if used. + float _zNear; + float _zFar; + float _nearField; + + /** Build a complete CameraGroup from a property node. + * @param viewer the viewer associated with this camera group. + * @param wbuilder the window builder to be used for this camera group. + * @param the camera group property node. + */ + static CameraGroup* buildCameraGroup(osgViewer::Viewer* viewer, + SGPropertyNode* node); +}; + +/** Get the osg::Camera that draws the GUI, if any, from a camera + * group. + * @param cgroup the camera group + * @return the GUI camera or 0 + */ +osg::Camera* getGUICamera(CameraGroup* cgroup); +/** Choose a camera using an event and do intersection testing on its + * view of the scene. Only cameras with the DO_INTERSECTION_TEST flag + * set are considered. + * @param cgroup the CameraGroup + * @param ea the event containing a window and mouse coordinates + * @param intersections container for the result of intersection + * testing. + * @return true if any intersections are found + */ +bool computeIntersections(const CameraGroup* cgroup, + const osg::Vec2d& windowPos, + osgUtil::LineSegmentIntersector::Intersections& + intersections); +/** Warp the pointer to coordinates in the GUI camera of a camera group. + * @param cgroup the camera group + * @param x x window coordinate of pointer + * @param y y window coordinate of pointer, in "y down" coordinates. + */ +void warpGUIPointer(CameraGroup* cgroup, int x, int y); + +} -#ifdef HAVE_CONFIG_H -# include #endif - -#ifdef ENABLE_COMPOSITOR -# include "CameraGroup_compositor.hxx" -#else -# include "CameraGroup_legacy.hxx" -#endif - -#endif /* COMMON_CAMERAGROUP_HXX */ diff --git a/src/Viewer/CameraGroup_compositor.hxx b/src/Viewer/CameraGroup_compositor.hxx deleted file mode 100644 index cd1111ef4..000000000 --- a/src/Viewer/CameraGroup_compositor.hxx +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (C) 2008 Tim Moore -// -// 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 CAMERAGROUP_HXX -#define CAMERAGROUP_HXX 1 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace osg -{ -class Camera; -} - -namespace osgViewer -{ -class Viewer; -} - -class SGPropertyNode; - -namespace flightgear -{ - -class CameraGroupListener; -class GraphicsWindow; - -/** A wrapper around osg::Camera that contains some extra information. - */ -struct CameraInfo : public osg::Referenced -{ - /** properties of a camera. - */ - enum Flags - { - VIEW_ABSOLUTE = 0x1, /**< The camera view is absolute, not - relative to the master camera. */ - PROJECTION_ABSOLUTE = 0x2, /**< The projection is absolute. */ - ORTHO = 0x4, /**< The projection is orthographic */ - GUI = 0x8, /**< Camera draws the GUI. */ - DO_INTERSECTION_TEST = 0x10,/**< scene intersection tests this - camera. */ - FIXED_NEAR_FAR = 0x20, /**< take the near far values in the - projection for real. */ - ENABLE_MASTER_ZOOM = 0x40 /**< Can apply the zoom algorithm. */ - }; - - CameraInfo(unsigned flags_) : - flags(flags_), - physicalWidth(0), physicalHeight(0), bezelHeightTop(0), - bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0), - relativeCameraParent(0) { } - /** The name as given in the config file. - */ - std::string name; - /** Properties of the camera. @see CameraGroup::Flags. - */ - unsigned flags; - /** Physical size parameters. - */ - double physicalWidth; - double physicalHeight; - double bezelHeightTop; - double bezelHeightBottom; - double bezelWidthLeft; - double bezelWidthRight; - /** Non-owning reference to the parent camera for relative camera - * configurations. - */ - const CameraInfo *relativeCameraParent; - /** The reference points in the parents projection space. - */ - osg::Vec2d parentReference[2]; - /** The reference points in the current projection space. - */ - osg::Vec2d thisReference[2]; - /** View offset from the viewer master camera. - */ - osg::Matrix viewOffset; - /** Projection offset from the viewer master camera. - */ - osg::Matrix projOffset; - /** Current view and projection matrices for this camera. - * They are only used by other child cameras through relativeCameraParent - * so they can avoid recalculating them. - */ - osg::Matrix viewMatrix, projMatrix; - /** The Compositor used to manage the pipeline of this camera. - */ - osg::ref_ptr compositor; -}; - -class CameraGroup : public osg::Referenced -{ -public: - /** Create a camera group associated with an osgViewer::Viewer. - * @param viewer the viewer - */ - CameraGroup(osgViewer::Viewer* viewer); - virtual ~CameraGroup(); - - /** Set the default CameraGroup, which is the only one that - * matters at this time. - * @param group the group to set. - */ - static void buildDefaultGroup(osgViewer::Viewer* viewer); - static void setDefault(CameraGroup* group) { _defaultGroup = group; } - /** Get the default CameraGroup. - * @return the default camera group. - */ - static CameraGroup* getDefault() { return _defaultGroup.get(); } - /** Get the camera group's Viewer. - * @return the viewer - */ - osgViewer::Viewer* getViewer() { return _viewer.get(); } - /** Create an osg::Camera from a property node and add it to the - * camera group. - * @param cameraNode the property node. - * @return a CameraInfo object for the camera. - */ - void buildCamera(SGPropertyNode* cameraNode); - /** Create a camera from properties that will draw the GUI and add - * it to the camera group. - * @param cameraNode the property node. This can be 0, in which - * case a default GUI camera is created. - * @param window the GraphicsWindow to use for the GUI camera. If - * this is 0, the window is determined from the property node. - * @return a CameraInfo object for the GUI camera. - */ - void buildGUICamera(SGPropertyNode* cameraNode, - GraphicsWindow* window = 0); - /** Update the view for the camera group. - * @param position the world position of the view - * @param orientation the world orientation of the view. - */ - void update(const osg::Vec3d& position, - const osg::Quat& orientation); - /** Set the parameters of the viewer's master camera. This won't - * affect cameras that have CameraFlags::PROJECTION_ABSOLUTE set. - * XXX Should znear and zfar be settable? - * @param vfov the vertical field of view angle - * @param aspectRatio the master camera's aspect ratio. This - * doesn't actually change the viewport, but should reflect the - * current viewport. - */ - void setCameraParameters(float vfov, float aspectRatio); - /** Update camera properties after a resize event. - */ - void resized(); - - void buildDistortionCamera(const SGPropertyNode* psNode, - osg::Camera* camera); - /** - * get aspect ratio of master camera's viewport - */ - double getMasterAspectRatio() const; - - CameraInfo *getGUICamera() const; - -protected: - friend CameraGroupListener; - friend bool computeIntersections(const CameraGroup* cgroup, - const osg::Vec2d& windowPos, - osgUtil::LineSegmentIntersector::Intersections& - intersections); - - typedef std::vector> CameraList; - CameraList _cameras; - osg::ref_ptr _viewer; - static osg::ref_ptr _defaultGroup; - std::unique_ptr _listener; - - // Near, far for the master camera if used. - float _zNear; - float _zFar; - float _nearField; - - /** Build a complete CameraGroup from a property node. - * @param viewer the viewer associated with this camera group. - * @param wbuilder the window builder to be used for this camera group. - * @param the camera group property node. - */ - static CameraGroup* buildCameraGroup(osgViewer::Viewer* viewer, - SGPropertyNode* node); -}; - -/** Get the osg::Camera that draws the GUI, if any, from a camera - * group. - * @param cgroup the camera group - * @return the GUI camera or 0 - */ -osg::Camera* getGUICamera(CameraGroup* cgroup); -/** Choose a camera using an event and do intersection testing on its - * view of the scene. Only cameras with the DO_INTERSECTION_TEST flag - * set are considered. - * @param cgroup the CameraGroup - * @param ea the event containing a window and mouse coordinates - * @param intersections container for the result of intersection - * testing. - * @return true if any intersections are found - */ -bool computeIntersections(const CameraGroup* cgroup, - const osg::Vec2d& windowPos, - osgUtil::LineSegmentIntersector::Intersections& - intersections); -/** Warp the pointer to coordinates in the GUI camera of a camera group. - * @param cgroup the camera group - * @param x x window coordinate of pointer - * @param y y window coordinate of pointer, in "y down" coordinates. - */ -void warpGUIPointer(CameraGroup* cgroup, int x, int y); - -} - -#endif diff --git a/src/Viewer/CameraGroup_legacy.cxx b/src/Viewer/CameraGroup_legacy.cxx deleted file mode 100644 index 5b004dedf..000000000 --- a/src/Viewer/CameraGroup_legacy.cxx +++ /dev/null @@ -1,1389 +0,0 @@ -// Copyright (C) 2008 Tim Moore -// Copyright (C) 2011 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 -#endif - -#include "CameraGroup.hxx" - -#include
-#include
-#include "renderer.hxx" -#include "FGEventHandler.hxx" -#include "WindowBuilder.hxx" -#include "WindowSystemAdapter.hxx" - -#include -#include -#include // for copyProperties -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -using namespace osg; - -namespace -{ - - // Given a projection matrix, return a new one with the same frustum - // sides and new near / far values. - - void makeNewProjMat(Matrixd& oldProj, double znear, - double zfar, Matrixd& projection) - { - projection = oldProj; - // Slightly inflate the near & far planes to avoid objects at the - // extremes being clipped out. - znear *= 0.999; - zfar *= 1.001; - - // Clamp the projection matrix z values to the range (near, far) - double epsilon = 1.0e-6; - if (fabs(projection(0,3)) < epsilon && - fabs(projection(1,3)) < epsilon && - fabs(projection(2,3)) < epsilon) { - // Projection is Orthographic - epsilon = -1.0/(zfar - znear); // Used as a temp variable - projection(2,2) = 2.0*epsilon; - projection(3,2) = (zfar + znear)*epsilon; - } else { - // Projection is Perspective - double trans_near = (-znear*projection(2,2) + projection(3,2)) / - (-znear*projection(2,3) + projection(3,3)); - double trans_far = (-zfar*projection(2,2) + projection(3,2)) / - (-zfar*projection(2,3) + projection(3,3)); - double ratio = fabs(2.0/(trans_near - trans_far)); - double center = -0.5*(trans_near + trans_far); - - projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, ratio, 0.0, - 0.0, 0.0, center*ratio, 1.0)); - } - } - - osg::Matrix - invert(const osg::Matrix& matrix) - { - return osg::Matrix::inverse(matrix); - } - - /// Returns the zoom factor of the master camera. - /// The reference fov is the historic 55 deg - double - zoomFactor() - { - double fov = fgGetDouble("/sim/current-view/field-of-view", 55); - if (fov < 1) - fov = 1; - return tan(55*0.5*SG_DEGREES_TO_RADIANS)/tan(fov*0.5*SG_DEGREES_TO_RADIANS); - } - - osg::Vec2d - preMult(const osg::Vec2d& v, const osg::Matrix& m) - { - osg::Vec3d tmp = m.preMult(osg::Vec3(v, 0)); - return osg::Vec2d(tmp[0], tmp[1]); - } - - osg::Matrix - relativeProjection(const osg::Matrix& P0, const osg::Matrix& R, const osg::Vec2d ref[2], - const osg::Matrix& pP, const osg::Matrix& pR, const osg::Vec2d pRef[2]) - { - // Track the way from one projection space to the other: - // We want - // P = T*S*P0 - // where P0 is the projection template sensible for the given window size, - // T is a translation matrix and S a scale 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) = T*S*P0*R*inv(pP*pR) - // So, at first compute that matrix without T*S and determine S and T from that - - // Ok, now osg uses the inverse matrix multiplication order, thus: - osg::Matrix PtoPwithoutTS = invert(pR*pP)*R*P0; - // Compute the parents reference points in the current projection space - // without the yet unknown T and S - osg::Vec2d pRefInThis[2] = { - preMult(pRef[0], PtoPwithoutTS), - preMult(pRef[1], PtoPwithoutTS) - }; - - // To get the same zoom, rescale to match the parents size - double s = (ref[0] - ref[1]).length()/(pRefInThis[0] - pRefInThis[1]).length(); - osg::Matrix S = osg::Matrix::scale(s, s, 1); - - // For the translation offset, incorporate the now known scale - // and recompute the position ot the first reference point in the - // currents projection space without the yet unknown T. - pRefInThis[0] = preMult(pRef[0], PtoPwithoutTS*S); - // The translation is then the difference of the reference points - osg::Matrix T = osg::Matrix::translate(osg::Vec3d(ref[0] - pRefInThis[0], 0)); - - // Compose and return the desired final projection matrix - return P0*S*T; - } - -} // of anonymous namespace - -typedef std::vector SGPropertyNodeVec; - -namespace flightgear -{ -using namespace osg; - -using std::strcmp; -using std::string; - - class CameraGroupListener : public SGPropertyChangeListener - { - public: - CameraGroupListener(CameraGroup* cg, SGPropertyNode* gnode) : - _groupNode(gnode), - _cameraGroup(cg) - { - listenToNode("znear", 0.1f); - listenToNode("zfar", 120000.0f); - listenToNode("near-field", 100.0f); - } - - virtual ~CameraGroupListener() - { - unlisten("znear"); - unlisten("zfar"); - unlisten("near-field"); - } - - virtual void valueChanged(SGPropertyNode* prop) - { - if (!strcmp(prop->getName(), "znear")) { - _cameraGroup->setZNear(prop->getFloatValue()); - } else if (!strcmp(prop->getName(), "zfar")) { - _cameraGroup->setZFar(prop->getFloatValue()); - } else if (!strcmp(prop->getName(), "near-field")) { - _cameraGroup->setNearField(prop->getFloatValue()); - } - } - private: - void listenToNode(const std::string& name, double val) - { - SGPropertyNode* n = _groupNode->getChild(name); - if (!n) { - n = _groupNode->getChild(name, 0 /* index */, true); - n->setDoubleValue(val); - } - n->addChangeListener(this); - valueChanged(n); // propogate initial state through - } - - void unlisten(const std::string& name) - { - _groupNode->getChild(name)->removeChangeListener(this); - } - - SGPropertyNode_ptr _groupNode; - CameraGroup* _cameraGroup; // non-owning reference - - }; - - class CameraViewportListener : public SGPropertyChangeListener - { - public: - CameraViewportListener(CameraInfo* info, - SGPropertyNode* vnode, - const osg::GraphicsContext::Traits *traits) : - _viewportNode(vnode), - _camera(info) - { - listenToNode("x", 0.0f); - listenToNode("y", 0.0f); - listenToNode("width", traits->width); - listenToNode("height", traits->height); - } - - virtual ~CameraViewportListener() - { - unlisten("x"); - unlisten("y"); - unlisten("width"); - unlisten("height"); - } - - virtual void valueChanged(SGPropertyNode* prop) - { - if (!strcmp(prop->getName(), "x")) { - _camera->x = prop->getDoubleValue(); - } else if (!strcmp(prop->getName(), "y")) { - _camera->y = prop->getDoubleValue(); - } else if (!strcmp(prop->getName(), "width")) { - _camera->width = prop->getDoubleValue(); - } else if (!strcmp(prop->getName(), "height")) { - _camera->height = prop->getDoubleValue(); - } - } - private: - void listenToNode(const std::string& name, double val) - { - SGPropertyNode* n = _viewportNode->getChild(name); - if (!n) { - n = _viewportNode->getChild(name, 0 /* index */, true); - n->setDoubleValue(val); - } - n->addChangeListener(this); - valueChanged(n); // propogate initial state through - } - - void unlisten(const std::string& name) - { - _viewportNode->getChild(name)->removeChangeListener(this); - } - - SGPropertyNode_ptr _viewportNode; - CameraInfo* _camera; - - }; - - const char* MAIN_CAMERA = "main"; - const char* FAR_CAMERA = "far"; - const char* GEOMETRY_CAMERA = "geometry"; - const char* SHADOW_CAMERA = "shadow"; - const char* LIGHTING_CAMERA = "lighting"; - const char* DISPLAY_CAMERA = "display"; - -void CameraInfo::updateCameras() -{ - bufferSize->set( osg::Vec2f( width, height ) ); - - for (CameraMap::iterator ii = cameras.begin(); ii != cameras.end(); ++ii ) { - float f = ii->second.scaleFactor; - if ( f == 0.0f ) continue; - - if (ii->second.camera->getRenderTargetImplementation() == osg::Camera::FRAME_BUFFER_OBJECT) - ii->second.camera->getViewport()->setViewport(0, 0, width*f, height*f); - else - ii->second.camera->getViewport()->setViewport(x*f, y*f, width*f, height*f); - } - - for (RenderBufferMap::iterator ii = buffers.begin(); ii != buffers.end(); ++ii ) { - float f = ii->second.scaleFactor; - if ( f == 0.0f ) continue; - osg::Texture2D* texture = ii->second.texture.get(); - if ( texture->getTextureHeight() != height*f || texture->getTextureWidth() != width*f ) { - texture->setTextureSize( width*f, height*f ); - texture->dirtyTextureObject(); - } - } -} - -void CameraInfo::resized(double w, double h) -{ - if (w == 1.0 && h == 1.0) - return; - - bufferSize->set( osg::Vec2f( w, h ) ); - - for (RenderBufferMap::iterator ii = buffers.begin(); ii != buffers.end(); ++ii) { - float s = ii->second.scaleFactor; - if ( s == 0.0f ) continue; - ii->second.texture->setTextureSize( w * s, h * s ); - ii->second.texture->dirtyTextureObject(); - } - - for (CameraMap::iterator ii = cameras.begin(); ii != cameras.end(); ++ii) { - RenderStageInfo& rsi = ii->second; - if (!rsi.resizable || - rsi.camera->getRenderTargetImplementation() != osg::Camera::FRAME_BUFFER_OBJECT || - rsi.scaleFactor == 0.0f ) - continue; - - Viewport* vp = rsi.camera->getViewport(); - vp->width() = w * rsi.scaleFactor; - vp->height() = h * rsi.scaleFactor; - - osgViewer::Renderer* renderer - = static_cast(rsi.camera->getRenderer()); - for (int i = 0; i < 2; ++i) { - osgUtil::SceneView* sceneView = renderer->getSceneView(i); - sceneView->getRenderStage()->setFrameBufferObject(0); - sceneView->getRenderStage()->setCameraRequiresSetUp(true); - if (sceneView->getRenderStageLeft()) { - sceneView->getRenderStageLeft()->setFrameBufferObject(0); - sceneView->getRenderStageLeft()->setCameraRequiresSetUp(true); - } - if (sceneView->getRenderStageRight()) { - sceneView->getRenderStageRight()->setFrameBufferObject(0); - sceneView->getRenderStageRight()->setCameraRequiresSetUp(true); - } - } - } -} - -CameraInfo::~CameraInfo() -{ - delete viewportListener; -} - -osg::Camera* CameraInfo::getCamera(const std::string& k) const -{ - CameraMap::const_iterator ii = cameras.find( k ); - if (ii == cameras.end()) - return 0; - return ii->second.camera.get(); -} - -osg::Texture2D* CameraInfo::getBuffer(const std::string& k) const -{ - RenderBufferMap::const_iterator ii = buffers.find(k); - if (ii == buffers.end()) - return 0; - return ii->second.texture.get(); -} - -int CameraInfo::getMainSlaveIndex() const -{ - return cameras.find( MAIN_CAMERA )->second.slaveIndex; -} - -void CameraInfo::setMatrices(osg::Camera* c) -{ - view->set( c->getViewMatrix() ); - osg::Matrixd vi = c->getInverseViewMatrix(); - viewInverse->set( vi ); - projInverse->set( osg::Matrix::inverse( c->getProjectionMatrix() ) ); - osg::Vec4d pos = osg::Vec4d(0., 0., 0., 1.) * vi; - worldPosCart->set( osg::Vec3f( pos.x(), pos.y(), pos.z() ) ); - SGGeod pos2 = SGGeod::fromCart( SGVec3d( pos.x(), pos.y(), pos.z() ) ); - worldPosGeod->set( osg::Vec3f( pos2.getLongitudeRad(), pos2.getLatitudeRad(), pos2.getElevationM() ) ); -} - -CameraGroup::~CameraGroup() -{ - - for (CameraList::iterator i = _cameras.begin(); i != _cameras.end(); ++i) { - CameraInfo* info = *i; - for (CameraMap::iterator ii = info->cameras.begin(); ii != info->cameras.end(); ++ii) { - RenderStageInfo& rsi = ii->second; - unsigned int slaveIndex = _viewer->findSlaveIndexForCamera(rsi.camera); - _viewer->removeSlave(slaveIndex); - } - } - - _cameras.clear(); -} - -void CameraGroup::update(const osg::Vec3d& position, - const osg::Quat& orientation) -{ - const Matrix masterView(osg::Matrix::translate(-position) - * osg::Matrix::rotate(orientation.inverse())); - _viewer->getCamera()->setViewMatrix(masterView); - const Matrix& masterProj = _viewer->getCamera()->getProjectionMatrix(); - double masterZoomFactor = zoomFactor(); - for (CameraList::iterator i = _cameras.begin(); i != _cameras.end(); ++i) { - const CameraInfo* info = i->get(); - - Camera* camera = info->getCamera(MAIN_CAMERA); - if ( camera ) { - const osg::View::Slave& slave = _viewer->getSlave(info->getMainSlaveIndex()); - - Matrix viewMatrix; - if (info->flags & GUI) { - viewMatrix = osg::Matrix(); // identifty transform on the GUI camera - } else if ((info->flags & VIEW_ABSOLUTE) != 0) - viewMatrix = slave._viewOffset; - else - viewMatrix = masterView * slave._viewOffset; - camera->setViewMatrix(viewMatrix); - Matrix projectionMatrix; - if (info->flags & GUI) { - projectionMatrix = osg::Matrix::ortho2D(0, info->width, 0, info->height); - } else if ((info->flags & PROJECTION_ABSOLUTE) != 0) { - if (info->flags & ENABLE_MASTER_ZOOM) { - if (info->relativeCameraParent < _cameras.size()) { - // template projection matrix and view matrix of the current camera - osg::Matrix P0 = slave._projectionOffset; - osg::Matrix R = viewMatrix; - - // The already known projection and view matrix of the parent camera - const CameraInfo* parentInfo = _cameras[info->relativeCameraParent].get(); - RenderStageInfo prsi = parentInfo->cameras.find(MAIN_CAMERA)->second; - osg::Matrix pP = prsi.camera->getProjectionMatrix(); - osg::Matrix pR = prsi.camera->getViewMatrix(); - - // And the projection matrix derived from P0 so that the reference points match - projectionMatrix = relativeProjection(P0, R, info->thisReference, - pP, pR, info->parentReference); - - } else { - // We want to zoom, so take the original matrix and apply the zoom to it. - projectionMatrix = slave._projectionOffset; - projectionMatrix.postMultScale(osg::Vec3d(masterZoomFactor, masterZoomFactor, 1)); - } - } else { - projectionMatrix = slave._projectionOffset; - } - } else { - projectionMatrix = masterProj * slave._projectionOffset; - } - - CameraMap::const_iterator ii = info->cameras.find(FAR_CAMERA); - if (ii == info->cameras.end() || !ii->second.camera.valid()) { - camera->setProjectionMatrix(projectionMatrix); - } else { - Camera* farCamera = ii->second.camera; - farCamera->setViewMatrix(viewMatrix); - double left, right, bottom, top, parentNear, parentFar; - projectionMatrix.getFrustum(left, right, bottom, top, - parentNear, parentFar); - if ((info->flags & FIXED_NEAR_FAR) == 0) { - parentNear = _zNear; - parentFar = _zFar; - } - if (parentFar < _nearField || _nearField == 0.0f) { - camera->setProjectionMatrix(projectionMatrix); - camera->setCullMask(camera->getCullMask() - | simgear::BACKGROUND_BIT); - camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - farCamera->setNodeMask(0); - } else { - Matrix nearProj, farProj; - makeNewProjMat(projectionMatrix, parentNear, _nearField, - nearProj); - makeNewProjMat(projectionMatrix, _nearField, parentFar, - farProj); - camera->setProjectionMatrix(nearProj); - camera->setCullMask(camera->getCullMask() - & ~simgear::BACKGROUND_BIT); - camera->setClearMask(GL_DEPTH_BUFFER_BIT); - farCamera->setProjectionMatrix(farProj); - farCamera->setNodeMask(camera->getNodeMask()); - } - } - } else { - bool viewDone = false; - Matrix viewMatrix; - bool projectionDone = false; - Matrix projectionMatrix; - for ( CameraMap::const_iterator ii = info->cameras.begin(); ii != info->cameras.end(); ++ii ) { - if ( ii->first == SHADOW_CAMERA ) { - globals->get_renderer()->updateShadowCamera(info, position); - continue; - } - if ( ii->second.fullscreen ) - continue; - - Camera* camera = ii->second.camera.get(); - int slaveIndex = ii->second.slaveIndex; - const osg::View::Slave& slave = _viewer->getSlave(slaveIndex); - - if ( !viewDone ) { - if ((info->flags & VIEW_ABSOLUTE) != 0) - viewMatrix = slave._viewOffset; - else - viewMatrix = masterView * slave._viewOffset; - viewDone = true; - } - - camera->setViewMatrix( viewMatrix ); - - if ( !projectionDone ) { - if ((info->flags & PROJECTION_ABSOLUTE) != 0) { - if (info->flags & ENABLE_MASTER_ZOOM) { - if (info->relativeCameraParent < _cameras.size()) { - // template projection matrix and view matrix of the current camera - osg::Matrix P0 = slave._projectionOffset; - osg::Matrix R = viewMatrix; - - // The already known projection and view matrix of the parent camera - const CameraInfo* parentInfo = _cameras[info->relativeCameraParent].get(); - RenderStageInfo prsi = parentInfo->cameras.find(MAIN_CAMERA)->second; - osg::Matrix pP = prsi.camera->getProjectionMatrix(); - osg::Matrix pR = prsi.camera->getViewMatrix(); - - // And the projection matrix derived from P0 so that the reference points match - projectionMatrix = relativeProjection(P0, R, info->thisReference, - pP, pR, info->parentReference); - - } else { - // We want to zoom, so take the original matrix and apply the zoom to it. - projectionMatrix = slave._projectionOffset; - projectionMatrix.postMultScale(osg::Vec3d(masterZoomFactor, masterZoomFactor, 1)); - } - } else { - projectionMatrix = slave._projectionOffset; - } - } else { - projectionMatrix = masterProj * slave._projectionOffset; - } - projectionDone = true; - } - - camera->setProjectionMatrix(projectionMatrix); - } - } - } - - globals->get_renderer()->setPlanes( _zNear, _zFar ); -} - -ref_ptr CameraGroup::_defaultGroup; - -CameraGroup::CameraGroup(osgViewer::Viewer* viewer) : -_viewer(viewer) -{ -} - -void CameraGroup::setCameraParameters(float vfov, float aspectRatio) -{ - if (vfov != 0.0f && aspectRatio != 0.0f) - _viewer->getCamera() - ->setProjectionMatrixAsPerspective(vfov, - 1.0f / aspectRatio, - _zNear, _zFar); -} - -double CameraGroup::getMasterAspectRatio() const -{ - if (_cameras.empty()) - return 0.0; - - const CameraInfo* info = _cameras.front(); - - osg::Camera* camera = info->getCamera(MAIN_CAMERA); - if ( !camera ) - camera = info->getCamera( GEOMETRY_CAMERA ); - const osg::Viewport* viewport = camera->getViewport(); - if (!viewport) { - return 0.0; - } - - return static_cast(viewport->height()) / viewport->width(); -} - -// Mostly copied from osg's osgViewer/View.cpp - -static osg::Geometry* createPanoramicSphericalDisplayDistortionMesh( - const Vec3& origin, const Vec3& widthVector, const Vec3& heightVector, - double sphere_radius, double collar_radius, - Image* intensityMap = 0, const Matrix& projectorMatrix = Matrix()) -{ - osg::Vec3d center(0.0,0.0,0.0); - osg::Vec3d eye(0.0,0.0,0.0); - - double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius); - bool flip = false; - bool texcoord_flip = false; - -#if 0 - osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance); - - OSG_INFO<<"createPanoramicSphericalDisplayDistortionMesh : Projector position = "<getStringValue(); - TextureMap::iterator itr = _textureTargets.find(texName); - if (itr == _textureTargets.end()) { - // error - return; - } - Viewport* viewport = camera->getViewport(); - float width = viewport->width(); - float height = viewport->height(); - TextureRectangle* texRect = itr->second.get(); - double radius = psNode->getDoubleValue("radius", 1.0); - double collar = psNode->getDoubleValue("collar", 0.45); - Geode* geode = new Geode(); - geode->addDrawable(createPanoramicSphericalDisplayDistortionMesh( - Vec3(0.0f,0.0f,0.0f), Vec3(width,0.0f,0.0f), - Vec3(0.0f,height,0.0f), radius, collar)); - - // new we need to add the texture to the mesh, we do so by creating a - // StateSet to contain the Texture StateAttribute. - StateSet* stateset = geode->getOrCreateStateSet(); - stateset->setTextureAttributeAndModes(0, texRect, StateAttribute::ON); - stateset->setMode(GL_LIGHTING, StateAttribute::OFF); - - TexMat* texmat = new TexMat; - texmat->setScaleByTextureRectangleSize(true); - stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON); -#if 0 - if (!applyIntensityMapAsColours && intensityMap) - { - stateset->setTextureAttributeAndModes(1, new osg::Texture2D(intensityMap), osg::StateAttribute::ON); - } -#endif - // add subgraph to render - camera->addChild(geode); - camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0)); - camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); - camera->setCullingMode(osg::CullSettings::NO_CULLING); - camera->setName("DistortionCorrectionCamera"); -} - -CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode) -{ - WindowBuilder *wBuild = WindowBuilder::getWindowBuilder(); - const SGPropertyNode* windowNode = cameraNode->getNode("window"); - GraphicsWindow* window = 0; - int cameraFlags = DO_INTERSECTION_TEST; - if (windowNode) { - // New style window declaration / definition - window = wBuild->buildWindow(windowNode); - } else { - // Old style: suck window params out of camera block - window = wBuild->buildWindow(cameraNode); - } - if (!window) { - return 0; - } - Camera* camera = new Camera; - camera->setName("windowCamera"); - camera->setAllowEventFocus(false); - camera->setGraphicsContext(window->gc.get()); - camera->setViewport(new Viewport); - camera->setCullingMode(CullSettings::SMALL_FEATURE_CULLING - | CullSettings::VIEW_FRUSTUM_CULLING); - camera->setInheritanceMask(CullSettings::ALL_VARIABLES - & ~(CullSettings::CULL_MASK - | CullSettings::CULLING_MODE - | CullSettings::CLEAR_MASK - )); - - osg::Matrix vOff; - const SGPropertyNode* viewNode = cameraNode->getNode("view"); - if (viewNode) { - double heading = viewNode->getDoubleValue("heading-deg", 0.0); - double pitch = viewNode->getDoubleValue("pitch-deg", 0.0); - double roll = viewNode->getDoubleValue("roll-deg", 0.0); - double x = viewNode->getDoubleValue("x", 0.0); - double y = viewNode->getDoubleValue("y", 0.0); - double z = viewNode->getDoubleValue("z", 0.0); - // Build a view matrix, which is the inverse of a model - // orientation matrix. - vOff = (Matrix::translate(-x, -y, -z) - * Matrix::rotate(-DegreesToRadians(heading), - Vec3d(0.0, 1.0, 0.0), - -DegreesToRadians(pitch), - Vec3d(1.0, 0.0, 0.0), - -DegreesToRadians(roll), - Vec3d(0.0, 0.0, 1.0))); - if (viewNode->getBoolValue("absolute", false)) - cameraFlags |= VIEW_ABSOLUTE; - } else { - // Old heading parameter, works in the opposite direction - double heading = cameraNode->getDoubleValue("heading-deg", 0.0); - vOff.makeRotate(DegreesToRadians(heading), osg::Vec3(0, 1, 0)); - } - // Configuring the physical dimensions of a monitor - SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true); - double physicalWidth = viewportNode->getDoubleValue("width", 1024); - double physicalHeight = viewportNode->getDoubleValue("height", 768); - double bezelHeightTop = 0; - double bezelHeightBottom = 0; - double bezelWidthLeft = 0; - double bezelWidthRight = 0; - const SGPropertyNode* physicalDimensionsNode = 0; - if ((physicalDimensionsNode = cameraNode->getNode("physical-dimensions")) != 0) { - physicalWidth = physicalDimensionsNode->getDoubleValue("width", physicalWidth); - physicalHeight = physicalDimensionsNode->getDoubleValue("height", physicalHeight); - const SGPropertyNode* bezelNode = 0; - if ((bezelNode = physicalDimensionsNode->getNode("bezel")) != 0) { - bezelHeightTop = bezelNode->getDoubleValue("top", bezelHeightTop); - bezelHeightBottom = bezelNode->getDoubleValue("bottom", bezelHeightBottom); - bezelWidthLeft = bezelNode->getDoubleValue("left", bezelWidthLeft); - bezelWidthRight = bezelNode->getDoubleValue("right", bezelWidthRight); - } - } - osg::Matrix pOff; - unsigned parentCameraIndex = ~0u; - osg::Vec2d parentReference[2]; - osg::Vec2d thisReference[2]; - SGPropertyNode* projectionNode = 0; - if ((projectionNode = cameraNode->getNode("perspective")) != 0) { - double fovy = projectionNode->getDoubleValue("fovy-deg", 55.0); - double aspectRatio = projectionNode->getDoubleValue("aspect-ratio", - 1.0); - double zNear = projectionNode->getDoubleValue("near", 0.0); - double zFar = projectionNode->getDoubleValue("far", zNear + 20000); - double offsetX = projectionNode->getDoubleValue("offset-x", 0.0); - double offsetY = projectionNode->getDoubleValue("offset-y", 0.0); - double tan_fovy = tan(DegreesToRadians(fovy*0.5)); - double right = tan_fovy * aspectRatio * zNear + offsetX; - double left = -tan_fovy * aspectRatio * zNear + offsetX; - double top = tan_fovy * zNear + offsetY; - double bottom = -tan_fovy * zNear + offsetY; - pOff.makeFrustum(left, right, bottom, top, zNear, zFar); - cameraFlags |= PROJECTION_ABSOLUTE; - if (projectionNode->getBoolValue("fixed-near-far", true)) - cameraFlags |= FIXED_NEAR_FAR; - } else if ((projectionNode = cameraNode->getNode("frustum")) != 0 - || (projectionNode = cameraNode->getNode("ortho")) != 0) { - double top = projectionNode->getDoubleValue("top", 0.0); - double bottom = projectionNode->getDoubleValue("bottom", 0.0); - double left = projectionNode->getDoubleValue("left", 0.0); - double right = projectionNode->getDoubleValue("right", 0.0); - double zNear = projectionNode->getDoubleValue("near", 0.0); - double zFar = projectionNode->getDoubleValue("far", zNear + 20000); - if (cameraNode->getNode("frustum")) { - pOff.makeFrustum(left, right, bottom, top, zNear, zFar); - cameraFlags |= PROJECTION_ABSOLUTE; - } else { - pOff.makeOrtho(left, right, bottom, top, zNear, zFar); - cameraFlags |= (PROJECTION_ABSOLUTE | ORTHO); - } - if (projectionNode->getBoolValue("fixed-near-far", true)) - cameraFlags |= FIXED_NEAR_FAR; - } else if ((projectionNode = cameraNode->getNode("master-perspective")) != 0) { - double zNear = projectionNode->getDoubleValue("eye-distance", 0.4*physicalWidth); - double xoff = projectionNode->getDoubleValue("x-offset", 0); - double yoff = projectionNode->getDoubleValue("y-offset", 0); - double left = -0.5*physicalWidth - xoff; - double right = 0.5*physicalWidth - xoff; - double bottom = -0.5*physicalHeight - yoff; - double top = 0.5*physicalHeight - yoff; - pOff.makeFrustum(left, right, bottom, top, zNear, zNear*1000); - cameraFlags |= PROJECTION_ABSOLUTE | ENABLE_MASTER_ZOOM; - } else if ((projectionNode = cameraNode->getNode("right-of-perspective")) - || (projectionNode = cameraNode->getNode("left-of-perspective")) - || (projectionNode = cameraNode->getNode("above-perspective")) - || (projectionNode = cameraNode->getNode("below-perspective")) - || (projectionNode = cameraNode->getNode("reference-points-perspective"))) { - std::string name = projectionNode->getStringValue("parent-camera"); - for (unsigned i = 0; i < _cameras.size(); ++i) { - if (_cameras[i]->name != name) - continue; - parentCameraIndex = i; - } - if (_cameras.size() <= parentCameraIndex) { - SG_LOG(SG_VIEW, SG_ALERT, "CameraGroup::buildCamera: " - "failed to find parent camera for relative camera!"); - return 0; - } - const CameraInfo* parentInfo = _cameras[parentCameraIndex].get(); - if (projectionNode->getNameString() == "right-of-perspective") { - double tmp = (parentInfo->physicalWidth + 2*parentInfo->bezelWidthRight)/parentInfo->physicalWidth; - parentReference[0] = osg::Vec2d(tmp, -1); - parentReference[1] = osg::Vec2d(tmp, 1); - tmp = (physicalWidth + 2*bezelWidthLeft)/physicalWidth; - thisReference[0] = osg::Vec2d(-tmp, -1); - thisReference[1] = osg::Vec2d(-tmp, 1); - } else if (projectionNode->getNameString() == "left-of-perspective") { - double tmp = (parentInfo->physicalWidth + 2*parentInfo->bezelWidthLeft)/parentInfo->physicalWidth; - parentReference[0] = osg::Vec2d(-tmp, -1); - parentReference[1] = osg::Vec2d(-tmp, 1); - tmp = (physicalWidth + 2*bezelWidthRight)/physicalWidth; - thisReference[0] = osg::Vec2d(tmp, -1); - thisReference[1] = osg::Vec2d(tmp, 1); - } else if (projectionNode->getNameString() == "above-perspective") { - double tmp = (parentInfo->physicalHeight + 2*parentInfo->bezelHeightTop)/parentInfo->physicalHeight; - parentReference[0] = osg::Vec2d(-1, tmp); - parentReference[1] = osg::Vec2d(1, tmp); - tmp = (physicalHeight + 2*bezelHeightBottom)/physicalHeight; - thisReference[0] = osg::Vec2d(-1, -tmp); - thisReference[1] = osg::Vec2d(1, -tmp); - } else if (projectionNode->getNameString() == "below-perspective") { - double tmp = (parentInfo->physicalHeight + 2*parentInfo->bezelHeightBottom)/parentInfo->physicalHeight; - parentReference[0] = osg::Vec2d(-1, -tmp); - parentReference[1] = osg::Vec2d(1, -tmp); - tmp = (physicalHeight + 2*bezelHeightTop)/physicalHeight; - thisReference[0] = osg::Vec2d(-1, tmp); - thisReference[1] = osg::Vec2d(1, tmp); - } else if (projectionNode->getNameString() == "reference-points-perspective") { - SGPropertyNode* parentNode = projectionNode->getNode("parent", true); - SGPropertyNode* thisNode = projectionNode->getNode("this", true); - SGPropertyNode* pointNode; - - pointNode = parentNode->getNode("point", 0, true); - parentReference[0][0] = pointNode->getDoubleValue("x", 0)*2/parentInfo->physicalWidth; - parentReference[0][1] = pointNode->getDoubleValue("y", 0)*2/parentInfo->physicalHeight; - pointNode = parentNode->getNode("point", 1, true); - parentReference[1][0] = pointNode->getDoubleValue("x", 0)*2/parentInfo->physicalWidth; - parentReference[1][1] = pointNode->getDoubleValue("y", 0)*2/parentInfo->physicalHeight; - - pointNode = thisNode->getNode("point", 0, true); - thisReference[0][0] = pointNode->getDoubleValue("x", 0)*2/physicalWidth; - thisReference[0][1] = pointNode->getDoubleValue("y", 0)*2/physicalHeight; - pointNode = thisNode->getNode("point", 1, true); - thisReference[1][0] = pointNode->getDoubleValue("x", 0)*2/physicalWidth; - thisReference[1][1] = pointNode->getDoubleValue("y", 0)*2/physicalHeight; - } - - pOff = osg::Matrix::perspective(45, physicalWidth/physicalHeight, 1, 20000); - cameraFlags |= PROJECTION_ABSOLUTE | ENABLE_MASTER_ZOOM; - } else { - // old style shear parameters - double shearx = cameraNode->getDoubleValue("shear-x", 0); - double sheary = cameraNode->getDoubleValue("shear-y", 0); - pOff.makeTranslate(-shearx, -sheary, 0); - } - const SGPropertyNode* textureNode = cameraNode->getNode("texture"); - if (textureNode) { - string texName = textureNode->getStringValue("name"); - int tex_width = textureNode->getIntValue("width"); - int tex_height = textureNode->getIntValue("height"); - TextureRectangle* texture = new TextureRectangle; - - texture->setTextureSize(tex_width, tex_height); - texture->setInternalFormat(GL_RGB); - texture->setFilter(Texture::MIN_FILTER, Texture::LINEAR); - texture->setFilter(Texture::MAG_FILTER, Texture::LINEAR); - texture->setWrap(Texture::WRAP_S, Texture::CLAMP_TO_EDGE); - texture->setWrap(Texture::WRAP_T, Texture::CLAMP_TO_EDGE); - camera->setDrawBuffer(GL_FRONT); - camera->setReadBuffer(GL_FRONT); - camera->setRenderTargetImplementation(Camera::FRAME_BUFFER_OBJECT); - camera->attach(Camera::COLOR_BUFFER, texture); - _textureTargets[texName] = texture; - } else { - camera->setDrawBuffer(GL_BACK); - camera->setReadBuffer(GL_BACK); - } - const SGPropertyNode* psNode = cameraNode->getNode("panoramic-spherical"); - bool useMasterSceneGraph = !psNode; - CameraInfo* info = globals->get_renderer()->buildRenderingPipeline(this, cameraFlags, camera, vOff, pOff, - window->gc.get(), useMasterSceneGraph); - - info->name = cameraNode->getStringValue("name"); - info->physicalWidth = physicalWidth; - info->physicalHeight = physicalHeight; - info->bezelHeightTop = bezelHeightTop; - info->bezelHeightBottom = bezelHeightBottom; - info->bezelWidthLeft = bezelWidthLeft; - info->bezelWidthRight = bezelWidthRight; - info->relativeCameraParent = parentCameraIndex; - info->parentReference[0] = parentReference[0]; - info->parentReference[1] = parentReference[1]; - info->thisReference[0] = thisReference[0]; - info->thisReference[1] = thisReference[1]; - - // If a viewport isn't set on the camera, then it's hard to dig it - // out of the SceneView objects in the viewer, and the coordinates - // of mouse events are somewhat bizzare. - - info->viewportListener = new CameraViewportListener(info, viewportNode, window->gc->getTraits()); - - info->updateCameras(); - // Distortion camera needs the viewport which is created by addCamera(). - if (psNode) { - info->flags = info->flags | VIEW_ABSOLUTE; - buildDistortionCamera(psNode, camera); - } - return info; -} - -CameraInfo* CameraGroup::buildGUICamera(SGPropertyNode* cameraNode, - GraphicsWindow* window) -{ - WindowBuilder *wBuild = WindowBuilder::getWindowBuilder(); - const SGPropertyNode* windowNode = (cameraNode - ? cameraNode->getNode("window") - : 0); - if (!window && windowNode) { - // New style window declaration / definition - window = wBuild->buildWindow(windowNode); - } - - if (!window) { // buildWindow can fail - SG_LOG(SG_VIEW, SG_WARN, "CameraGroup::buildGUICamera: failed to build a window"); - return NULL; - } - - Camera* camera = new Camera; - camera->setName( "GUICamera" ); - camera->setAllowEventFocus(false); - camera->setGraphicsContext(window->gc.get()); - camera->setViewport(new Viewport); - camera->setClearMask(0); - camera->setInheritanceMask(CullSettings::ALL_VARIABLES - & ~(CullSettings::COMPUTE_NEAR_FAR_MODE - | CullSettings::CULLING_MODE - | CullSettings::CLEAR_MASK - )); - camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); - camera->setCullingMode(osg::CullSettings::NO_CULLING); - camera->setProjectionResizePolicy(Camera::FIXED); - camera->setReferenceFrame(Transform::ABSOLUTE_RF); - const int cameraFlags = GUI | DO_INTERSECTION_TEST; - - CameraInfo* result = new CameraInfo(cameraFlags); - result->name = "GUI camera"; - // The camera group will always update the camera - camera->setReferenceFrame(Transform::ABSOLUTE_RF); - - // Draw all nodes in the order they are added to the GUI camera - camera->getOrCreateStateSet() - ->setRenderBinDetails( 0, - "PreOrderBin", - osg::StateSet::OVERRIDE_RENDERBIN_DETAILS ); - - getViewer()->addSlave(camera, Matrixd::identity(), Matrixd::identity(), false); - //installCullVisitor(camera); - int slaveIndex = getViewer()->getNumSlaves() - 1; - result->addCamera( MAIN_CAMERA, camera, slaveIndex ); - camera->setRenderOrder(Camera::POST_RENDER, slaveIndex); - addCamera(result); - - // XXX Camera needs to be drawn last; eventually the render order - // should be assigned by a camera manager. - camera->setRenderOrder(osg::Camera::POST_RENDER, 10000); - SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true); - - result->viewportListener = new CameraViewportListener(result, viewportNode, - window->gc->getTraits()); - - // Disable statistics for the GUI camera. - camera->setStats(0); - result->updateCameras(); - return result; -} - -CameraGroup* CameraGroup::buildCameraGroup(osgViewer::Viewer* viewer, - SGPropertyNode* gnode) -{ - CameraGroup* cgroup = new CameraGroup(viewer); - cgroup->_listener.reset(new CameraGroupListener(cgroup, gnode)); - - for (int i = 0; i < gnode->nChildren(); ++i) { - SGPropertyNode* pNode = gnode->getChild(i); - const char* name = pNode->getName(); - if (!strcmp(name, "camera")) { - cgroup->buildCamera(pNode); - } else if (!strcmp(name, "window")) { - WindowBuilder::getWindowBuilder()->buildWindow(pNode); - } else if (!strcmp(name, "gui")) { - cgroup->buildGUICamera(pNode); - } - } - - return cgroup; -} - -void CameraGroup::setCameraCullMasks(Node::NodeMask nm) -{ - for (CameraIterator i = camerasBegin(), e = camerasEnd(); i != e; ++i) { - CameraInfo* info = i->get(); - if (info->flags & GUI) - continue; - osg::ref_ptr farCamera = info->getCamera(FAR_CAMERA); - osg::Camera* camera = info->getCamera( MAIN_CAMERA ); - if (camera) { - if (farCamera.valid() && farCamera->getNodeMask() != 0) { - camera->setCullMask(nm & ~simgear::BACKGROUND_BIT); - camera->setCullMaskLeft(nm & ~simgear::BACKGROUND_BIT); - camera->setCullMaskRight(nm & ~simgear::BACKGROUND_BIT); - farCamera->setCullMask(nm); - farCamera->setCullMaskLeft(nm); - farCamera->setCullMaskRight(nm); - } else { - camera->setCullMask(nm); - camera->setCullMaskLeft(nm); - camera->setCullMaskRight(nm); - } - } else { - camera = info->getCamera( GEOMETRY_CAMERA ); - if (camera == 0) continue; - camera->setCullMask( nm & ~simgear::MODELLIGHT_BIT ); - - camera = info->getCamera( LIGHTING_CAMERA ); - if (camera == 0) continue; - osg::Switch* sw = camera->getChild(0)->asSwitch(); - for (unsigned int i = 0; i < sw->getNumChildren(); ++i) { - osg::Camera* lc = dynamic_cast(sw->getChild(i)); - if (lc == 0) continue; - string name = lc->getName(); - if (name == "LightCamera") { - lc->setCullMask( (nm & simgear::LIGHTS_BITS) | (lc->getCullMask() & ~simgear::LIGHTS_BITS) ); - } - } - } - } -} - -void CameraGroup::resized() -{ - for (CameraIterator i = camerasBegin(), e = camerasEnd(); i != e; ++i) { - CameraInfo *info = i->get(); - Camera* camera = info->getCamera( MAIN_CAMERA ); - if ( camera == 0 ) - camera = info->getCamera( DISPLAY_CAMERA ); - const Viewport* viewport = camera->getViewport(); - info->x = viewport->x(); - info->y = viewport->y(); - info->width = viewport->width(); - info->height = viewport->height(); - - info->resized( info->width, info->height ); - } -} - -const CameraInfo* CameraGroup::getGUICamera() const -{ - auto result = std::find_if(camerasBegin(), camerasEnd(), - [](const osg::ref_ptr& cam) { - return cam->flags & GUI; - }); - - if (result == camerasEnd()) { - return nullptr; - } - - return *result; -} - -Camera* getGUICamera(CameraGroup* cgroup) -{ - if (!cgroup) - return nullptr; - - const CameraInfo* info = cgroup->getGUICamera(); - if (!info) { - return nullptr; - } - - return info->getCamera(MAIN_CAMERA); -} - - -static bool computeCameraIntersection(const CameraInfo* cinfo, const osg::Vec2d& windowPos, - osgUtil::LineSegmentIntersector::Intersections& intersections) -{ - using osgUtil::Intersector; - using osgUtil::LineSegmentIntersector; - - if (!(cinfo->flags & CameraGroup::DO_INTERSECTION_TEST)) - return false; - - const Camera* camera = cinfo->getCamera(MAIN_CAMERA); - if ( !camera ) - camera = cinfo->getCamera( GEOMETRY_CAMERA ); - - // if (camera->getGraphicsContext() != ea->getGraphicsContext()) - // return false; - - const Viewport* viewport = camera->getViewport(); - SGRect viewportRect(viewport->x(), viewport->y(), - viewport->x() + viewport->width() - 1.0, - viewport->y() + viewport->height()- 1.0); - - double epsilon = 0.5; - if (!viewportRect.contains(windowPos.x(), windowPos.y(), epsilon)) - return false; - - Vec4d start(windowPos.x(), windowPos.y(), 0.0, 1.0); - Vec4d end(windowPos.x(), windowPos.y(), 1.0, 1.0); - Matrix windowMat = viewport->computeWindowMatrix(); - Matrix startPtMat = Matrix::inverse(camera->getProjectionMatrix() - * windowMat); - Matrix endPtMat; - const Camera* farCamera = cinfo->getCamera( FAR_CAMERA ); - if (!farCamera || farCamera->getNodeMask() == 0) - endPtMat = startPtMat; - else - endPtMat = Matrix::inverse(farCamera->getProjectionMatrix() - * windowMat); - start = start * startPtMat; - start /= start.w(); - end = end * endPtMat; - end /= end.w(); - ref_ptr picker - = new LineSegmentIntersector(Intersector::VIEW, - Vec3d(start.x(), start.y(), start.z()), - Vec3d(end.x(), end.y(), end.z())); - osgUtil::IntersectionVisitor iv(picker.get()); - iv.setTraversalMask( simgear::PICK_BIT ); - - const_cast(camera)->accept(iv); - if (picker->containsIntersections()) { - intersections = picker->getIntersections(); - return true; - } - - return false; -} - -bool computeIntersections(const CameraGroup* cgroup, - const osg::Vec2d& windowPos, - osgUtil::LineSegmentIntersector::Intersections& intersections) -{ - // test the GUI first - const CameraInfo* guiCamera = cgroup->getGUICamera(); - if (guiCamera && computeCameraIntersection(guiCamera, windowPos, intersections)) - return true; - - // Find camera that contains event - for (CameraGroup::ConstCameraIterator iter = cgroup->camerasBegin(), - e = cgroup->camerasEnd(); - iter != e; - ++iter) { - const CameraInfo* cinfo = iter->get(); - if (cinfo == guiCamera) - continue; - - if (computeCameraIntersection(cinfo, windowPos, intersections)) - return true; - } - - intersections.clear(); - return false; -} - -void warpGUIPointer(CameraGroup* cgroup, int x, int y) -{ - using osgViewer::GraphicsWindow; - Camera* guiCamera = getGUICamera(cgroup); - if (!guiCamera) - return; - Viewport* vport = guiCamera->getViewport(); - GraphicsWindow* gw - = dynamic_cast(guiCamera->getGraphicsContext()); - if (!gw) - return; - globals->get_renderer()->getEventHandler()->setMouseWarped(); - // Translate the warp request into the viewport of the GUI camera, - // send the request to the window, then transform the coordinates - // for the Viewer's event queue. - double wx = x + vport->x(); - double wyUp = vport->height() + vport->y() - y; - double wy; - const GraphicsContext::Traits* traits = gw->getTraits(); - if (gw->getEventQueue()->getCurrentEventState()->getMouseYOrientation() - == osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS) { - wy = traits->height - wyUp; - } else { - wy = wyUp; - } - gw->getEventQueue()->mouseWarped(wx, wy); - gw->requestWarpPointer(wx, wy); - osgGA::GUIEventAdapter* eventState - = cgroup->getViewer()->getEventQueue()->getCurrentEventState(); - double viewerX - = (eventState->getXmin() - + ((wx / double(traits->width)) - * (eventState->getXmax() - eventState->getXmin()))); - double viewerY - = (eventState->getYmin() - + ((wyUp / double(traits->height)) - * (eventState->getYmax() - eventState->getYmin()))); - cgroup->getViewer()->getEventQueue()->mouseWarped(viewerX, viewerY); -} - -void CameraGroup::buildDefaultGroup(osgViewer::Viewer* viewer) -{ - // Look for windows, camera groups, and the old syntax of - // top-level cameras - SGPropertyNode* renderingNode = fgGetNode("/sim/rendering"); - SGPropertyNode* cgroupNode = renderingNode->getNode("camera-group", true); - bool oldSyntax = !cgroupNode->hasChild("camera"); - if (oldSyntax) { - for (int i = 0; i < renderingNode->nChildren(); ++i) { - SGPropertyNode* propNode = renderingNode->getChild(i); - const char* propName = propNode->getName(); - if (!strcmp(propName, "window") || !strcmp(propName, "camera")) { - SGPropertyNode* copiedNode - = cgroupNode->getNode(propName, propNode->getIndex(), true); - copyProperties(propNode, copiedNode); - } - } - - SGPropertyNodeVec cameras(cgroupNode->getChildren("camera")); - SGPropertyNode* masterCamera = 0; - SGPropertyNodeVec::const_iterator it; - for (it = cameras.begin(); it != cameras.end(); ++it) { - if ((*it)->getDoubleValue("shear-x", 0.0) == 0.0 - && (*it)->getDoubleValue("shear-y", 0.0) == 0.0) { - masterCamera = it->ptr(); - break; - } - } - if (!masterCamera) { - WindowBuilder *windowBuilder = WindowBuilder::getWindowBuilder(); - masterCamera = cgroupNode->getChild("camera", cameras.size(), true); - setValue(masterCamera->getNode("window/name", true), - windowBuilder->getDefaultWindowName()); - } - SGPropertyNode* nameNode = masterCamera->getNode("window/name"); - if (nameNode) - setValue(cgroupNode->getNode("gui/window/name", true), - nameNode->getStringValue()); - } - - CameraGroup* cgroup = buildCameraGroup(viewer, cgroupNode); - setDefault(cgroup); -} - -} // of namespace flightgear - diff --git a/src/Viewer/CameraGroup_legacy.hxx b/src/Viewer/CameraGroup_legacy.hxx deleted file mode 100644 index 1a7c3221a..000000000 --- a/src/Viewer/CameraGroup_legacy.hxx +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright (C) 2008 Tim Moore -// -// 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 CAMERAGROUP_HXX -#define CAMERAGROUP_HXX 1 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -// For osgUtil::LineSegmentIntersector::Intersections, which is a typedef. -#include -namespace osg -{ -class Camera; -} - -namespace osgViewer -{ -class Viewer; -} - -class SGPropertyNode; - -namespace flightgear -{ - -class GraphicsWindow; -class CameraViewportListener; -class CameraGroupListener; - -struct RenderBufferInfo { - RenderBufferInfo(osg::Texture2D* t = 0, float s = 1.0 ) : texture(t), scaleFactor(s) {} - osg::ref_ptr texture; - float scaleFactor; -}; -typedef std::map RenderBufferMap; -typedef std::map AttachmentMap; - -struct RenderStageInfo { - RenderStageInfo(osg::Camera* camera_ = 0, int si = -1, bool fs = false) - : camera(camera_), slaveIndex(si), scaleFactor(1.0f), fullscreen(fs) - , resizable(true) - { - } - - osg::ref_ptr camera; - AttachmentMap buffers; - int slaveIndex; - float scaleFactor; - bool fullscreen; - bool resizable; -}; - -extern const char* MAIN_CAMERA; -extern const char* FAR_CAMERA; -extern const char* GEOMETRY_CAMERA; -extern const char* SHADOW_CAMERA; -extern const char* LIGHTING_CAMERA; -extern const char* DISPLAY_CAMERA; - -typedef std::map CameraMap; - -/** A wrapper around osg::Camera that contains some extra information. - */ -struct CameraInfo : public osg::Referenced -{ - CameraInfo(unsigned flags_) - : flags(flags_), - x(0.0), y(0.0), width(0.0), height(0.0), - physicalWidth(0), physicalHeight(0), bezelHeightTop(0), - bezelHeightBottom(0), bezelWidthLeft(0), bezelWidthRight(0), - relativeCameraParent(~0u), - bufferSize( new osg::Uniform("fg_BufferSize", osg::Vec2f() ) ), - projInverse( new osg::Uniform( "fg_ProjectionMatrixInverse", osg::Matrixf() ) ), - viewInverse( new osg::Uniform( "fg_ViewMatrixInverse",osg::Matrixf() ) ), - view( new osg::Uniform( "fg_ViewMatrix",osg::Matrixf() ) ), - worldPosCart( new osg::Uniform( "fg_CameraPositionCart", osg::Vec3f() ) ), - worldPosGeod( new osg::Uniform( "fg_CameraPositionGeod", osg::Vec3f() ) ), - du( new osg::Uniform( "fg_du",osg::Vec4() ) ), - dv( new osg::Uniform( "fg_dv",osg::Vec4() ) ), - viewportListener(NULL) - { - shadowMatrix[0] = new osg::Uniform("fg_ShadowMatrix_0", osg::Matrixf()); - shadowMatrix[1] = new osg::Uniform("fg_ShadowMatrix_1", osg::Matrixf()); - shadowMatrix[2] = new osg::Uniform("fg_ShadowMatrix_2", osg::Matrixf()); - shadowMatrix[3] = new osg::Uniform("fg_ShadowMatrix_3", osg::Matrixf()); - } - - ~CameraInfo(); - - /** Update and resize cameras - */ - void updateCameras(); - void resized(double w, double h); - - /** The name as given in the config file. - */ - std::string name; - /** Properties of the camera. @see CameraGroup::Flags. - */ - unsigned flags; - - /** Viewport parameters. - */ - double x; - double y; - double width; - double height; - /** Physical size parameters. - */ - double physicalWidth; - double physicalHeight; - double bezelHeightTop; - double bezelHeightBottom; - double bezelWidthLeft; - double bezelWidthRight; - /** The parent camera for relative camera configurations. - */ - unsigned relativeCameraParent; - - /** the camera objects - */ - CameraMap cameras; - void addCamera( const std::string& k, osg::Camera* c, int si = -1, bool fs = false ) { cameras[k].camera = c; cameras[k].slaveIndex = si; cameras[k].fullscreen = fs; } - void addCamera( const std::string& k, osg::Camera* c, bool fs ) { cameras[k].camera = c; cameras[k].fullscreen = fs; } - void addCamera( const std::string& k, osg::Camera* c, float s, bool fs = false ) { cameras[k].camera = c; cameras[k].scaleFactor = s; cameras[k].fullscreen = fs; } - osg::Camera* getCamera(const std::string& k) const; - int getMainSlaveIndex() const; - RenderStageInfo& getRenderStageInfo( const std::string& k ) { return cameras[k]; } - - /** the buffer objects - */ - RenderBufferMap buffers; - void addBuffer(const std::string& k, osg::Texture2D* tex, float scale = 1.0 ) { buffers[k] = RenderBufferInfo(tex,scale); } - osg::Texture2D* getBuffer(const std::string& k) const; - - osg::ref_ptr bufferSize; - osg::ref_ptr projInverse; - osg::ref_ptr viewInverse; - osg::ref_ptr view; - osg::ref_ptr worldPosCart; - osg::ref_ptr worldPosGeod; - osg::ref_ptr du; - osg::ref_ptr dv; - osg::ref_ptr shadowMatrix[4]; - - CameraViewportListener* viewportListener; - - void setMatrices( osg::Camera* c ); - - osgUtil::RenderBin::RenderBinList savedTransparentBins; - /** The reference points in the parents projection space. - */ - osg::Vec2d parentReference[2]; - /** The reference points in the current projection space. - */ - osg::Vec2d thisReference[2]; -}; - -class CameraGroup : public osg::Referenced -{ -public: - /** properties of a camera. - */ - enum Flags - { - VIEW_ABSOLUTE = 0x1, /**< The camera view is absolute, not - relative to the master camera. */ - PROJECTION_ABSOLUTE = 0x2, /**< The projection is absolute. */ - ORTHO = 0x4, /**< The projection is orthographic */ - GUI = 0x8, /**< Camera draws the GUI. */ - DO_INTERSECTION_TEST = 0x10,/**< scene intersection tests this - camera. */ - FIXED_NEAR_FAR = 0x20, /**< take the near far values in the - projection for real. */ - ENABLE_MASTER_ZOOM = 0x40 /**< Can apply the zoom algorithm. */ - }; - /** Create a camera group associated with an osgViewer::Viewer. - * @param viewer the viewer - */ - CameraGroup(osgViewer::Viewer* viewer); - - ~CameraGroup(); - - /** Get the camera group's Viewer. - * @return the viewer - */ - osgViewer::Viewer* getViewer() { return _viewer.get(); } - /** Create an osg::Camera from a property node and add it to the - * camera group. - * @param cameraNode the property node. - * @return a CameraInfo object for the camera. - */ - CameraInfo* buildCamera(SGPropertyNode* cameraNode); - /** Create a camera from properties that will draw the GUI and add - * it to the camera group. - * @param cameraNode the property node. This can be 0, in which - * case a default GUI camera is created. - * @param window the GraphicsWindow to use for the GUI camera. If - * this is 0, the window is determined from the property node. - * @return a CameraInfo object for the GUI camera. - */ - CameraInfo* buildGUICamera(SGPropertyNode* cameraNode, - GraphicsWindow* window = 0); - /** Update the view for the camera group. - * @param position the world position of the view - * @param orientation the world orientation of the view. - */ - void update(const osg::Vec3d& position, const osg::Quat& orientation); - /** Set the parameters of the viewer's master camera. This won't - * affect cameras that have CameraFlags::PROJECTION_ABSOLUTE set. - * XXX Should znear and zfar be settable? - * @param vfov the vertical field of view angle - * @param aspectRatio the master camera's aspect ratio. This - * doesn't actually change the viewport, but should reflect the - * current viewport. - */ - void setCameraParameters(float vfov, float aspectRatio); - /** Set the default CameraGroup, which is the only one that - * matters at this time. - * @param group the group to set. - */ - - static void buildDefaultGroup(osgViewer::Viewer* viewer); - - static void setDefault(CameraGroup* group) { _defaultGroup = group; } - /** Get the default CameraGroup. - * @return the default camera group. - */ - static CameraGroup* getDefault() { return _defaultGroup.get(); } - - typedef std::vector > CameraList; - typedef CameraList::iterator CameraIterator; - typedef CameraList::const_iterator ConstCameraIterator; - /** Get iterator for camera vector. The iterator's value is a ref_ptr. - */ - CameraIterator camerasBegin() { return _cameras.begin(); } - /** Get iteator pointing to the end of the camera list. - */ - CameraIterator camerasEnd() { return _cameras.end(); } - ConstCameraIterator camerasBegin() const { return _cameras.begin(); } - ConstCameraIterator camerasEnd() const { return _cameras.end(); } - void addCamera(CameraInfo* info) { _cameras.push_back(info); } - /** Set the cull mask on all non-GUI cameras - */ - void setCameraCullMasks(osg::Node::NodeMask nm); - /** Update camera properties after a resize event. - */ - void resized(); - - void buildDistortionCamera(const SGPropertyNode* psNode, - osg::Camera* camera); - - /** - * get aspect ratio of master camera's viewport - */ - double getMasterAspectRatio() const; - - /** - * find the GUI camera if one is defined - */ - const CameraInfo* getGUICamera() const; - - void setZNear(float f) { _zNear = f; } - void setZFar(float f) { _zFar = f; } - void setNearField(float f) { _nearField = f; } -protected: - CameraList _cameras; - osg::ref_ptr _viewer; - static osg::ref_ptr _defaultGroup; - std::unique_ptr _listener; - - // Near, far for the master camera if used. - float _zNear; - float _zFar; - float _nearField; - - typedef std::map > TextureMap; - TextureMap _textureTargets; - - /** Build a complete CameraGroup from a property node. - * @param viewer the viewer associated with this camera group. - * @param the camera group property node. - */ - static CameraGroup* buildCameraGroup(osgViewer::Viewer* viewer, - SGPropertyNode* node); -}; - -} - -namespace flightgear -{ -/** Get the osg::Camera that draws the GUI, if any, from a camera - * group. - * @param cgroup the camera group - * @return the GUI camera or 0 - */ -osg::Camera* getGUICamera(CameraGroup* cgroup); -/** Choose a camera using an event and do intersection testing on its - * view of the scene. Only cameras with the DO_INTERSECTION_TEST flag - * set are considered. - * @param cgroup the CameraGroup - * @param ea the event containing a window and mouse coordinates - * @param intersections container for the result of intersection - * testing. - * @return true if any intersections are found - */ -bool computeIntersections(const CameraGroup* cgroup, - const osg::Vec2d& windowPos, - osgUtil::LineSegmentIntersector::Intersections& - intersections); -/** Warp the pointer to coordinates in the GUI camera of a camera group. - * @param cgroup the camera group - * @param x x window coordinate of pointer - * @param y y window coordinate of pointer, in "y down" coordinates. - */ -void warpGUIPointer(CameraGroup* cgroup, int x, int y); -} -#endif diff --git a/src/Viewer/fgviewer.cxx b/src/Viewer/fgviewer.cxx index 7fd5a82f5..fcd7bcaca 100644 --- a/src/Viewer/fgviewer.cxx +++ b/src/Viewer/fgviewer.cxx @@ -34,7 +34,7 @@ #include #include -#include +#include #include
#include
diff --git a/src/Viewer/renderer_compositor.cxx b/src/Viewer/renderer.cxx similarity index 93% rename from src/Viewer/renderer_compositor.cxx rename to src/Viewer/renderer.cxx index e8dc7092d..3f2f9e9ef 100644 --- a/src/Viewer/renderer_compositor.cxx +++ b/src/Viewer/renderer.cxx @@ -343,7 +343,8 @@ public: bool FGScenerySwitchCallback::scenery_enabled = false; FGRenderer::FGRenderer() : - _sky(NULL) + _sky(NULL), + MaximumTextureSize(0) { _root = new osg::Group; _root->setName("fakeRoot"); @@ -352,6 +353,11 @@ FGRenderer::FGRenderer() : FGRenderer::~FGRenderer() { + SGPropertyChangeListenerVec::iterator i = _listeners.begin(); + for (; i != _listeners.end(); ++i) { + delete *i; + } + // replace the viewer's scene completely if (getViewer()) { getViewer()->setSceneData(new osg::Group); @@ -360,6 +366,37 @@ FGRenderer::~FGRenderer() delete _sky; } +class PointSpriteListener : public SGPropertyChangeListener { +public: + virtual void valueChanged(SGPropertyNode* node) { + static SGSceneFeatures* sceneFeatures = SGSceneFeatures::instance(); + sceneFeatures->setEnablePointSpriteLights(node->getIntValue()); + } +}; + +class DistanceAttenuationListener : public SGPropertyChangeListener { +public: + virtual void valueChanged(SGPropertyNode* node) { + static SGSceneFeatures* sceneFeatures = SGSceneFeatures::instance(); + sceneFeatures->setEnableDistanceAttenuationLights(node->getIntValue()); + } +}; + +class DirectionalLightsListener : public SGPropertyChangeListener { +public: + virtual void valueChanged(SGPropertyNode* node) { + static SGSceneFeatures* sceneFeatures = SGSceneFeatures::instance(); + sceneFeatures->setEnableTriangleDirectionalLights(node->getIntValue()); + } +}; + +void +FGRenderer::addChangeListener(SGPropertyChangeListener* l, const char* path) +{ + _listeners.push_back(l); + fgAddChangeListener(l, path); +} + // Initialize various GL/view parameters void FGRenderer::preinit( void ) @@ -411,9 +448,6 @@ FGRenderer::init( void ) _ysize = fgGetNode("/sim/startup/ysize", true); _splash_alpha = fgGetNode("/sim/startup/splash-alpha", true); - _point_sprites = fgGetNode("/sim/rendering/point-sprites", true); - _triangle_directional_lights = fgGetNode("/sim/rendering/triangle-directional-lights", true); - _distance_attenuation = fgGetNode("/sim/rendering/distance-attenuation", true); _horizon_effect = fgGetNode("/sim/rendering/horizon-effect", true); _altitude_ft = fgGetNode("/position/altitude-ft", true); @@ -421,11 +455,15 @@ FGRenderer::init( void ) _cloud_status = fgGetNode("/environment/clouds/status", true); _visibility_m = fgGetNode("/environment/visibility-m", true); - bool use_point_sprites = _point_sprites->getBoolValue(); - bool distance_attenuation = _distance_attenuation->getBoolValue(); - bool triangles = _triangle_directional_lights->getBoolValue(); + // configure the lighting related parameters and add change listeners. + bool use_point_sprites = fgGetBool("/sim/rendering/point-sprites", true); + bool distance_attenuation = fgGetBool("/sim/rendering/distance-attenuation", false); + bool triangles = fgGetBool("/sim/rendering/triangle-directional-lights", true); + SGConfigureDirectionalLights(use_point_sprites, distance_attenuation, triangles); - SGConfigureDirectionalLights( use_point_sprites, distance_attenuation, triangles ); + addChangeListener(new PointSpriteListener, "/sim/rendering/point-sprites"); + addChangeListener(new DistanceAttenuationListener, "/sim/rendering/distance-attenuation"); + addChangeListener(new DirectionalLightsListener, "/sim/rendering/triangle-directional-lights"); if (const char* tc = fgGetString("/sim/rendering/texture-compression", NULL)) { if (strcmp(tc, "false") == 0 || strcmp(tc, "off") == 0 || @@ -654,13 +692,18 @@ FGRenderer::update( ) { { _splash_alpha->setDoubleValue(1.0); - GLint max_texture_size; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); - // abritrary range change as sometimes during init the device reports somewhat dubious values, so - // we know that the size must be greater than size and that probably 9999999 is unreasonably large - if (max_texture_size > 0 && max_texture_size < 9999999) - SGSceneFeatures::instance()->setMaxTextureSize(max_texture_size); - + if (!MaximumTextureSize) { + osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault()); + if (guiCamera) { + GraphicsContext *gc = guiCamera->getGraphicsContext(); + osg::GLExtensions* gl2ext = gc->getState()->get(); + if (gl2ext) { + MaximumTextureSize = gl2ext->maxTextureSize; + SGSceneFeatures::instance()->setMaxTextureSize(MaximumTextureSize); + SG_LOG(SG_VIEW, SG_INFO, "FGRenderer:: Maximum texture size " << MaximumTextureSize); + } + } + } return; } osgViewer::Viewer* viewer = globals->get_renderer()->getViewer(); @@ -676,12 +719,13 @@ FGRenderer::update( ) { double sAlpha = _splash_alpha->getDoubleValue(); sAlpha -= SGMiscd::max(0.0,delay_time/fade_time); FGScenerySwitchCallback::scenery_enabled = (sAlpha<1.0); - _splash_alpha->setDoubleValue((sAlpha < 0) ? 0.0 : sAlpha); if (sAlpha <= 0.0) { flightgear::addSentryBreadcrumb("splash-screen fade out complete", "info"); } + _splash_alpha->setDoubleValue((sAlpha < 0) ? 0.0 : sAlpha); + syncPausePopupState(); fgSetBool("/sim/menubar/overlap-hide", false); } diff --git a/src/Viewer/renderer.hxx b/src/Viewer/renderer.hxx index 36a4be880..b01416125 100644 --- a/src/Viewer/renderer.hxx +++ b/src/Viewer/renderer.hxx @@ -1,14 +1,130 @@ -#ifndef COMMON_RENDERER_HXX -#define COMMON_RENDERER_HXX +#ifndef __FG_RENDERER_HXX +#define __FG_RENDERER_HXX 1 + +#include +#include +#include + +#include +#include +#include +#include + +namespace osg +{ +class Camera; +class Group; +class GraphicsContext; +class FrameStamp; +} + +namespace osgGA +{ +class GUIEventAdapter; +} + +namespace osgViewer +{ +class Viewer; +} + +namespace flightgear +{ +class FGEventHandler; +class CameraGroup; +class PUICamera; +} + +class SGSky; +class SGUpdateVisitor; +class SplashScreen; +class QQuickDrawable; + +typedef std::vector PickList; + +class FGRenderer { + +public: + + FGRenderer(); + ~FGRenderer(); + + void preinit(); + void init(); + + void setupView(); + + void resize(int width, int height ); + + void update(); + + /** Just pick into the scene and return the pick callbacks on the way ... + */ + PickList pick(const osg::Vec2& windowPos); + + /** Get and set the OSG Viewer object, if any. + */ + osgViewer::Viewer* getViewer() { return viewer.get(); } + const osgViewer::Viewer* getViewer() const { return viewer.get(); } + void setViewer(osgViewer::Viewer* viewer); + /** Get and set the manipulator object, if any. + */ + flightgear::FGEventHandler* getEventHandler() { return eventHandler.get(); } + const flightgear::FGEventHandler* getEventHandler() const { return eventHandler.get(); } + void setEventHandler(flightgear::FGEventHandler* manipulator); + + /** Add a top level camera. + */ + void addCamera(osg::Camera* camera, bool useSceneData); + + void removeCamera(osg::Camera* camera); + + SGSky* getSky() const { return _sky; } + + void setPlanes( double zNear, double zFar ); + +protected: + osg::ref_ptr viewer; + osg::ref_ptr eventHandler; + + osg::ref_ptr _frameStamp; + osg::ref_ptr _updateVisitor; + osg::ref_ptr _viewerSceneRoot; + osg::ref_ptr _root; + + SGPropertyNode_ptr _scenery_loaded, _position_finalized; + + SGPropertyNode_ptr _splash_alpha; + SGPropertyNode_ptr _enhanced_lighting; + SGPropertyNode_ptr _textures; + SGPropertyNode_ptr _cloud_status, _visibility_m; + SGPropertyNode_ptr _xsize, _ysize; + SGPropertyNode_ptr _panel_hotspots, _sim_delta_sec, _horizon_effect, _altitude_ft; + SGPropertyNode_ptr _virtual_cockpit; + SGTimeStamp _splash_time; + SGSky* _sky; + int MaximumTextureSize; + + typedef std::vector SGPropertyChangeListenerVec; + SGPropertyChangeListenerVec _listeners; + + void addChangeListener(SGPropertyChangeListener* l, const char* path); + + void updateSky(); + + void setupRoot(); + + SplashScreen* _splash; + QQuickDrawable* _quickDrawable = nullptr; + flightgear::PUICamera* _puiCamera = nullptr; +}; + +bool fgDumpSceneGraphToFile(const char* filename); +bool fgDumpTerrainBranchToFile(const char* filename); + +namespace flightgear +{ +bool printVisibleSceneInfo(FGRenderer* renderer); +} -#ifdef HAVE_CONFIG_H -# include #endif - -#ifdef ENABLE_COMPOSITOR -# include "renderer_compositor.hxx" -#else -# include "renderer_legacy.hxx" -#endif - -#endif /* COMMON_RENDERER_HXX */ diff --git a/src/Viewer/renderer_compositor.hxx b/src/Viewer/renderer_compositor.hxx deleted file mode 100644 index e5fff12d1..000000000 --- a/src/Viewer/renderer_compositor.hxx +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef __FG_RENDERER_HXX -#define __FG_RENDERER_HXX 1 - -#include -#include -#include - -#include -#include -#include -#include - -namespace osg -{ -class Camera; -class Group; -class GraphicsContext; -class FrameStamp; -} - -namespace osgGA -{ -class GUIEventAdapter; -} - -namespace osgViewer -{ -class Viewer; -} - -namespace flightgear -{ -class FGEventHandler; -class CameraGroup; -class PUICamera; -} - -class SGSky; -class SGUpdateVisitor; -class SplashScreen; -class QQuickDrawable; - -typedef std::vector PickList; - -class FGRenderer { - -public: - - FGRenderer(); - ~FGRenderer(); - - void preinit(); - void init(); - - void setupView(); - - void resize(int width, int height ); - - void update(); - - /** Just pick into the scene and return the pick callbacks on the way ... - */ - PickList pick(const osg::Vec2& windowPos); - - /** Get and set the OSG Viewer object, if any. - */ - osgViewer::Viewer* getViewer() { return viewer.get(); } - const osgViewer::Viewer* getViewer() const { return viewer.get(); } - void setViewer(osgViewer::Viewer* viewer); - /** Get and set the manipulator object, if any. - */ - flightgear::FGEventHandler* getEventHandler() { return eventHandler.get(); } - const flightgear::FGEventHandler* getEventHandler() const { return eventHandler.get(); } - void setEventHandler(flightgear::FGEventHandler* manipulator); - - /** Add a top level camera. - */ - void addCamera(osg::Camera* camera, bool useSceneData); - - void removeCamera(osg::Camera* camera); - - SGSky* getSky() const { return _sky; } - - void setPlanes( double zNear, double zFar ); - -protected: - osg::ref_ptr viewer; - osg::ref_ptr eventHandler; - - osg::ref_ptr _frameStamp; - osg::ref_ptr _updateVisitor; - osg::ref_ptr _viewerSceneRoot; - osg::ref_ptr _root; - - SGPropertyNode_ptr _scenery_loaded, _position_finalized; - - SGPropertyNode_ptr _splash_alpha; - SGPropertyNode_ptr _point_sprites, _enhanced_lighting, _distance_attenuation, _triangle_directional_lights; - SGPropertyNode_ptr _textures; - SGPropertyNode_ptr _cloud_status, _visibility_m; - SGPropertyNode_ptr _xsize, _ysize; - SGPropertyNode_ptr _panel_hotspots, _sim_delta_sec, _horizon_effect, _altitude_ft; - SGPropertyNode_ptr _virtual_cockpit; - SGTimeStamp _splash_time; - SGSky* _sky; - - void updateSky(); - - void setupRoot(); - - SplashScreen* _splash; - QQuickDrawable* _quickDrawable; - flightgear::PUICamera* _puiCamera = nullptr; -}; - -bool fgDumpSceneGraphToFile(const char* filename); -bool fgDumpTerrainBranchToFile(const char* filename); - -namespace flightgear -{ -bool printVisibleSceneInfo(FGRenderer* renderer); -} - -#endif diff --git a/src/Viewer/renderer_legacy.cxx b/src/Viewer/renderer_legacy.cxx deleted file mode 100755 index 8c2a4a71b..000000000 --- a/src/Viewer/renderer_legacy.cxx +++ /dev/null @@ -1,2111 +0,0 @@ -// renderer.cxx -- top level sim routines -// -// Written by Curtis Olson, started May 1997. -// This file contains parts of main.cxx prior to october 2004 -// -// Copyright (C) 1997 - 2002 Curtis L. Olson - http://www.flightgear.org/~curt -// -// 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. - -#include - -#ifdef HAVE_WINDOWS_H -# include -#endif - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include