Andrew,

Class attached. I don't use osgEphemeris (yet) so don't know exactly how this might interact with it. My graph from bottom to top looks like :

Sphere - DepthFunction(always), depthRange(1.0,1.0), Sky texture map, fog and lighting off
  |
MoveEarthySkyTransform (or similar type thing which is probably already in osgEphemeris)
  |
ExtentsCamera
  |
Rest of scene

I also do
    extentsCamera->setRenderOrder(osg::CameraNode::PRE_RENDER);
    extentsCamera->setRenderTargetImplementation(osg::CameraNode::FRAME_BUFFER);
    extentsCamera->setClearMask(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
and put a ClearNode with RequiresClear(false) off the root node to prevent the "main renderbin" from clearing the screen again.

to place the sky first. Unfortunately I think this means pixel overdraw (you're drawing the sky behind objects) which is bad if you have expensive atmosphere shaders, but I didn't find anyway around this.

Hope that's useful.

David

#include "dvsLibrary/ExtentsCamera.h"

#include <osgUtil/CullVisitor>

CExtentsCamera::CExtentsCamera() : osg::CameraNode()
{
        // Turn culling off (possibly duplicated statements)
        this->setCullingActive(false);
        this->setCullingMode(osg::CullSettings::NO_CULLING);

        // We will compute the near/far planes ourselves
        this->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);

        // Reset our store of the projection matrix
        _matrix.identity();

        // Default near/far ranges (to bracket a viewer centred sphere with 
radius 1)
        _zNear = 0.5;   // Forcing the near plane to be 0.5m
        _zFar  = 2.0;   // Forcing the far plane to be 2m


}

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
        // NB : This may be an unnecessary test (not sure).
    unsigned int numChildren = _children.size();
    if(numChildren == 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);
    if(!cv) 
    { 
                CameraNode::traverse(nv);
                return; 
    }

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

        // For the purposes of minimising the work we need to do,
        // compare our copy of the projection matrix with the current one. If 
they
        // are the same then we don't need to do anything.
        // NB 1 : No speed trials have been done to determine whether this 
"early out" is worth it
        // NB 2 : Direct comparison of float matrices is not really a good idea
        if(projection==_matrix)
        {
                CameraNode::traverse(nv);
                return; 
    }

        // The projection matrix has changed, one way or another (e.g. first 
pass, or through
        // changing the window size
        double n,f,l,r,t,b;     // near, far, left, right, top, bottom
        projection.getFrustum(l,r,b,t,n,f);
        
        //double a = (r-l)/(t-b);
        

        // NB : This might be possible to simplify and hence optimise (haven't 
yet checked)
    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);

        // 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));
        
        // Take a copy of the projection matrix
        _matrix = projection;

        CameraNode::traverse(nv);
}

void CExtentsCamera::SetZRange(float zNear, float zFar)
{
        // NB : Should probably check that zNear!=zFar otherwise we'll get div0 
in the
        // traverse loop
        _zNear = zNear;
        _zFar = zFar;
}
#ifndef EXTENTS_CAMERA_H
#define EXTENTS_CAMERA_H

#include <osg/CameraNode>

class CExtentsCamera : public osg::CameraNode
{

    public:
                CExtentsCamera();
                virtual void traverse(osg::NodeVisitor &nv); 

                // Sets the forcing range for the near and far planes
                void SetZRange(float zNear, float zFar);
    protected:
                osg::Matrix _matrix;
                float           _zNear;
                float           _zFar;
 
};

#endif
_______________________________________________
osg-users mailing list
[email protected]
http://openscenegraph.net/mailman/listinfo/osg-users
http://www.openscenegraph.org/

Reply via email to