From e042364dd03f2ab425027444f79b94b3babbcd42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Garc=C3=ADa=20Li=C3=B1=C3=A1n?= Date: Mon, 4 Feb 2019 18:01:15 +0100 Subject: [PATCH] Compositor framework initial commit. --- CMakeLists.txt | 2 +- src/Include/config_cmake.h.in | 1 + src/Viewer/CMakeLists.txt | 11 +- src/Viewer/CameraGroup.hxx | 353 +---- src/Viewer/CameraGroup_compositor.cxx | 936 +++++++++++++ src/Viewer/CameraGroup_compositor.hxx | 244 ++++ ...CameraGroup.cxx => CameraGroup_legacy.cxx} | 0 src/Viewer/CameraGroup_legacy.hxx | 343 +++++ src/Viewer/renderer.hxx | 218 +-- src/Viewer/renderer_compositor.cxx | 1165 +++++++++++++++++ src/Viewer/renderer_compositor.hxx | 124 ++ .../{renderer.cxx => renderer_legacy.cxx} | 0 src/Viewer/renderer_legacy.hxx | 208 +++ src/Viewer/splash.cxx | 2 +- src/Viewer/viewmgr.cxx | 4 +- 15 files changed, 3056 insertions(+), 555 deletions(-) create mode 100644 src/Viewer/CameraGroup_compositor.cxx create mode 100644 src/Viewer/CameraGroup_compositor.hxx rename src/Viewer/{CameraGroup.cxx => CameraGroup_legacy.cxx} (100%) create mode 100644 src/Viewer/CameraGroup_legacy.hxx create mode 100644 src/Viewer/renderer_compositor.cxx create mode 100644 src/Viewer/renderer_compositor.hxx rename src/Viewer/{renderer.cxx => renderer_legacy.cxx} (100%) create mode 100644 src/Viewer/renderer_legacy.hxx diff --git a/CMakeLists.txt b/CMakeLists.txt index deac9bae7..91645cbf6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -201,7 +201,7 @@ 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" OFF) 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) # Test-suite options. diff --git a/src/Include/config_cmake.h.in b/src/Include/config_cmake.h.in index 0656c8153..d6b61941d 100644 --- a/src/Include/config_cmake.h.in +++ b/src/Include/config_cmake.h.in @@ -68,3 +68,4 @@ #cmakedefine HAVE_QRC_TRANSLATIONS +#cmakedefine ENABLE_COMPOSITOR diff --git a/src/Viewer/CMakeLists.txt b/src/Viewer/CMakeLists.txt index 1ac79feb0..95f4d604a 100644 --- a/src/Viewer/CMakeLists.txt +++ b/src/Viewer/CMakeLists.txt @@ -1,14 +1,11 @@ include(FlightGearComponent) set(SOURCES - CameraGroup.cxx FGEventHandler.cxx WindowBuilder.cxx WindowSystemAdapter.cxx fg_os_osgviewer.cxx fgviewer.cxx - renderer.cxx - renderingpipeline.cxx splash.cxx view.cxx viewmgr.cxx @@ -21,7 +18,6 @@ set(HEADERS WindowSystemAdapter.hxx fgviewer.hxx renderer.hxx - renderingpipeline.hxx splash.hxx view.hxx viewmgr.hxx @@ -37,5 +33,12 @@ 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.hxx b/src/Viewer/CameraGroup.hxx index 1a7c3221a..14347b9e4 100644 --- a/src/Viewer/CameraGroup.hxx +++ b/src/Viewer/CameraGroup.hxx @@ -1,343 +1,14 @@ -// 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 COMMON_CAMERAGROUP_HXX +#define COMMON_CAMERAGROUP_HXX -#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); -} +#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.cxx b/src/Viewer/CameraGroup_compositor.cxx new file mode 100644 index 000000000..388292e8a --- /dev/null +++ b/src/Viewer/CameraGroup_compositor.cxx @@ -0,0 +1,936 @@ +// 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. + +#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 + +#include +#include +#include + +using namespace osg; + +namespace { + +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; +} + +} // anonymous namespace + +namespace flightgear +{ +using namespace simgear::compositor; + +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->_zNear = prop->getFloatValue(); + } else if (!strcmp(prop->getName(), "zfar")) { + _cameraGroup->_zFar = prop->getFloatValue(); + } else if (!strcmp(prop->getName(), "near-field")) { + _cameraGroup->_nearField = 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 +}; + +struct GUIUpdateCallback : public Pass::PassUpdateCallback { + virtual void updatePass(Pass &pass, + const osg::Matrix &view_matrix, + const osg::Matrix &proj_matrix) { + // Just set both the view matrix and the projection matrix + pass.camera->setViewMatrix(view_matrix); + pass.camera->setProjectionMatrix(proj_matrix); + } +}; + +typedef std::vector SGPropertyNodeVec; + +osg::ref_ptr CameraGroup::_defaultGroup; + +CameraGroup::CameraGroup(osgViewer::Viewer* viewer) : + _viewer(viewer) +{ +} + +CameraGroup::~CameraGroup() +{ + +} + +void CameraGroup::update(const osg::Vec3d& position, + const osg::Quat& orientation) +{ + const osg::Matrix masterView(osg::Matrix::translate(-position) + * osg::Matrix::rotate(orientation.inverse())); + _viewer->getCamera()->setViewMatrix(masterView); + const osg::Matrix& masterProj = _viewer->getCamera()->getProjectionMatrix(); + double masterZoomFactor = zoomFactor(); + + for (const auto &info : _cameras) { + osg::Matrix view_matrix; + if (info->flags & CameraInfo::GUI) + view_matrix = osg::Matrix::identity(); + else if ((info->flags & CameraInfo::VIEW_ABSOLUTE) != 0) + view_matrix = info->viewOffset; + else + view_matrix = masterView * info->viewOffset; + + osg::Matrix proj_matrix; + if (info->flags & CameraInfo::GUI) { + const osg::GraphicsContext::Traits *traits = + info->compositor->getGraphicsContext()->getTraits(); + proj_matrix = osg::Matrix::ortho2D(0, traits->width, 0, traits->height); + } else if ((info->flags & CameraInfo::PROJECTION_ABSOLUTE) != 0) { + if (info->flags & CameraInfo::ENABLE_MASTER_ZOOM) { + if (info->relativeCameraParent) { + // template projection and view matrices of the current camera + osg::Matrix P0 = info->projOffset; + osg::Matrix R = view_matrix; + + // The already known projection and view matrix of the parent camera + osg::Matrix pP = info->relativeCameraParent->viewMatrix; + osg::Matrix pR = info->relativeCameraParent->projMatrix; + + // And the projection matrix derived from P0 so that the + // reference points match + proj_matrix = 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 + proj_matrix = info->projOffset; + proj_matrix.postMultScale(osg::Vec3d(masterZoomFactor, + masterZoomFactor, + 1)); + } + } else { + proj_matrix = info->projOffset; + } + } else { + proj_matrix = masterProj * info->projOffset; + } + + info->viewMatrix = view_matrix; + info->projMatrix = proj_matrix; + info->compositor->update(view_matrix, proj_matrix); + } +} + +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; + + // The master camera is the first one added + const CameraInfo *info = _cameras.front(); + if (!info) + return 0.0; + const osg::GraphicsContext::Traits *traits = + info->compositor->getGraphicsContext()->getTraits(); + + return static_cast(traits->height) / traits->width; +} + +// FIXME: Port this to the Compositor +#if 0 +// 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; + + // create the quad to visualize. + osg::Geometry* geometry = new osg::Geometry(); + + geometry->setSupportsDisplayList(false); + + osg::Vec3 xAxis(widthVector); + float width = widthVector.length(); + xAxis /= width; + + osg::Vec3 yAxis(heightVector); + float height = heightVector.length(); + yAxis /= height; + + int noSteps = 160; + + osg::Vec3Array* vertices = new osg::Vec3Array; + osg::Vec2Array* texcoords0 = new osg::Vec2Array; + osg::Vec2Array* texcoords1 = intensityMap==0 ? new osg::Vec2Array : 0; + osg::Vec4Array* colors = new osg::Vec4Array; + + osg::Vec3 top = origin + yAxis*height; + + osg::Vec3 screenCenter = origin + widthVector*0.5f + heightVector*0.5f; + float screenRadius = heightVector.length() * 0.5f; + + geometry->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); + + for(int i=0;ipush_back(osg::Vec3(v.x(), top.y()-(v.y()-origin.y()),v.z())); + else + vertices->push_back(v); + + texcoords0->push_back( texcoord ); + + osg::Vec2 texcoord1(alpha/(2.0*osg::PI), 1.0f - beta/osg::PI); + if (intensityMap) + { + colors->push_back(intensityMap->getColor(texcoord1)); + } + else + { + colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); + if (texcoords1) texcoords1->push_back( texcoord1 ); + } + + + } + } + + // pass the created vertex array to the points geometry object. + geometry->setVertexArray(vertices); + + geometry->setColorArray(colors); + geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); + + geometry->setTexCoordArray(0,texcoords0); + if (texcoords1) geometry->setTexCoordArray(1,texcoords1); + + osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES); + geometry->addPrimitiveSet(elements); + + for(int i=0;iscreenRadius) continue; + if ((v2-screenCenter).length()>screenRadius) continue; + if ((v3-screenCenter).length()>screenRadius) continue; + if ((v4-screenCenter).length()>screenRadius) continue; + + elements->push_back(i1); + elements->push_back(i2); + elements->push_back(i3); + + elements->push_back(i1); + elements->push_back(i3); + elements->push_back(i4); + } + } + + return geometry; +} + +#endif + +void CameraGroup::buildDistortionCamera(const SGPropertyNode* psNode, + Camera* camera) +{ + // FIXME: Port this to the Compositor +#if 0 + const SGPropertyNode* texNode = psNode->getNode("texture"); + if (!texNode) { + // error + return; + } + string texName = texNode->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"); +#endif +} + +void CameraGroup::buildCamera(SGPropertyNode* cameraNode) +{ + WindowBuilder *wBuild = WindowBuilder::getWindowBuilder(); + const SGPropertyNode* windowNode = cameraNode->getNode("window"); + GraphicsWindow* window = 0; + int cameraFlags = CameraInfo::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; + } + + 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 |= CameraInfo::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 |= CameraInfo::PROJECTION_ABSOLUTE; + if (projectionNode->getBoolValue("fixed-near-far", true)) + cameraFlags |= CameraInfo::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 |= CameraInfo::PROJECTION_ABSOLUTE; + } else { + pOff.makeOrtho(left, right, bottom, top, zNear, zFar); + cameraFlags |= (CameraInfo::PROJECTION_ABSOLUTE | CameraInfo::ORTHO); + } + if (projectionNode->getBoolValue("fixed-near-far", true)) + cameraFlags |= CameraInfo::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 |= CameraInfo::PROJECTION_ABSOLUTE | CameraInfo::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; + } + const CameraInfo* parentInfo = _cameras[parentCameraIndex]; + 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 |= CameraInfo::PROJECTION_ABSOLUTE | CameraInfo::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* psNode = cameraNode->getNode("panoramic-spherical"); + //bool useMasterSceneGraph = !psNode; + + CameraInfo *info = new CameraInfo(cameraFlags); + _cameras.push_back(info); + info->name = cameraNode->getStringValue("name"); + info->physicalWidth = physicalWidth; + info->physicalHeight = physicalHeight; + info->bezelHeightTop = bezelHeightTop; + info->bezelHeightBottom = bezelHeightBottom; + info->bezelWidthLeft = bezelWidthLeft; + info->bezelWidthRight = bezelWidthRight; + if (parentCameraIndex < _cameras.size()) + info->relativeCameraParent = _cameras[parentCameraIndex]; + info->parentReference[0] = parentReference[0]; + info->parentReference[1] = parentReference[1]; + info->thisReference[0] = thisReference[0]; + info->thisReference[1] = thisReference[1]; + info->viewOffset = vOff; + info->projOffset = pOff; + + osg::Viewport *viewport = new osg::Viewport( + viewportNode->getDoubleValue("x"), + viewportNode->getDoubleValue("y"), + // If no width or height has been specified, fill the entire window + viewportNode->getDoubleValue("width", window->gc->getTraits()->width), + viewportNode->getDoubleValue("height",window->gc->getTraits()->height)); + std::string comp_path = cameraNode->getStringValue("compositor", + "Compositor/default"); + Compositor *compositor = Compositor::create(_viewer, + window->gc, + viewport, + comp_path); + if (compositor) + info->compositor = compositor; + else + SG_LOG(SG_INPUT, SG_WARN, "Unable to build Compositor"); + + // Distortion camera needs the viewport which is created by addCamera(). + if (psNode) { + info->flags = info->flags | CameraInfo::VIEW_ABSOLUTE; + //buildDistortionCamera(psNode, camera); + } +} + +void 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; + } + + Camera* camera = new Camera; + camera->setName( "GUICamera" ); + camera->setAllowEventFocus(false); + camera->setGraphicsContext(window->gc.get()); + // 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. + osg::Viewport *viewport = new osg::Viewport( + 0, 0, window->gc->getTraits()->width, window->gc->getTraits()->height); + camera->setViewport(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(osg::Camera::FIXED); + + // 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 ); + + // 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); + + Pass *pass = new Pass; + pass->camera = camera; + pass->useMastersSceneData = false; + pass->update_callback = new GUIUpdateCallback; + + // For now we just build a simple Compositor directly from C++ space that + // encapsulates a single osg::Camera. This could be improved by letting + // users change the Compositor config in XML space, for example to be able + // to add post-processing to a HUD. + // However, since many other parts of FG require direct access to the GUI + // osg::Camera object, this is fine for now. + Compositor *compositor = new Compositor(_viewer, window->gc, viewport); + compositor->addPass(pass); + + const int cameraFlags = CameraInfo::GUI | CameraInfo::DO_INTERSECTION_TEST; + CameraInfo* info = new CameraInfo(cameraFlags); + info->name = "GUI camera"; + info->viewOffset = osg::Matrix::identity(); + info->projOffset = osg::Matrix::identity(); + info->compositor = compositor; + _cameras.push_back(info); + + // Disable statistics for the GUI camera. + camera->setStats(0); +} + +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 (const auto &info : _cameras) + info->compositor->setCameraCullMasks(nm); +} + +void CameraGroup::resized() +{ + for (const auto &info : _cameras) + info->compositor->resized(); +} + +CameraInfo* CameraGroup::getGUICamera() const +{ + auto result = std::find_if(_cameras.begin(), _cameras.end(), + [](const osg::ref_ptr &i) { + return (i->flags & CameraInfo::GUI) != 0; + }); + if (result == _cameras.end()) + return 0; + return (*result); +} + +osg::Camera* getGUICamera(CameraGroup* cgroup) +{ + return cgroup->getGUICamera()->compositor->getPass(0)->camera; +} + +bool computeIntersections(const CameraGroup* cgroup, + const osg::Vec2d& windowPos, + osgUtil::LineSegmentIntersector::Intersections& intersections) +{ + // test the GUI first + CameraInfo* guiCamera = cgroup->getGUICamera(); + if (guiCamera && guiCamera->compositor->computeIntersection(windowPos, intersections)) + return true; + + // Find camera that contains event + for (const auto &info : cgroup->_cameras) { + if (info == guiCamera) + continue; + if (!(info->flags & CameraInfo::DO_INTERSECTION_TEST)) + continue; + + if (info->compositor->computeIntersection(windowPos, intersections)) + return true; + } + + intersections.clear(); + return false; +} + +void warpGUIPointer(CameraGroup* cgroup, int x, int y) +{ + using osgViewer::GraphicsWindow; + osg::Camera* guiCamera = getGUICamera(cgroup); + if (!guiCamera) + return; + osg::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 osg::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_compositor.hxx b/src/Viewer/CameraGroup_compositor.hxx new file mode 100644 index 000000000..5aa420539 --- /dev/null +++ b/src/Viewer/CameraGroup_compositor.hxx @@ -0,0 +1,244 @@ +// 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); + /** 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; + + 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.cxx b/src/Viewer/CameraGroup_legacy.cxx similarity index 100% rename from src/Viewer/CameraGroup.cxx rename to src/Viewer/CameraGroup_legacy.cxx diff --git a/src/Viewer/CameraGroup_legacy.hxx b/src/Viewer/CameraGroup_legacy.hxx new file mode 100644 index 000000000..1a7c3221a --- /dev/null +++ b/src/Viewer/CameraGroup_legacy.hxx @@ -0,0 +1,343 @@ +// 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/renderer.hxx b/src/Viewer/renderer.hxx index 28cab3c8c..36a4be880 100644 --- a/src/Viewer/renderer.hxx +++ b/src/Viewer/renderer.hxx @@ -1,208 +1,14 @@ +#ifndef COMMON_RENDERER_HXX +#define COMMON_RENDERER_HXX -#ifndef __FG_RENDERER_HXX -#define __FG_RENDERER_HXX 1 - -#include -#include -#include - -#include -#include -#include - -#include "renderingpipeline.hxx" - -namespace osg -{ -class Camera; -class Group; -class GraphicsContext; -} - -namespace osgGA -{ -class GUIEventAdapter; -} - -namespace osgShadow -{ -class ShadowedScene; -} - -namespace osgViewer -{ -class Viewer; -} - -namespace flightgear -{ -class FGEventHandler; -struct CameraInfo; -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); - - /** Add a camera to the group. The camera is added to the viewer - * as a slave. See osgViewer::Viewer::addSlave. - * @param flags properties of the camera; see CameraGroup::Flags - * @param projection slave projection matrix - * @param view slave view matrix - * @param useMasterSceneData whether the camera displays the - * viewer's scene data. - * @return a CameraInfo object for the camera. - */ - flightgear::CameraInfo* buildRenderingPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera, - const osg::Matrix& view, - const osg::Matrix& projection, - osg::GraphicsContext* gc, - bool useMasterSceneData); - - /** - */ - flightgear::CameraInfo* buildClassicalPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera, - const osg::Matrix& view, - const osg::Matrix& projection, - bool useMasterSceneData); - - /** - */ - flightgear::CameraInfo* buildDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera, - const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc); - - void updateShadowCamera(const flightgear::CameraInfo* info, const osg::Vec3d& position); - void updateShadowMapSize(int mapSize); - void enableShadows(bool enabled); - void updateCascadeFar(int index, float far_m); - void updateCascadeNumber(size_t num); - - 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 _deferredRealRoot; - osg::ref_ptr _root; - - SGPropertyNode_ptr _scenery_loaded, _position_finalized; - - - SGPropertyNode_ptr _splash_alpha; - SGPropertyNode_ptr _point_sprites, _enhanced_lighting, _distance_attenuation; - 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; - bool _classicalRenderer; - std::string _renderer; - int _shadowMapSize; - size_t _numCascades; - float _cascadeFar[4]; - bool _useColorForDepth; - - typedef std::vector SGPropertyChangeListenerVec; - SGPropertyChangeListenerVec _listeners; - - flightgear::CameraInfo* buildCameraFromRenderingPipeline(FGRenderingPipeline* rpipe, flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera, - const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc); - - void buildBuffers(FGRenderingPipeline* rpipe, flightgear::CameraInfo* info); - void buildStage(flightgear::CameraInfo* info, FGRenderingPipeline::Stage* stage, flightgear::CameraGroup* cgroup, osg::Camera* mainCamera, const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc); - osg::Node* buildPass(flightgear::CameraInfo* info, FGRenderingPipeline::Pass* pass); - osg::Node* buildLightingSkyCloudsPass(FGRenderingPipeline::Pass* pass); - osg::Node* buildLightingLightsPass(flightgear::CameraInfo* info, FGRenderingPipeline::Pass* pass); - - osg::Camera* buildDeferredGeometryCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const std::string& name, const FGRenderingPipeline::AttachmentList& attachments ); - osg::Camera* buildDeferredShadowCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const std::string& name, const FGRenderingPipeline::AttachmentList& attachments ); - osg::Camera* buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const FGRenderingPipeline::Stage* stage ); - osg::Camera* buildDeferredFullscreenCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const FGRenderingPipeline::Stage* stage ); - osg::Camera* buildDeferredFullscreenCamera( flightgear::CameraInfo* info, const FGRenderingPipeline::Pass* pass ); - void buildDeferredDisplayCamera( osg::Camera* camera, flightgear::CameraInfo* info, const FGRenderingPipeline::Stage* stage, osg::GraphicsContext* gc ); - - void updateShadowCascade(const flightgear::CameraInfo* info, osg::Camera* camera, osg::Group* grp, int idx, double left, double right, double bottom, double top, double zNear, double f1, double f2); - osg::Vec3 getSunDirection() const; - osg::ref_ptr _ambientFactor; - osg::ref_ptr _sunDiffuse; - osg::ref_ptr _sunSpecular; - osg::ref_ptr _sunDirection; - osg::ref_ptr _planes; - osg::ref_ptr _fogColor; - osg::ref_ptr _fogDensity; - osg::ref_ptr _shadowNumber; - osg::ref_ptr _shadowDistances; - osg::ref_ptr _depthInColor; - - osg::ref_ptr _pipeline; - - void addChangeListener(SGPropertyChangeListener* l, const char* path); - - 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); -} - +#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.cxx b/src/Viewer/renderer_compositor.cxx new file mode 100644 index 000000000..b2e492377 --- /dev/null +++ b/src/Viewer/renderer_compositor.cxx @@ -0,0 +1,1165 @@ +// 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 + +#include