root/OpenSceneGraph/trunk/examples/osgtexture3D/osgtexture3D.cpp @ 13612

Revision 13574, 7.7 kB (checked in by robert, 10 hours ago)

Changed the osgUI behaviour so that events are set to be handled by Widgets that have focus even if they don't directly use them.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgtexture3D.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osg/Node>
20#include <osg/Geometry>
21#include <osg/Notify>
22#include <osg/Texture3D>
23#include <osg/TexGen>
24#include <osg/Geode>
25
26#include <osgDB/Registry>
27#include <osgDB/ReadFile>
28
29#include <osgViewer/Viewer>
30
31#include <iostream>
32
33//
34// A simple demo demonstrating different texturing modes,
35// including using of texture extensions.
36//
37
38
39typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
40
41osg::StateSet* createState()
42{
43    // read 4 2d images
44    osg::ref_ptr<osg::Image> image_0 = osgDB::readImageFile("Images/lz.rgb");
45    osg::ref_ptr<osg::Image> image_1 = osgDB::readImageFile("Images/reflect.rgb");
46    osg::ref_ptr<osg::Image> image_2 = osgDB::readImageFile("Images/tank.rgb");
47    osg::ref_ptr<osg::Image> image_3 = osgDB::readImageFile("Images/skymap.jpg");
48
49    if (!image_0 || !image_1 || !image_2 || !image_3)
50    {
51        std::cout << "Warning: could not open files."<<std::endl;
52        return new osg::StateSet;
53    }
54
55    if (image_0->getPixelFormat()!=image_1->getPixelFormat() || image_0->getPixelFormat()!=image_2->getPixelFormat() || image_0->getPixelFormat()!=image_3->getPixelFormat())
56    {
57        std::cout << "Warning: image pixel formats not compatible."<<std::endl;
58        return new osg::StateSet;
59    }
60
61    GLint textureSize = 256;
62
63    // scale them all to the same size.
64    image_0->scaleImage(textureSize,textureSize,1);
65    image_1->scaleImage(textureSize,textureSize,1);
66    image_2->scaleImage(textureSize,textureSize,1);
67    image_3->scaleImage(textureSize,textureSize,1);
68
69
70    // then allocated a 3d image to use for texturing.
71    osg::Image* image_3d = new osg::Image;
72    image_3d->allocateImage(textureSize,textureSize,4,
73                            image_0->getPixelFormat(),image_0->getDataType());
74
75    // copy the 2d images into the 3d image.
76    image_3d->copySubImage(0,0,0,image_0.get());
77    image_3d->copySubImage(0,0,1,image_1.get());
78    image_3d->copySubImage(0,0,2,image_2.get());
79    image_3d->copySubImage(0,0,3,image_3.get());
80
81    image_3d->setInternalTextureFormat(image_0->getInternalTextureFormat());
82
83    // set up the 3d texture itself,
84    // note, well set the filtering up so that mip mapping is disabled,
85    // gluBuild3DMipsmaps doesn't do a very good job of handled the
86    // inbalanced dimensions of the 256x256x4 texture.
87    osg::Texture3D* texture3D = new osg::Texture3D;
88    texture3D->setFilter(osg::Texture3D::MIN_FILTER,osg::Texture3D::LINEAR);
89    texture3D->setFilter(osg::Texture3D::MAG_FILTER,osg::Texture3D::LINEAR);
90    texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::REPEAT);
91    texture3D->setImage(image_3d);
92
93
94    // create a texgen to generate a R texture coordinate, the geometry
95    // itself will supply the S & T texture coordinates.
96    // in the animateStateSet callback well alter this R value to
97    // move the texture through the 3d texture, 3d texture filtering
98    // will do the blending for us.
99    osg::TexGen* texgen = new osg::TexGen;
100    texgen->setMode(osg::TexGen::OBJECT_LINEAR);
101    texgen->setPlane(osg::TexGen::R, osg::Plane(0.0f,0.0f,0.0f,0.2f));
102
103    // create the StateSet to store the texture data
104    osg::StateSet* stateset = new osg::StateSet;
105    stateset->setTextureMode(0,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
106    stateset->setTextureAttribute(0,texgen);
107    stateset->setTextureAttributeAndModes(0,texture3D,osg::StateAttribute::ON);
108
109    return stateset;
110}
111
112
113class UpdateStateCallback : public osg::NodeCallback
114{
115    public:
116        UpdateStateCallback() {}
117
118        void animateState(osg::StateSet* stateset)
119        {
120            // here we simply get any existing texgen, and then increment its
121            // plane, pushing the R coordinate through the texture.
122            osg::StateAttribute* attribute = stateset->getTextureAttribute(0,osg::StateAttribute::TEXGEN);
123            osg::TexGen* texgen = dynamic_cast<osg::TexGen*>(attribute);
124            if (texgen)
125            {
126                texgen->getPlane(osg::TexGen::R)[3] += 0.001f;
127            }
128
129        }
130
131        virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
132        {
133
134            osg::StateSet* stateset = node->getStateSet();
135            if (stateset)
136            {
137                // we have an exisitng stateset, so lets animate it.
138                animateState(stateset);
139            }
140
141            // note, callback is repsonsible for scenegraph traversal so
142            // should always include call the traverse(node,nv) to ensure
143            // that the rest of cullbacks and the scene graph are traversed.
144            traverse(node,nv);
145        }
146};
147
148/** create 2,2 square with center at 0,0,0 and aligned along the XZ plan */
149osg::Drawable* createSquare(float textureCoordMax=1.0f)
150{
151    // set up the Geometry.
152    osg::Geometry* geom = new osg::Geometry;
153
154    osg::Vec3Array* coords = new osg::Vec3Array(4);
155    (*coords)[0].set(-1.0f,0.0f,1.0f);
156    (*coords)[1].set(-1.0f,0.0f,-1.0f);
157    (*coords)[2].set(1.0f,0.0f,-1.0f);
158    (*coords)[3].set(1.0f,0.0f,1.0f);
159    geom->setVertexArray(coords);
160
161    osg::Vec3Array* norms = new osg::Vec3Array(1);
162    (*norms)[0].set(0.0f,-1.0f,0.0f);
163    geom->setNormalArray(norms, osg::Array::BIND_OVERALL);
164
165    osg::Vec2Array* tcoords = new osg::Vec2Array(4);
166    (*tcoords)[0].set(0.0f,textureCoordMax);
167    (*tcoords)[1].set(0.0f,0.0f);
168    (*tcoords)[2].set(textureCoordMax,0.0f);
169    (*tcoords)[3].set(textureCoordMax,textureCoordMax);
170    geom->setTexCoordArray(0,tcoords);
171
172    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
173
174    return geom;
175}
176
177osg::Node* createModel()
178{
179
180    // create the geometry of the model, just a simple 2d quad right now.
181    osg::Geode* geode = new osg::Geode;
182    geode->addDrawable(createSquare());
183
184    // normally we'd create the stateset's to contain all the textures
185    // etc here, but, the above technique uses osg::Image::scaleImage and
186    // osg::Image::copySubImage() which are implemented with OpenGL utility
187    // library, which unfortunately can't be used until we have a valid
188    // OpenGL context, and at this point in initilialization we don't have
189    // a valid OpenGL context, so we have to delay creation of state until
190    // there is a valid OpenGL context.  I'll manage this by using an
191    // app callback which will create the state during the first traversal.
192    // A bit hacky, and my plan is to reimplement the osg::scaleImage and
193    // osg::Image::copySubImage() without using GLU which will get round
194    // this current limitation.
195    geode->setUpdateCallback(new UpdateStateCallback());
196    geode->setStateSet(createState());
197
198    return geode;
199
200}
201
202
203int main(int , char **)
204{
205    // construct the viewer.
206    osgViewer::Viewer viewer;
207
208    // create a model from the images and pass it to the viewer.
209    viewer.setSceneData(createModel());
210
211    return viewer.run();
212}
Note: See TracBrowser for help on using the browser.