Hi list,

I'm trying to set a cube map to do environment mapping, based on the
osgprerendercubemap example; it works fine, as long as it's just one
object that uses the reflection.

It's like the cameras are only updated for the last object that the
reflection is applied to, as the position of the reflection remains
static on the other objects; which isn't so, because if the cameras
weren't applied it would look different than what it does now. If I
add more reflected objects, only the last one works fine.

>From the code, you'll notice that if you change line 208:

        if( 1 )
for
        if( a )

the first object will run fine, since the callback for updating the
camera will only be applied the first time; applying it to more
objects cause the problem of only having the last one working.
Therefore, it might be something related to
UpdateCameraAndTexGenCallback.

Here's the entire code, you can just copy & paste to compile and link
to libosg and libosgViewer :

#include <osg/ShapeDrawable>
#include <osg/TextureCubeMap>
#include <osg/TexGenNode>
#include <osg/TexMat>

#include <osg/PositionAttitudeTransform>
#include <osgViewer/Viewer>

class UpdateCameraAndTexGenCallback : public osg::NodeCallback
{
    public:
        UpdateCameraAndTexGenCallback( osg::NodePath reflector,
std::vector< osg::Camera* > Cameras ):
            _reflectorNodePath( reflector ),
            _Cameras( Cameras )
        {
        }

        virtual void operator()( osg::Node* node, osg::NodeVisitor* nv )
        {
            // first update subgraph to make sure objects are all
moved into position
            traverse( node, nv );

            // compute the position of the center of the reflector subgraph
            osg::Matrixd worldToLocal = osg::computeWorldToLocal(
_reflectorNodePath );
            osg::BoundingSphere bs = _reflectorNodePath.back() -> getBound();
            osg::Vec3 position = bs.center();

            typedef std::pair<osg::Vec3, osg::Vec3> ImageData;
            const ImageData id[] =
            {
                ImageData( osg::Vec3( 1,  0,  0), osg::Vec3( 0, -1,  0) ), // +X
                ImageData( osg::Vec3(-1,  0,  0), osg::Vec3( 0, -1,  0) ), // -X
                ImageData( osg::Vec3( 0,  1,  0), osg::Vec3( 0,  0,  1) ), // +Y
                ImageData( osg::Vec3( 0, -1,  0), osg::Vec3( 0,  0, -1) ), // -Y
                ImageData( osg::Vec3( 0,  0,  1), osg::Vec3( 0, -1,  0) ), // +Z
                ImageData( osg::Vec3( 0,  0, -1), osg::Vec3( 0, -1,  0) )  // -Z
            };

            for(unsigned int i=0; i < 6 && i < _Cameras.size();
                ++i)
            {
                osg::Matrix localOffset;
                localOffset.makeLookAt(position,position+id[ i
].first, id[ i ].second);

                osg::Matrix viewMatrix = worldToLocal*localOffset;

                _Cameras[i]->setReferenceFrame(osg::Camera::ABSOLUTE_RF);

_Cameras[i]->setProjectionMatrixAsFrustum(-1.0,1.0,-1.0,1.0,1.0,10000.0);
                _Cameras[i]->setViewMatrix(viewMatrix);
            }
        }

    protected:

        virtual ~UpdateCameraAndTexGenCallback() {}

        osg::NodePath               _reflectorNodePath;
        std::vector< osg::Camera*>  _Cameras;
};

class TexMatCullCallback : public osg::NodeCallback
{
    public:

        TexMatCullCallback(osg::TexMat* texmat):
            _texmat(texmat)
        {
        }

        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
        {
            // first update subgraph to make sure objects are all
moved into position
            traverse(node,nv);

            osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
            if (cv)
            {
                osg::Quat quat = cv->getModelViewMatrix()->getRotate();
                _texmat->setMatrix(osg::Matrix::rotate(quat.inverse()));
            }
        }

    protected:

        osg::ref_ptr<osg::TexMat>    _texmat;
};

osg::Group* createScene()
{
    //Make object that will be cube mapped
    osg::Geode* sphere = new osg::Geode();
    sphere->addDrawable
    (
        new osg::ShapeDrawable
        (
            new osg::Sphere
            (
                osg::Vec3( 0.0f, 0.0f, 0.0f ), 1.0f
            )
        )
    );

    osg::Geode* capsule = new osg::Geode();
    capsule->addDrawable
    (
        new osg::ShapeDrawable
        (
            new osg::Capsule
            (
                osg::Vec3( 4.0f, 0.0f, 0.0f ), 1.0f, 1.5f
            )
        )
    );

    osg::Group* shapes = new osg::Group();
    shapes->addChild( sphere );
    shapes->addChild( capsule );

    return shapes;
}

