From d43e0b83f715575123ea23eb72d33dd2ae436096 Mon Sep 17 00:00:00 2001 From: timoore Date: Sat, 27 Dec 2008 14:35:33 +0000 Subject: [PATCH 1/5] Expose the CameraGroup near, far, and near/far boundry as properties The near/far boundary, called "near-field", can be set to 0 which disables the far camera and renders the whole scene using only one camera. I'm hoping that this may be useful in resolving some system-specific rendering bugs. Various fixes were made to correctly render the scene using only the near camera. --- src/Main/CameraGroup.cxx | 40 ++++++++++++++++++++++++------------ src/Main/CameraGroup.hxx | 4 ++++ src/Main/fg_os_osgviewer.cxx | 6 +++--- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 4e968fc2d..938008967 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -146,8 +146,8 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera, info->farSlaveIndex = _viewer->getNumSlaves() - 1; farCamera->setRenderOrder(Camera::NESTED_RENDER, info->farSlaveIndex); camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT); + camera->setClearMask(GL_DEPTH_BUFFER_BIT); } - camera->setClearMask(GL_DEPTH_BUFFER_BIT); _viewer->addSlave(camera, view, projection, useMasterSceneData); installCullVisitor(camera); info->camera = camera; @@ -190,18 +190,22 @@ void CameraGroup::update(const osg::Vec3d& position, double left, right, bottom, top, parentNear, parentFar; projectionMatrix.getFrustum(left, right, bottom, top, parentNear, parentFar); - if (parentFar < 100.0) { + if (parentFar < _nearField || _nearField == 0.0f) { camera->setProjectionMatrix(projectionMatrix); camera->setCullMask(camera->getCullMask() | simgear::BACKGROUND_BIT); + camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); farCamera->setNodeMask(0); } else { Matrix nearProj, farProj; - makeNewProjMat(projectionMatrix, parentNear, 100.0, nearProj); - makeNewProjMat(projectionMatrix, 100.0, parentFar, farProj); + makeNewProjMat(projectionMatrix, parentNear, _nearField, + nearProj); + makeNewProjMat(projectionMatrix, _nearField, parentFar, + farProj); camera->setProjectionMatrix(nearProj); camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT); + camera->setClearMask(GL_DEPTH_BUFFER_BIT); farCamera->setProjectionMatrix(farProj); farCamera->setNodeMask(camera->getNodeMask()); } @@ -211,11 +215,9 @@ void CameraGroup::update(const osg::Vec3d& position, void CameraGroup::setCameraParameters(float vfov, float aspectRatio) { - const float zNear = .1f; - const float zFar = 120000.0f; _viewer->getCamera()->setProjectionMatrixAsPerspective(vfov, 1.0f / aspectRatio, - zNear, zFar); + _zNear, _zFar); } } @@ -444,16 +446,25 @@ CameraGroup* CameraGroup::buildCameraGroup(osgViewer::Viewer* viewer, cgroup->buildGUICamera(pNode); } } + bindMemberToNode(gnode, "znear", cgroup, &CameraGroup::_zNear, .4f); + bindMemberToNode(gnode, "zfar", cgroup, &CameraGroup::_zFar, 120000.0f); + bindMemberToNode(gnode, "near-field", cgroup, &CameraGroup::_nearField, + 100.0f); return cgroup; } void CameraGroup::setCameraCullMasks(Node::NodeMask nm) { for (CameraIterator i = camerasBegin(), e = camerasEnd(); i != e; ++i) { - if ((*i)->flags & GUI) + CameraInfo* info = i->get(); + if (info->flags & GUI) continue; - (*i)->camera->setCullMask(nm & ~simgear::BACKGROUND_BIT); - (*i)->farCamera->setCullMask(nm); + if (info->farCamera.valid() && info->farCamera->getNodeMask() != 0) { + info->camera->setCullMask(nm & ~simgear::BACKGROUND_BIT); + info->farCamera->setCullMask(nm); + } else { + info->camera->setCullMask(nm); + } } } @@ -512,9 +523,12 @@ bool computeIntersections(const CameraGroup* cgroup, Matrix windowMat = viewport->computeWindowMatrix(); Matrix startPtMat = Matrix::inverse(camera->getProjectionMatrix() * windowMat); - Matrix endPtMat - = Matrix::inverse(cinfo->farCamera->getProjectionMatrix() - * windowMat); + Matrix endPtMat; + if (!cinfo->farCamera.valid() || cinfo->farCamera->getNodeMask() == 0) + endPtMat = startPtMat; + else + endPtMat = Matrix::inverse(cinfo->farCamera->getProjectionMatrix() + * windowMat); start = start * startPtMat; start /= start.w(); end = end * endPtMat; diff --git a/src/Main/CameraGroup.hxx b/src/Main/CameraGroup.hxx index d44b90226..79d0d33d4 100644 --- a/src/Main/CameraGroup.hxx +++ b/src/Main/CameraGroup.hxx @@ -182,6 +182,10 @@ protected: CameraList _cameras; osg::ref_ptr _viewer; static osg::ref_ptr _defaultGroup; + // Near, far for the master camera if used. + float _zNear; + float _zFar; + float _nearField; }; } diff --git a/src/Main/fg_os_osgviewer.cxx b/src/Main/fg_os_osgviewer.cxx index 628be1612..af92bc82f 100644 --- a/src/Main/fg_os_osgviewer.cxx +++ b/src/Main/fg_os_osgviewer.cxx @@ -103,9 +103,9 @@ void fgOSOpenWindow(bool stencil) // Look for windows, camera groups, and the old syntax of // top-level cameras SGPropertyNode* renderingNode = fgGetNode("/sim/rendering"); - SGPropertyNode* cgroupNode = renderingNode->getChild("camera-group"); - if (!cgroupNode) { - cgroupNode = renderingNode->getNode("camera-group", true); + 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(); From 60e8f14d5b193671167470c7e325527fc01b1e88 Mon Sep 17 00:00:00 2001 From: timoore Date: Tue, 30 Dec 2008 09:32:53 +0000 Subject: [PATCH 2/5] Don't clone far camera; create a new one and initialize it from the near camera The clone operation may be sharing things that shouldn't be shared. --- src/Main/CameraGroup.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 938008967..9e848978d 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -134,8 +134,11 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera, Camera* farCamera = 0; if ((flags & (GUI | ORTHO)) == 0) { - farCamera = simgear::clone(camera); + farCamera = new Camera; + farCamera->setAllowEventFocus(camera->getAllowEventFocus()); farCamera->setGraphicsContext(camera->getGraphicsContext()); + farCamera->setCullingMode(camera->getCullingMode()); + farCamera->setInheritanceMask(camera->getInheritanceMask()); // Each camera's viewport is written when the window is // resized; if the the viewport isn't copied here, it gets updated // twice and ends up with the wrong value. From ada7f622d719c961015b148acfc1274e51f52cdc Mon Sep 17 00:00:00 2001 From: timoore Date: Tue, 30 Dec 2008 21:09:46 +0000 Subject: [PATCH 3/5] Change the order of the main cameras from NESTED_RENDER to POST_RENDER This seems to be accepted OSG usage for slave cameras. It's possible that this order is important for rendering instruments that use RTT textures on systems without frame buffer object support. I'm thinking that the resulting bugs may be implicated in the "black rectangle" problem. --- src/Main/CameraGroup.cxx | 4 ++-- src/Scenery/redout.cxx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 9e848978d..06dab8efa 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -147,7 +147,7 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera, installCullVisitor(farCamera); info->farCamera = farCamera; info->farSlaveIndex = _viewer->getNumSlaves() - 1; - farCamera->setRenderOrder(Camera::NESTED_RENDER, info->farSlaveIndex); + farCamera->setRenderOrder(Camera::POST_RENDER, info->farSlaveIndex); camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT); camera->setClearMask(GL_DEPTH_BUFFER_BIT); } @@ -155,7 +155,7 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera, installCullVisitor(camera); info->camera = camera; info->slaveIndex = _viewer->getNumSlaves() - 1; - camera->setRenderOrder(Camera::NESTED_RENDER, info->slaveIndex); + camera->setRenderOrder(Camera::POST_RENDER, info->slaveIndex); _cameras.push_back(info); return info; } diff --git a/src/Scenery/redout.cxx b/src/Scenery/redout.cxx index b6ff2dc4d..1555a3305 100644 --- a/src/Scenery/redout.cxx +++ b/src/Scenery/redout.cxx @@ -101,7 +101,7 @@ osg::Node* FGCreateRedoutNode() camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); camera->setProjectionMatrix(osg::Matrix::ortho2D(-1, 1, -1, 1)); camera->setViewMatrix(osg::Matrix::identity()); - camera->setRenderOrder(osg::Camera::POST_RENDER, 10); + camera->setRenderOrder(osg::Camera::POST_RENDER, 99); camera->setClearMask(0); camera->setAllowEventFocus(false); camera->setCullingActive(false); From 74031287b4d60f789a90248bcdc0dc3cfba5d17f Mon Sep 17 00:00:00 2001 From: timoore Date: Tue, 30 Dec 2008 23:36:51 +0000 Subject: [PATCH 4/5] Set BACKGROUND_BIT as camera node mask. This prevents the dreaded black rectangle from appearing on systems that don't have OpenGL frame buffer object support. --- src/Instrumentation/od_gauge.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Instrumentation/od_gauge.cxx b/src/Instrumentation/od_gauge.cxx index 25184450c..820f0a9d8 100644 --- a/src/Instrumentation/od_gauge.cxx +++ b/src/Instrumentation/od_gauge.cxx @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -53,6 +54,8 @@ FGODGauge::FGODGauge() : void FGODGauge::allocRT () { camera = new osg::Camera; + // Only the far camera should trigger this texture to be rendered. + camera->setNodeMask(simgear::BACKGROUND_BIT); camera->setProjectionMatrix(osg::Matrix::ortho2D(-256.0, 256.0, -256.0, 256.0)); camera->setViewport(0, 0, textureWH, textureWH); From 61a496c2ea5e6435404fcda5b07a5e5ee1432ff9 Mon Sep 17 00:00:00 2001 From: timoore Date: Thu, 1 Jan 2009 09:35:15 +0000 Subject: [PATCH 5/5] Set far camera reference frame to ABSOLUTE_RF This was lost when I stopped cloning the near camera to make the far camera. The result was a lot of breakage, including explicit camera configurations not working and various ordering issues too. --- src/Main/CameraGroup.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 06dab8efa..2ff1bb169 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -139,6 +139,7 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera, farCamera->setGraphicsContext(camera->getGraphicsContext()); farCamera->setCullingMode(camera->getCullingMode()); farCamera->setInheritanceMask(camera->getInheritanceMask()); + farCamera->setReferenceFrame(Transform::ABSOLUTE_RF); // Each camera's viewport is written when the window is // resized; if the the viewport isn't copied here, it gets updated // twice and ends up with the wrong value.