root/OpenSceneGraph/trunk/examples/osgtexture1D/osgtexture1D.cpp @ 5763

Revision 5763, 8.1 kB (checked in by robert, 8 years ago)

Added support for float or double osg::Plane, and the default osg::Plane to double.
Performance tests on big models did not indicate any performance penalty in using doubles over floats,
so the move to doubles should mainly impact precision improvements for whole earth databases.

Also made improvements to osgUtil::PlaneIntersector? and osgSim::ElevationSlice? classes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Notify>
2#include <osg/Texture1D>
3#include <osg/TexGen>
4#include <osg/Material>
5
6#include <osgDB/Registry>
7#include <osgDB/ReadFile>
8
9#include <osgProducer/Viewer>
10
11
12// Creates a stateset which contains a 1D texture which is populated by contour banded color
13// this is then used in conjunction with TexGen to create contoured models, either in
14// object linear coords - like contours on a map, or eye linear which contour the distance from
15// the eye. An app callback toggles between the two tex gen modes.
16osg::StateSet* create1DTextureStateToDecorate(osg::Node* loadedModel)
17{
18   
19    const osg::BoundingSphere& bs = loadedModel->getBound();
20   
21    osg::Image* image = new osg::Image;
22
23    int noPixels = 1024;
24   
25    // allocate the image data, noPixels x 1 x 1 with 4 rgba floats - equivilant to a Vec4!
26    image->allocateImage(noPixels,1,1,GL_RGBA,GL_FLOAT);
27    image->setInternalTextureFormat(GL_RGBA);
28   
29    typedef std::vector<osg::Vec4> ColorBands;
30    ColorBands colorbands;
31    colorbands.push_back(osg::Vec4(0.0f,0.0,0.0,1.0f));
32    colorbands.push_back(osg::Vec4(1.0f,0.0,0.0,1.0f));
33    colorbands.push_back(osg::Vec4(1.0f,1.0,0.0,1.0f));
34    colorbands.push_back(osg::Vec4(0.0f,1.0,0.0,1.0f));
35    colorbands.push_back(osg::Vec4(0.0f,1.0,1.0,1.0f));
36    colorbands.push_back(osg::Vec4(0.0f,0.0,1.0,1.0f));
37    colorbands.push_back(osg::Vec4(1.0f,0.0,1.0,1.0f));
38    colorbands.push_back(osg::Vec4(1.0f,1.0,1.0,1.0f));
39
40    float nobands = colorbands.size();
41    float delta = nobands/(float)noPixels;
42    float pos = 0.0f;
43
44    // fill in the image data.   
45    osg::Vec4* dataPtr = (osg::Vec4*)image->data();
46    for(int i=0;i<noPixels;++i,pos+=delta)
47    {
48        //float p = floorf(pos);
49        //float r = pos-p;
50        //osg::Vec4 color = colorbands[(int)p]*(1.0f-r);
51        //if (p+1<colorbands.size()) color += colorbands[(int)p+1]*r;
52        osg::Vec4 color = colorbands[(int)pos];
53        *dataPtr++ = color;
54    }
55   
56    osg::Texture1D* texture = new osg::Texture1D;
57    texture->setWrap(osg::Texture1D::WRAP_S,osg::Texture1D::MIRROR);
58    texture->setFilter(osg::Texture1D::MIN_FILTER,osg::Texture1D::LINEAR);
59    texture->setImage(image);
60
61    float zBase = bs.center().z()-bs.radius();
62    float zScale = 2.0f/bs.radius();
63   
64    osg::TexGen* texgen = new osg::TexGen;
65    texgen->setMode(osg::TexGen::OBJECT_LINEAR);
66    texgen->setPlane(osg::TexGen::S,osg::Plane(0.0f,0.0f,zScale,-zBase));
67   
68    osg::Material* material = new osg::Material;
69   
70    osg::StateSet* stateset = new osg::StateSet;
71   
72    stateset->setTextureAttribute(0,texture,osg::StateAttribute::OVERRIDE);
73    stateset->setTextureMode(0,GL_TEXTURE_1D,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
74    stateset->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
75    stateset->setTextureMode(0,GL_TEXTURE_3D,osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
76
77    stateset->setTextureAttribute(0,texgen,osg::StateAttribute::OVERRIDE);
78    stateset->setTextureMode(0,GL_TEXTURE_GEN_S,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
79   
80    stateset->setAttribute(material,osg::StateAttribute::OVERRIDE);
81   
82    return stateset;
83}
84
85
86// An app callback which alternates the tex gen mode between object linear and eye linear to illustrate what differences it makes.
87class AnimateStateCallback : public osg::NodeCallback
88{
89    public:
90        AnimateStateCallback() {}
91       
92        void animateState(osg::StateSet* stateset,double time)
93        {
94            // here we simply get any existing texgen, and then increment its
95            // plane, pushing the R coordinate through the texture.
96            osg::StateAttribute* attribute = stateset->getTextureAttribute(0,osg::StateAttribute::TEXGEN);
97            osg::TexGen* texgen = dynamic_cast<osg::TexGen*>(attribute);
98            if (texgen)
99            {
100                const double timeInterval = 1.0f;
101               
102                static double previousTime = time;
103                static bool state = false;
104                while (time>previousTime+timeInterval)
105                {
106                    previousTime+=timeInterval;
107                    state = !state;
108                }
109           
110                if (state)
111                {
112                    texgen->setMode(osg::TexGen::OBJECT_LINEAR);
113                }
114                else
115                {
116                    texgen->setMode(osg::TexGen::EYE_LINEAR);
117                }
118            }
119           
120        }
121
122        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
123        {
124
125            osg::StateSet* stateset = node->getStateSet();
126            if (stateset && nv->getFrameStamp())
127            {
128                // we have an exisitng stateset, so lets animate it.
129                animateState(stateset,nv->getFrameStamp()->getReferenceTime());
130            }
131
132            // note, callback is repsonsible for scenegraph traversal so
133            // should always include call the traverse(node,nv) to ensure
134            // that the rest of cullbacks and the scene graph are traversed.
135            traverse(node,nv);
136        }
137};
138
139
140int main( int argc, char **argv )
141{
142
143    // use an ArgumentParser object to manage the program arguments.
144    osg::ArgumentParser arguments(&argc,argv);
145
146    // set up the usage document, in case we need to print out how to use this program.
147    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use of 1D textures.");
148    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
149    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
150   
151    // construct the viewer.
152    osgProducer::Viewer viewer(arguments);
153
154    // set up the value with sensible default event handlers.
155    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
156
157    // get details on keyboard and mouse bindings used by the viewer.
158    viewer.getUsage(*arguments.getApplicationUsage());
159
160    // if user request help write it out to cout.
161    if (arguments.read("-h") || arguments.read("--help"))
162    {
163        arguments.getApplicationUsage()->write(std::cout);
164        return 1;
165    }
166
167    // any option left unread are converted into errors to write out later.
168    arguments.reportRemainingOptionsAsUnrecognized();
169
170    // report any errors if they have occured when parsing the program aguments.
171    if (arguments.errors())
172    {
173        arguments.writeErrorMessages(std::cout);
174        return 1;
175    }
176   
177    if (arguments.argc()<=1)
178    {
179        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
180        return 1;
181    }
182
183    // load the images specified on command line
184    osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
185
186   
187    if (loadedModel)
188    {
189
190        osg::StateSet* stateset = create1DTextureStateToDecorate(loadedModel);
191        if (!stateset)
192        {
193            std::cout<<"Error: failed to create 1D texture state."<<std::endl;
194            return 1;
195        }
196
197
198        loadedModel->setStateSet(stateset);
199        loadedModel->setUpdateCallback(new AnimateStateCallback());
200
201        // add model to viewer.
202        viewer.setSceneData( loadedModel );
203
204        // create the windows and run the threads.
205        viewer.realize();
206
207        while( !viewer.done() )
208        {
209            // wait for all cull and draw threads to complete.
210            viewer.sync();
211
212            // update the scene by traversing it with the the update visitor which will
213            // call all node update callbacks and animations.
214            viewer.update();
215
216            // fire off the cull and draw traversals of the scene.
217            viewer.frame();
218
219        }
220   
221        // wait for all cull and draw threads to complete.
222        viewer.sync();
223
224        // run a clean up frame to delete all OpenGL objects.
225        viewer.cleanup_frame();
226
227        // wait for all the clean up frame to complete.
228        viewer.sync();
229    }
230    else
231    {
232        osg::notify(osg::NOTICE)<<arguments.getApplicationUsage()->getCommandLineUsage()<<std::endl;
233        return 0;
234    }
235   
236   
237   
238    return 0;
239}
Note: See TracBrowser for help on using the browser.