Hello Chris,

I wonder if there were somehow a callback you could apply somewhere that would hork with the near/far clip, or if it's just easier to use multiple cameras at that point.

Perhaps in a Drawable DrawCallback? Something like:

OK, I've finally got this to work well, without the need to add an extra camera. It's a classic two-pronged attack:

1. Use a CullCallback that sets the compute near/far mode to off, traverses the skydome and resets it to the previous value. 2. Use a drawable DrawCallback on all the skydome's drawables that will calculate the maximum possible value the far plane would need to be at for the skydome to be visible from the current camera position, draws the drawable, and resets the old far plane after drawing.

One thing I found I needed to do is keep the same near plane value as was set before, otherwise the skydome seemed to move when the camera moved.

Here's the code I'm using:

struct DoNotIncludeInNearFarComputationCallback
    : public osg::NodeCallback
{
    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
    {
        osgUtil::CullVisitor *cv =
            dynamic_cast< osgUtil::CullVisitor*>( nv );

        // Default value
        osg::CullSettings::ComputeNearFarMode oldMode =
            osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES;

        if( cv )
        {
            oldMode = cv->getComputeNearFarMode();
            cv->setComputeNearFarMode(
                osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
        }

        traverse(node, nv);

        if( cv )
        {
            cv->setComputeNearFarMode(oldMode);
        }
    }
};

struct OverrideNearFarValuesCallback
    : public osg::Drawable::DrawCallback
{
    OverrideNearFarValuesCallback(SkyDome* skyDome)
        : m_skyDome(skyDome) {}

    virtual void drawImplementation(osg::RenderInfo& renderInfo,
                                    const osg::Drawable* drawable) const
    {
        osg::Camera* currentCamera = renderInfo.getCurrentCamera();
        if (currentCamera)
        {
            // Get the current camera position.
            osg::Vec3 eye, center, up;
            renderInfo.getCurrentCamera()->getViewMatrixAsLookAt(
                eye, center, up);

            // Get the max distance we need the far plane to be at,
            // which is the distance between the eye and the skydome's
            // center, plus the skydome's radius.
            double distance = (m_skyDome->getCenter() - eye).length() +
                               m_skyDome->getRadius();

            // Save old values.
            osg::ref_ptr<osg::RefMatrixd> oldProjectionMatrix =
                new osg::RefMatrix;
            oldProjectionMatrix->set(
                renderInfo.getState()->getProjectionMatrix());

            // Get the individual values
            double left, right, bottom, top, zNear, zFar;
            oldProjectionMatrix->getFrustum(
                left, right, bottom, top, zNear, zFar);

            // Build a new projection matrix with a modified far plane
            osg::ref_ptr<osg::RefMatrixd> projectionMatrix =
                new osg::RefMatrix;
            projectionMatrix->makeFrustum(
                left, right, bottom, top, zNear, distance);
            renderInfo.getState()->applyProjectionMatrix(
                projectionMatrix.get());

            // Draw the drawable
            drawable->drawImplementation(renderInfo);

            // Reset the far plane to the old value.
            renderInfo.getState()->applyProjectionMatrix(
                oldProjectionMatrix.get());
        }
        else
        {
            drawable->drawImplementation(renderInfo);
        }
    }

    SkyDome* m_skyDome;
};

struct AddCallbackToDrawablesVisitor : public osg::NodeVisitor
{
    AddCallbackToDrawablesVisitor(SkyDome* skyDome)
        : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
          m_skyDome(skyDome) {}

    virtual void apply(osg::Geode& node)
    {
        for (unsigned int i = 0; i < node.getNumDrawables(); i++)
        {
            node.getDrawable(i)->setDrawCallback(
                new OverrideNearFarValuesCallback(m_skyDome));
            // Do not use display lists otherwise the callback will only
            // be called once on initial compile.
            node.getDrawable(i)->setUseDisplayList(false);
        }
    }

    SkyDome* m_skyDome;
};


Then when adding the dome to the scene I do these extra steps:

    // Setup rendering so that the skydome does not affect the automatic
    // near/far plane calculation.
    m_node->setCullCallback(
        new DoNotIncludeInNearFarComputationCallback);
    AddCallbackToDrawablesVisitor visitor(this);
    m_node->accept(visitor);

    // Transparent bin is #10 by default so render just before
    // transparent objects.
    ss->setRenderBinDetails(9, "RenderBin");
    ss->setAttributeAndModes(
        new osg::Depth(osg::Depth::LEQUAL, 1.0, 1.0),
        osg::StateAttribute::ON);


I'm open to suggestions as to how to improve this, especially the DrawCallback (OverrideNearFarValuesCallback) which seems heavy to me (two new RefMatrix per drawable per frame...). But it works well and I like it better than the camera approach, no need to change anything else in the scene graph or viewer setup.

Hope this can help someone.

J-S
--
______________________________________________________
Jean-Sebastien Guay    jean-sebastien.g...@cm-labs.com
                               http://www.cm-labs.com/
                        http://whitestar02.webhop.org/
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
            • ... Jean-Sébastien Guay
            • ... Jean-Sébastien Guay
            • ... Doug McCorkle
            • ... Chris 'Xenon' Hanson
            • ... David Spilling
            • ... Jean-Sébastien Guay
            • ... David Spilling
            • ... Jean-Sébastien Guay
            • ... Jean-Sébastien Guay
            • ... Jean-Sébastien Guay
            • ... Jean-Sébastien Guay
            • ... Cole, Charles E. (LARC-B702)[RAYTHEON TECHNICAL SERVICES COMPANY]
            • ... Jean-Sébastien Guay
            • ... Jean-Sébastien Guay
            • ... Cole, Charles E. (LARC-B702)[RAYTHEON TECHNICAL SERVICES COMPANY]
            • ... Jean-Sébastien Guay
            • ... Jean-Sébastien Guay
          • ... David Spilling
            • ... Paul Martz
  • Re: [osg... Jean-Sébastien Guay

Reply via email to