From d2962ffb2d8d173659c1412b12e688c6192983d1 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sat, 16 Nov 2013 12:10:21 +0000 Subject: [PATCH] Reset: refactor static CameraGroup ownership --- src/Main/fg_os.hxx | 1 + src/Main/main.cxx | 3 +- src/Viewer/CameraGroup.cxx | 500 ++++++++++++++++++++------------- src/Viewer/CameraGroup.hxx | 41 ++- src/Viewer/fg_os_osgviewer.cxx | 70 ++--- 5 files changed, 356 insertions(+), 259 deletions(-) diff --git a/src/Main/fg_os.hxx b/src/Main/fg_os.hxx index 70ffb1b6c..6913e817a 100644 --- a/src/Main/fg_os.hxx +++ b/src/Main/fg_os.hxx @@ -63,6 +63,7 @@ void fgOSCloseWindow(); void fgOSFullScreen(); int fgOSMainLoop(); void fgOSExit(int code); +void fgOSResetProperties(); void fgSetMouseCursor(int cursor); int fgGetMouseCursor(); diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 84f03a6fd..b5d9dfa67 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -387,7 +387,8 @@ int fgMainInit( int argc, char **argv ) { // Clouds3D requires an alpha channel fgOSOpenWindow(true /* request stencil buffer */); - + fgOSResetProperties(); + // Initialize the splash screen right away fntInit(); fgSplashInit(); diff --git a/src/Viewer/CameraGroup.cxx b/src/Viewer/CameraGroup.cxx index b09622bb7..7eba76c5f 100644 --- a/src/Viewer/CameraGroup.cxx +++ b/src/Viewer/CameraGroup.cxx @@ -30,6 +30,7 @@ #include #include +#include // for copyProperties #include #include #include @@ -57,79 +58,116 @@ #include #include -namespace flightgear { -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"; -} - -static osg::Matrix -invert(const osg::Matrix& matrix) -{ - return osg::Matrix::inverse(matrix); -} +using namespace osg; -/// Returns the zoom factor of the master camera. -/// The reference fov is the historic 55 deg -static double -zoomFactor() +namespace { - 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); -} + + // 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; + } -static 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]); -} +} // of anonymous namespace -static 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; -} +typedef std::vector SGPropertyNodeVec; namespace flightgear { @@ -138,59 +176,121 @@ using namespace osg; using std::strcmp; using std::string; -ref_ptr CameraGroup::_defaultGroup; - -CameraGroup::CameraGroup(osgViewer::Viewer* viewer) : - _viewer(viewer) -{ -} - -} - -namespace -{ -using namespace osg; - -// 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)); - } -} -} + 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"; -namespace flightgear -{ void CameraInfo::updateCameras() { bufferSize->set( osg::Vec2f( width, height ) ); @@ -259,6 +359,11 @@ void CameraInfo::resized(double w, double h) } } +CameraInfo::~CameraInfo() +{ + +} + osg::Camera* CameraInfo::getCamera(const std::string& k) const { CameraMap::const_iterator ii = cameras.find( k ); @@ -292,6 +397,21 @@ void CameraInfo::setMatrices(osg::Camera* c) 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) { @@ -447,6 +567,13 @@ void CameraGroup::update(const osg::Vec3d& position, 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) @@ -473,74 +600,6 @@ double CameraGroup::getMasterAspectRatio() const return static_cast(viewport->height()) / viewport->width(); } - -} - -namespace -{ -// A raw value for property nodes that references a class member via -// an osg::ref_ptr. -template -class RefMember : public SGRawValue -{ -public: - RefMember (C *obj, T C::*ptr) - : _obj(obj), _ptr(ptr) {} - virtual ~RefMember () {} - virtual T getValue () const - { - return _obj.get()->*_ptr; - } - virtual bool setValue (T value) - { - _obj.get()->*_ptr = value; - return true; - } - virtual SGRawValue * clone () const - { - return new RefMember(_obj.get(), _ptr); - } -private: - ref_ptr _obj; - T C::* const _ptr; -}; - -template -RefMember makeRefMember(C *obj, T C::*ptr) -{ - return RefMember(obj, ptr); -} - -template -void bindMemberToNode(SGPropertyNode* parent, const char* childName, - C* obj, T C::*ptr, T value) -{ - SGPropertyNode* valNode = parent->getNode(childName); - RefMember refMember = makeRefMember(obj, ptr); - if (!valNode) { - valNode = parent->getNode(childName, true); - valNode->tie(refMember, false); - setValue(valNode, value); - } else { - valNode->tie(refMember, true); - } -} - -void buildViewport(flightgear::CameraInfo* info, SGPropertyNode* viewportNode, - const osg::GraphicsContext::Traits *traits) -{ - using namespace flightgear; - bindMemberToNode(viewportNode, "x", info, &CameraInfo::x, 0.0); - bindMemberToNode(viewportNode, "y", info, &CameraInfo::y, 0.0); - bindMemberToNode(viewportNode, "width", info, &CameraInfo::width, - static_cast(traits->width)); - bindMemberToNode(viewportNode, "height", info, &CameraInfo::height, - static_cast(traits->height)); -} -} - -namespace flightgear -{ // Mostly copied from osg's osgViewer/View.cpp @@ -958,6 +1017,7 @@ CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode) 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; @@ -970,10 +1030,13 @@ CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode) 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. - buildViewport(info, viewportNode, window->gc->getTraits()); + + info->viewportListener.reset(new CameraViewportListener(info, viewportNode, window->gc->getTraits())); + info->updateCameras(); // Distortion camera needs the viewport which is created by addCamera(). if (psNode) { @@ -1033,7 +1096,9 @@ CameraInfo* CameraGroup::buildGUICamera(SGPropertyNode* cameraNode, // should be assigned by a camera manager. camera->setRenderOrder(osg::Camera::POST_RENDER, 10000); SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true); - buildViewport(result, viewportNode, window->gc->getTraits()); + + result->viewportListener.reset(new CameraViewportListener(result, viewportNode, + window->gc->getTraits())); // Disable statistics for the GUI camera. camera->setStats(0); @@ -1045,6 +1110,8 @@ 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(); @@ -1056,10 +1123,7 @@ CameraGroup* CameraGroup::buildCameraGroup(osgViewer::Viewer* viewer, cgroup->buildGUICamera(pNode); } } - bindMemberToNode(gnode, "znear", cgroup, &CameraGroup::_zNear, .1f); - bindMemberToNode(gnode, "zfar", cgroup, &CameraGroup::_zFar, 120000.0f); - bindMemberToNode(gnode, "near-field", cgroup, &CameraGroup::_nearField, - 100.0f); + return cgroup; } @@ -1266,4 +1330,50 @@ void warpGUIPointer(CameraGroup* cgroup, int x, int y) * (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.hxx b/src/Viewer/CameraGroup.hxx index 1d5bd0aa0..84447e43c 100644 --- a/src/Viewer/CameraGroup.hxx +++ b/src/Viewer/CameraGroup.hxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,9 @@ 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; @@ -106,10 +109,13 @@ struct CameraInfo : public osg::Referenced 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; @@ -161,6 +167,8 @@ struct CameraInfo : public osg::Referenced osg::ref_ptr dv; osg::ref_ptr shadowMatrix[4]; + std::auto_ptr viewportListener; + void setMatrices( osg::Camera* c ); osgUtil::RenderBin::RenderBinList savedTransparentBins; @@ -172,10 +180,6 @@ struct CameraInfo : public osg::Referenced osg::Vec2d thisReference[2]; }; -/** Update the OSG cameras from the camera info. - */ -void updateCameras(const CameraInfo* info); - class CameraGroup : public osg::Referenced { public: @@ -198,6 +202,9 @@ public: * @param viewer the viewer */ CameraGroup(osgViewer::Viewer* viewer); + + ~CameraGroup(); + /** Get the camera group's Viewer. * @return the viewer */ @@ -236,11 +243,15 @@ public: * 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; @@ -253,12 +264,6 @@ public: ConstCameraIterator camerasBegin() const { return _cameras.begin(); } ConstCameraIterator camerasEnd() const { return _cameras.end(); } void addCamera(CameraInfo* info) { _cameras.push_back(info); } - /** 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); /** Set the cull mask on all non-GUI cameras */ void setCameraCullMasks(osg::Node::NodeMask nm); @@ -278,16 +283,30 @@ public: * 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::auto_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); }; } diff --git a/src/Viewer/fg_os_osgviewer.cxx b/src/Viewer/fg_os_osgviewer.cxx index 01c646cd8..976b3d753 100644 --- a/src/Viewer/fg_os_osgviewer.cxx +++ b/src/Viewer/fg_os_osgviewer.cxx @@ -101,7 +101,7 @@ using namespace std; using namespace flightgear; using namespace osg; -static osg::ref_ptr viewer; +osg::ref_ptr viewer; static osg::ref_ptr mainCamera; static void setStereoMode( const char * mode ) @@ -251,12 +251,9 @@ void fgOSOpenWindow(bool stencil) { osg::setNotifyHandler(new NotifyLogger); - SGPropertyNode* osgLevel = fgGetNode("/sim/rendering/osg-notify-level", true); - osgLevel->addChangeListener(new NotifyLevelListener, true); - viewer = new osgViewer::Viewer; viewer->setDatabasePager(FGScenery::getPagerSingleton()); - CameraGroup* cameraGroup = 0; + std::string mode; mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded"); if (mode == "AutomaticSelection") @@ -270,49 +267,8 @@ void fgOSOpenWindow(bool stencil) else viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded); WindowBuilder::initWindowBuilder(stencil); - WindowBuilder *windowBuilder = WindowBuilder::getWindowBuilder(); - - // 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); - } - } - vector cameras = cgroupNode->getChildren("camera"); - SGPropertyNode* masterCamera = 0; - BOOST_FOREACH(SGPropertyNode_ptr& camera, cameras) { - if (camera->getDoubleValue("shear-x", 0.0) == 0.0 - && camera->getDoubleValue("shear-y", 0.0) == 0.0) { - masterCamera = camera.ptr(); - break; - } - } - if (!masterCamera) { - 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 = CameraGroup::buildCameraGroup(viewer.get(), cgroupNode); - Camera* guiCamera = getGUICamera(cameraGroup); - if (guiCamera) { - Viewport* guiViewport = guiCamera->getViewport(); - fgSetInt("/sim/startup/xsize", guiViewport->width()); - fgSetInt("/sim/startup/ysize", guiViewport->height()); - } + CameraGroup::buildDefaultGroup(viewer.get()); + FGEventHandler* manipulator = globals->get_renderer()->getEventHandler(); WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA(); if (wsa->windows.size() != 1) { @@ -325,8 +281,20 @@ void fgOSOpenWindow(bool stencil) // The viewer won't start without some root. viewer->setSceneData(new osg::Group); globals->get_renderer()->setViewer(viewer.get()); - CameraGroup::setDefault(cameraGroup); +} +void fgOSResetProperties() +{ + SGPropertyNode* osgLevel = fgGetNode("/sim/rendering/osg-notify-level", true); + osgLevel->addChangeListener(new NotifyLevelListener, true); + + osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault()); + if (guiCamera) { + Viewport* guiViewport = guiCamera->getViewport(); + fgSetInt("/sim/startup/xsize", guiViewport->width()); + fgSetInt("/sim/startup/ysize", guiViewport->height()); + } + DisplaySettings * displaySettings = DisplaySettings::instance(); fgTie("/sim/rendering/osg-displaysettings/eye-separation", displaySettings, &DisplaySettings::getEyeSeparation, &DisplaySettings::setEyeSeparation ); fgTie("/sim/rendering/osg-displaysettings/screen-distance", displaySettings, &DisplaySettings::getScreenDistance, &DisplaySettings::setScreenDistance ); @@ -350,13 +318,11 @@ void fgOSExit(int code) int fgOSMainLoop() { - ref_ptr manipulator - = globals->get_renderer()->getEventHandler(); viewer->setReleaseContextAtEndOfFrameHint(false); if (!viewer->isRealized()) viewer->realize(); while (!viewer->done()) { - fgIdleHandler idleFunc = manipulator->getIdleHandler(); + fgIdleHandler idleFunc = globals->get_renderer()->getEventHandler()->getIdleHandler(); if (idleFunc) (*idleFunc)(); globals->get_renderer()->update(); -- 2.39.5