+++ /dev/null
-// Copyright (C) 2008 Tim Moore
-//
-// Much of this file was copied directly from the osgdepthpartition
-// example in the OpenSceneGraph distribution, so I feel it is right
-// to preserve the license in that code:
-/*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-* THE SOFTWARE.
-*/
-
-#include <osg/CullSettings>
-#include <osg/Depth>
-#include <osg/StateSet>
-#include <osgUtil/CullVisitor>
-// For DotOsgWrapperProxy
-#include <osgDB/Registry>
-#include <osgDB/Input>
-#include <osgDB/Output>
-
-#include <simgear/scene/util/RenderConstants.hxx>
-#include "ViewPartitionNode.hxx"
-
-using namespace osg;
-
-const double ViewPartitionNode::nearCameraFar = 100.0;
-ViewPartitionNode::ViewPartitionNode():
- cameras(2), visibility(40000.0)
-{
- const GLbitfield inheritanceMask = (CullSettings::ALL_VARIABLES
- & ~CullSettings::COMPUTE_NEAR_FAR_MODE
- & ~CullSettings::NEAR_FAR_RATIO
- & ~CullSettings::CULLING_MODE);
- int i = 1;
- for (CameraList::iterator iter = cameras.begin();
- iter != cameras.end();
- ++iter, ++i) {
- Camera* camera = new Camera;
- camera->setReferenceFrame(Transform::RELATIVE_RF);
- camera->setInheritanceMask(inheritanceMask);
- camera->setComputeNearFarMode(CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
- camera->setCullingMode(CullSettings::VIEW_FRUSTUM_CULLING);
- camera->setRenderOrder(Camera::POST_RENDER, i);
- // Slave camera "above" us clears the viewport. Perhaps the
- // far camera doesn't need to clear the depth buffer; it
- // probably doesn't make much difference.
- camera->setClearMask(GL_DEPTH_BUFFER_BIT);
- *iter = camera;
- }
-}
-
-ViewPartitionNode::ViewPartitionNode(const ViewPartitionNode& rhs,
- const CopyOp& copyop) :
- cameras(2), visibility(rhs.visibility)
-{
- for (int i = 0; i < 2; i++)
- cameras[i] = static_cast<Camera*>(copyop(rhs.cameras[i].get()));
-}
-
-void ViewPartitionNode::traverse(NodeVisitor& nv)
-{
- osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
- if(!cv) {
- Group::traverse(nv);
- return;
- }
- RefMatrix& modelview = *(cv->getModelViewMatrix());
- RefMatrix& projection = *(cv->getProjectionMatrix());
- // Get the frustum of the enclosing camera. The ViewPartitionNode
- // will divide up the frustum between that camera's near and far
- // planes i.e., parentNear and ParentFar.
- double left, right, bottom, top, parentNear, parentFar;
- projection.getFrustum(left, right, bottom, top, parentNear, parentFar);
- double nearPlanes[2], farPlanes[2];
- nearPlanes[0] = nearCameraFar;
- farPlanes[0] = parentFar;
- nearPlanes[1] = parentNear;
- farPlanes[1] = nearCameraFar;
- for (int i = 0; i < 2; ++i) {
- if (farPlanes[i] >0.0) {
- ref_ptr<RefMatrix> newProj = new RefMatrix();
- makeNewProjMat(projection, nearPlanes[i], farPlanes[i],
- *newProj.get());
- cv->pushProjectionMatrix(newProj.get());
- if (i == NEAR_CAMERA) {
- // The near camera shouldn't draw the background,
- // which is hard to cull out.
- unsigned int savedTraversalMask = cv->getTraversalMask();
- cv->setTraversalMask(savedTraversalMask
- & ~simgear::BACKGROUND_BIT);
- cameras[i]->accept(nv);
- cv->setTraversalMask(savedTraversalMask);
- } else {
- cameras[i]->accept(nv);
- }
- cv->popProjectionMatrix();
- }
- }
-}
-
-bool ViewPartitionNode::addChild(osg::Node *child)
-{
- return insertChild(_children.size(), child);
-}
-
-bool ViewPartitionNode::insertChild(unsigned int index, osg::Node *child)
-{
- if(!Group::insertChild(index, child))
- return false;
- // Insert child into each Camera
-
- for (CameraList::iterator iter = cameras.begin();
- iter != cameras.end();
- ++iter) {
- (*iter)->insertChild(index, child);
- }
- return true;
-}
-
-bool ViewPartitionNode::removeChildren(unsigned int pos, unsigned int numRemove)
-{
- if (!Group::removeChildren(pos, numRemove))
- return false;
-
- // Remove child from each Camera
-
- for (CameraList::iterator iter = cameras.begin();
- iter != cameras.end();
- ++iter) {
- (*iter)->removeChildren(pos, numRemove);
- }
- return true;
-}
-
-bool ViewPartitionNode::setChild(unsigned int i, osg::Node *node)
-{
- if(!Group::setChild(i, node)) return false; // Set child
-
- // Set child for each Camera
- for (CameraList::iterator iter = cameras.begin();
- iter != cameras.end();
- ++iter) {
- (*iter)->setChild(i, node);
- }
- return true;
-}
-
-// Given a projection matrix, return a new one with the same frustum
-// sides and new near / far values.
-
-void ViewPartitionNode::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));
- }
-}
-
-namespace
-{
-bool ViewPartitionNode_readLocalData(osg::Object& obj, osgDB::Input& fr)
-{
- ViewPartitionNode& node = static_cast<ViewPartitionNode&>(obj);
- if (fr[0].matchWord("visibility")) {
- ++fr;
- double visibility;
- if (fr[0].getFloat(visibility))
- ++fr;
- else
- return false;
- node.setVisibility(visibility);
- }
- return true;
-}
-
-bool ViewPartitionNode_writeLocalData(const Object& obj, osgDB::Output& fw)
-{
- const ViewPartitionNode& node = static_cast<const ViewPartitionNode&>(obj);
- fw.indent() << "visibility " << node.getVisibility() << std::endl;
- return true;
-}
-
-osgDB::RegisterDotOsgWrapperProxy viewPartitionNodeProxy
-(
- new ViewPartitionNode,
- "ViewPartitionNode",
- "Object Node ViewPartitionNode Group",
- &ViewPartitionNode_readLocalData,
- &ViewPartitionNode_writeLocalData
- );
-}
+++ /dev/null
-// 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 VIEWPARTITIONNODE_HXX
-#define VIEWPARTITIONNODE_HXX 1
-// The ViewPartitionNode splits the viewing frustum inherited from a
-// camera higher in the scene graph (usually the Viewer master or
-// slave camera) into 3 parts: from the parent near plane to a
-// intermediate far plane (100m), then out to the current visibility,
-// and then beyond where background stuff is rendered. The depth
-// buffer and depth testing are disabled for the background.
-
-#include <osg/Camera>
-#include <osg/Group>
-#include <osg/Matrix>
-
-class ViewPartitionNode : public osg::Group
-{
-public:
- ViewPartitionNode();
- ViewPartitionNode(const ViewPartitionNode& rhs,
- const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
- META_Node(flightgear, ViewPartitionNode);
-
- /** Catch child management functions so the Cameras can be informed
- of added or removed children. */
- virtual bool addChild(osg::Node *child);
- virtual bool insertChild(unsigned int index, osg::Node *child);
- virtual bool removeChildren(unsigned int pos, unsigned int numRemove = 1);
- virtual bool setChild(unsigned int i, osg::Node *node);
- virtual void traverse(osg::NodeVisitor &nv);
- void setVisibility(double vis) { visibility = vis; }
- double getVisibility() const { return visibility; }
- static void makeNewProjMat(osg::Matrixd& oldProj, double znear, double zfar,
- osg::Matrixd& projection);
-protected:
-
- typedef std::vector< osg::ref_ptr<osg::Camera> > CameraList;
- CameraList cameras;
- enum CameraNum {
- FAR_CAMERA = 0,
- NEAR_CAMERA = 1
- };
- double visibility;
- static const double nearCameraFar;
-};
-#endif