Hi,

I made an executable example based on the osgtexture2D example. I removed the 
code to render the different walls of the cube with the exception of the filter 
wall. I kept the rest as close to the original as possible. changes to the code 
have been marked using comments.

Essentially all I'm doing is generating an input image instead of loading one.


Code:

#include <osg/Node>
#include <osg/Geometry>
#include <osg/Notify>
#include <osg/MatrixTransform>
#include <osg/Texture2D>
#include <osg/DrawPixels>
#include <osg/PolygonOffset>
#include <osg/Geode>

#include <osgDB/Registry>
#include <osgDB/ReadFile>

#include <osgText/Text>

#include <osgViewer/Viewer>

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// filter wall and animation callback.
//

class FilterCallback : public osg::NodeCallback
{
public:

    FilterCallback(osg::Texture2D* texture,osgText::Text* text,double 
delay=1.0):
        _texture(texture),
        _text(text),
        _delay(delay),
        _currPos(0),
        _prevTime(0.0)
    {
        // start with a mip mapped mode to ensure that
        _minFilterList.push_back(osg::Texture2D::LINEAR_MIPMAP_LINEAR);
        _magFilterList.push_back(osg::Texture2D::LINEAR);
        _textList.push_back("Tri-linear mip mapping (default 
filtering)\nsetFilter(MIN_FILTER,LINEAR_MIP_LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");

        _minFilterList.push_back(osg::Texture2D::NEAREST);
        _magFilterList.push_back(osg::Texture2D::NEAREST);
        _textList.push_back("Nearest 
filtering\nsetFilter(MIN_FILTER,NEAREST)\nsetFilter(MAG_FILTER,NEAREST)");

        _minFilterList.push_back(osg::Texture2D::LINEAR);
        _magFilterList.push_back(osg::Texture2D::LINEAR);
        _textList.push_back("Linear 
filtering\nsetFilter(MIN_FILTER,LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");

        _minFilterList.push_back(osg::Texture2D::NEAREST_MIPMAP_NEAREST);
        _magFilterList.push_back(osg::Texture2D::LINEAR);
        _textList.push_back("nearest mip mapping (default 
filtering)\nsetFilter(MIN_FILTER,)\nsetFilter(MAG_FILTER,LINEAR)");

        _minFilterList.push_back(osg::Texture2D::LINEAR_MIPMAP_NEAREST);
        _magFilterList.push_back(osg::Texture2D::LINEAR);
        _textList.push_back("bi-linear mip 
mapping\nsetFilter(MIN_FILTER,LINEAR_MIPMAP_NEAREST)\nsetFilter(MAG_FILTER,LINEAR)");

        _minFilterList.push_back(osg::Texture2D::NEAREST_MIPMAP_LINEAR);
        _magFilterList.push_back(osg::Texture2D::LINEAR);
        _textList.push_back("bi-linear mip 
mapping\nsetFilter(MIN_FILTER,NEAREST_MIPMAP_LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");


        setValues();
    }

    virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
    {
        if (nv->getFrameStamp())
        {
            double currTime = nv->getFrameStamp()->getSimulationTime();
            if (currTime-_prevTime>_delay)
            {
                // update filter modes and text.
                setValues();

                // advance the current position, wrap round if required.
                _currPos++;
                if (_currPos>=_minFilterList.size()) _currPos=0;

                // record time
                _prevTime = currTime;
            }
        }
    }

    void setValues()
    {
        
_texture->setFilter(osg::Texture2D::MIN_FILTER,_minFilterList[_currPos]);
        
_texture->setFilter(osg::Texture2D::MAG_FILTER,_magFilterList[_currPos]);

        _text->setText(_textList[_currPos]);
    }

protected:

    typedef std::vector<osg::Texture2D::FilterMode> FilterList;
    typedef std::vector<std::string>                TextList;

    osg::ref_ptr<osg::Texture2D>    _texture;
    osg::ref_ptr<osgText::Text>     _text;
    double                          _delay;

    FilterList                      _minFilterList;
    FilterList                      _magFilterList;
    TextList                        _textList;

    unsigned int                    _currPos;
    double                          _prevTime;

};

osg::Node* createFilterWall(osg::BoundingBox& bb,osg::Image *img)
{
    osg::Group* group = new osg::Group;

    // left hand side of bounding box.
    osg::Vec3 top_left(bb.xMin(),bb.yMin(),bb.zMax());
    osg::Vec3 bottom_left(bb.xMin(),bb.yMin(),bb.zMin());
    osg::Vec3 bottom_right(bb.xMin(),bb.yMax(),bb.zMin());
    osg::Vec3 top_right(bb.xMin(),bb.yMax(),bb.zMax());
    osg::Vec3 
center(bb.xMin(),(bb.yMin()+bb.yMax())*0.5f,(bb.zMin()+bb.zMax())*0.5f);
    float height = bb.zMax()-bb.zMin();

    // create the geometry for the wall.
    osg::Geometry* geom = new osg::Geometry;

    osg::Vec3Array* vertices = new osg::Vec3Array(4);
    (*vertices)[0] = top_left;
    (*vertices)[1] = bottom_left;
    (*vertices)[2] = bottom_right;
    (*vertices)[3] = top_right;
    geom->setVertexArray(vertices);

    osg::Vec2Array* texcoords = new osg::Vec2Array(4);
    (*texcoords)[0].set(0.0f,1.0f);
    (*texcoords)[1].set(0.0f,0.0f);
    (*texcoords)[2].set(1.0f,0.0f);
    (*texcoords)[3].set(1.0f,1.0f);
    geom->setTexCoordArray(0,texcoords);

    osg::Vec3Array* normals = new osg::Vec3Array(1);
    (*normals)[0].set(1.0f,0.0f,0.0f);
    geom->setNormalArray(normals, osg::Array::BIND_OVERALL);

    osg::Vec4Array* colors = new osg::Vec4Array(1);
    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
    geom->setColorArray(colors, osg::Array::BIND_OVERALL);

    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));

    osg::Geode* geom_geode = new osg::Geode;
    geom_geode->addDrawable(geom);
    group->addChild(geom_geode);


    // set up the texture state.
    osg::Texture2D* texture = new osg::Texture2D;
    texture->setDataVariance(osg::Object::DYNAMIC); // protect from being 
optimized away as static state.
    texture->setImage(img); //////<-- setting image directly from ptr (original 
used osgDB::readImageFile() )

    osg::StateSet* stateset = geom->getOrCreateStateSet();
    stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);

    // create the text label.

    osgText::Text* text = new osgText::Text;
    text->setDataVariance(osg::Object::DYNAMIC);

    text->setFont("fonts/arial.ttf");
    text->setPosition(center);
    text->setCharacterSize(height*0.03f);
    text->setAlignment(osgText::Text::CENTER_CENTER);
    text->setAxisAlignment(osgText::Text::YZ_PLANE);

    osg::Geode* text_geode = new osg::Geode;
    text_geode->addDrawable(text);

    osg::StateSet* text_stateset = text_geode->getOrCreateStateSet();
    text_stateset->setAttributeAndModes(new 
osg::PolygonOffset(-1.0f,-1.0f),osg::StateAttribute::ON);

    group->addChild(text_geode);

    // set the update callback to cycle through the various min and mag filter 
modes.
    group->setUpdateCallback(new FilterCallback(texture,text));

    return group;

}


osg::Node* createModel()
{

    // create the root node which will hold the model.
    osg::Group* root = new osg::Group();

    // turn off lighting
    root->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);

    osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);

/////////// NEW CODE: ///////////////
                int w=10,h=10;
                GLubyte * pixels=(GLubyte*)calloc(w*h*3,sizeof(GLubyte));
        int pixelCount=0;

        for(int i=0;i<100;i++){
                int x=pixelCount%w;
                int y=int(pixelCount/w);

                int xy = y*w + x;
                
//pixels[xy*3]=GLubyte(stoi(tile->ToConstScalarToken()->GetRawData()));
                pixels[xy*3]=GLubyte(unsigned(x<6?180:10));
                pixels[xy*3+1]=0;
                pixels[xy*3+2]=0;

                pixelCount++;
        }
        osg::Image* m_tileDataImg = new osg::Image;
        
m_tileDataImg->setImage(w,h,1,GL_RGB,GL_RGB,GL_UNSIGNED_BYTE,pixels,osg::Image::NO_DELETE);
 
/////////// END NEW CODE: ///////////////

    root->addChild(createFilterWall(bb,m_tileDataImg)); ///// <-- passing image 
ptr (original code used image filename)

    return root;
}

int main(int , char **)
{
    // construct the viewer.
    osgViewer::Viewer viewer;

    // add model to viewer.
    viewer.setSceneData( createModel() );

    return viewer.run();
}




Note that the filter wall is on the side of the cube, so you have to rotate it 
before you see anything.

The input image which I am generating is the following (verified by using 
osgDB::writeImageFile() to output it):

[Image: https://i.imgur.com/8YUX0UD.png ]
It might be too small to see, but the important part is that it contains only 
two colors.


The result I get with nearest filtering:
[Image: https://i.imgur.com/h6MIpI9.png ]
Suddenly there is a band with an intermediate color which is not present in the 
input.


The expected result (created by editing the screenshot):
[Image: https://i.imgur.com/Plew0gD.png ]

I'm not sure how the images translate to the mailing list, so just in case: 
this is the imgur album containing the three images: https://imgur.com/a/rNFu0

Thank you!

Cheers,
antiro[img][/img]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=72972#72972





_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to