osg::TextureCubeMap* createCubeMap( const int TEXTURE_WIDTH, const int
TEXTURE_HEIGHT)
{
    osg::TextureCubeMap* texture = new osg::TextureCubeMap;

    texture->setTextureSize( TEXTURE_WIDTH, TEXTURE_HEIGHT );
    texture->setInternalFormat( GL_RGB );
    texture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE );
    texture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE );
    texture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE );
    
texture->setFilter(osg::TextureCubeMap::MIN_FILTER,osg::TextureCubeMap::LINEAR);
    
texture->setFilter(osg::TextureCubeMap::MAG_FILTER,osg::TextureCubeMap::LINEAR);

    return texture;
}

//Do those special GFX
void addReflections( osg::Group* const scene, const int REFLECTOR_ID,
osg::Group* const root, osg::TextureCubeMap* texture, const int
TEXTURE_WIDTH, const int TEXTURE_HEIGHT )
{
    osg::Group* const reflected_scene = static_cast<osg::Group*>(
scene->clone( osg::CopyOp::SHALLOW_COPY) );
    osg::Node* const reflector = reflected_scene->getChild( REFLECTOR_ID );
    reflector->ref();
    reflected_scene->removeChild( reflector );

        osg::Vec4 color ( 0.0, 1.0, 0.0, 1.0 );
        static bool a = true;
        if( !a )
        {
            color[0] = 1.0;
            color[1] = 0.0;
        }

    //Setup 6 cameras, one for each direction
    std::vector< osg::Camera* > cameras;
    for( unsigned int i = 0; i < 6; ++i )
    {
        osg::Camera* cam = new osg::Camera;

        cam->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        cam->setClearColor( color);
        cam->setViewport( 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT );

        cam->setRenderOrder( osg::Camera::PRE_RENDER );

        cam->attach( osg::Camera::COLOR_BUFFER, texture, 0, i );

        cam->addChild( reflected_scene );

        root->addChild(cam);

        cameras.push_back(cam);
    }

    const int unit = 1;

    if( a )
    {
        osg::TexGenNode* texgenNode = new osg::TexGenNode;
        texgenNode->getTexGen()->setMode( osg::TexGen::REFLECTION_MAP );
        texgenNode->setTextureUnit( unit );
        root->addChild( texgenNode );
    }

    {
        osg::StateSet* stateset = reflector->getOrCreateStateSet();
        
stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON);
        stateset->setTextureMode(unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
        stateset->setTextureMode(unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
        stateset->setTextureMode(unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
        stateset->setTextureMode(unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);

        osg::TexMat* texmat = new osg::TexMat;
        
stateset->setTextureAttributeAndModes(unit,texmat,osg::StateAttribute::ON);

        reflector->setCullCallback(new TexMatCullCallback(texmat));
    }

    osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform;
    pat->setPosition( osg::Vec3(0.0f,0.0f,0.0f));
    pat->addChild(reflector);

    osg::NodePath path;
    path.push_back(pat);
    path.push_back(reflector);

    root->addChild( pat );

    if( 1 )
        reflector->setUpdateCallback(new
UpdateCameraAndTexGenCallback(path, cameras));

    a = false;
}

int main()
{
    osg::Group* root = new osg::Group();
    const int TEXTURE_WIDTH = 512, TEXTURE_HEIGHT = 512;

    osg::Group* scene = createScene();
    root->addChild( scene );

    osg::TextureCubeMap* cube_map = createCubeMap( TEXTURE_WIDTH,
TEXTURE_HEIGHT );
    osg::TextureCubeMap* cube_map2 = createCubeMap( TEXTURE_WIDTH,
TEXTURE_HEIGHT );

    addReflections( scene, 0, root, cube_map, TEXTURE_WIDTH, TEXTURE_HEIGHT );
    addReflections( scene, 1, root, cube_map2, TEXTURE_WIDTH, TEXTURE_HEIGHT );

    {
        osgViewer::Viewer viewer;

        viewer.setSceneData( root );
        viewer.run();
    }
        return 0;
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to