If your geometry (such as a skydome) is not changing and always has the same
near and far extents, then it would be inefficient to derive an entire new
Camera node just to compute near and far values redundantly in every cull
traversal. Unless I'm missing something here, why not just disable auto
compute for the skydome camera and set the near and far planes explicitly?
Then use a separate camera to render the rest of the scene, with auto
compute enabled?
Paul Martz
Skew Matrix Software LLC
http://www.skew-matrix.com <http://www.skew-matrix.com/> 
+1 303 859 9466


From: osg-users-boun...@lists.openscenegraph.org
[mailto:osg-users-boun...@lists.openscenegraph.org] On Behalf Of David
Sent: Tuesday, April 21, 2009 2:30 PM
To: OpenSceneGraph Users
Subject: Re: [osg-users] Geometry considered in near+far plane

J-S (and others),

You could look at doing this is the same way the depth partition node does
it, which is what I do:

I use a class based on an OSG camera with an overriden traverse method, that
forces the projection matrix to a particular z near and z far. Oh, and the
camera has setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
in its constructor. The skydome is then a child of this camera.

You then set the z near and z far to be whatever you want (i.e. enveloping
your skydome radius). I typically have a skydome with a radius of 1

void CExtentsCamera::traverse(osg::NodeVisitor &nv)
    // If the scene hasn't been defined (i.e. we have no children at all)
then don't do anything
    if(_children.size() == 0) return;

    // If the visitor is not a cull visitor, then we are not interested in
intercepting it, so pass it directly onto the scene.
    osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);

    // Get a reference to the Cull Visitor's projection matrix
    osg::Matrix* projection = cv->getProjectionMatrix();

    // NB : This might be possible to simplify and hence optimise (haven't
yet checked)
    double a = (*projection)(2,2);
    double b = (*projection)(3,2);
    double c = (*projection)(2,3);
     double d = (*projection)(3,3);
    double trans_near = (-_zNear*a + b) / (-_zNear*c + d);
    double trans_far  = ( -_zFar*a + b) / ( -_zFar*c + d);
    double ratio = fabs(2.0/(trans_near - trans_far));
    double center = -0.5*(trans_near + trans_far);

    // Set the projection matrix
    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));

Probably a better way of doing it, but it works fine for me.

I also do this on the "camera"'s stateset

        osg::Depth* depth = new osg::Depth;        
        stateSet->setAttributeAndModes(depth,osg::StateAttribute::ON );   

so that you can render the sky last, and any expensive pixel shaders don't
get unnecessarily run.

Hope that helps,


osg-users mailing list

Reply via email to