root/OpenSceneGraph/trunk/examples/osgtexturerectangle/osgtexturerectangle.cpp @ 5522

Revision 5522, 9.0 kB (checked in by robert, 8 years ago)

Added osg::TexMat::s/getScaleByTextureRectangleSize feature that allows
one to use the osg::TexMat? to automatically scale non dimensional tex coordinats to
the size of the last texture rectangle applied.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// -*-c++-*-
2
3/*
4 * demonstrates usage of osg::TextureRectangle.
5 *
6 * Actually there isn't much difference to the rest of the osg::Texture*
7 * bunch only this:
8 * - texture coordinates for texture rectangles must be in image
9 *   coordinates instead of normalized coordinates (0-1). So for a 500x250
10 *   image the coordinates for the entire image would be
11 *   0,250 0,0 500,0 500,250 instead of 0,1 0,0 1,0 1,1
12 * - only the following wrap modes are supported (but not enforced)
13 *   CLAMP, CLAMP_TO_EDGE, CLAMP_TO_BORDER
14 * - a border is not supported
15 * - mipmap is not supported
16 */
17
18#include <osg/Notify>
19#include <osg/TextureRectangle>
20#include <osg/Geometry>
21#include <osg/Geode>
22#include <osg/TexMat>
23
24#include <osg/Group>
25#include <osg/Projection>
26#include <osg/MatrixTransform>
27#include <osgText/Text>
28
29#include <osgDB/Registry>
30#include <osgDB/ReadFile>
31
32#include <osgProducer/Viewer>
33
34
35/**********************************************************************
36 *
37 * Texture pan animation callback
38 *
39 **********************************************************************/
40
41class TexturePanCallback : public osg::NodeCallback
42{
43public:
44    TexturePanCallback(osg::TexMat* texmat,
45                       double delay = 0.05) :
46        _texmat(texmat),
47        _phaseS(35.0f),
48        _phaseT(18.0f),
49        _phaseScale(5.0f),
50        _delay(delay),
51        _prevTime(0.0)
52    {
53    }
54
55    virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
56    {
57        if (!_texmat)
58            return;
59
60        if (nv->getFrameStamp()) {
61            double currTime = nv->getFrameStamp()->getReferenceTime();
62            if (currTime - _prevTime > _delay) {
63
64                float rad = osg::DegreesToRadians(currTime);
65
66                // zoom scale (0.2 - 1.0)
67                float scale = sin(rad * _phaseScale) * 0.4f + 0.6f;
68                float scaleR = 1.0f - scale;
69
70                // calculate new texture coordinates
71                float s, t;
72                s = ((sin(rad * _phaseS) + 1) * 0.5f) * (scaleR);
73                t = ((sin(rad * _phaseT) + 1) * 0.5f) * (scaleR);
74
75
76                _texmat->setMatrix(osg::Matrix::translate(s,t,1.0)*osg::Matrix::scale(scale,scale,1.0));
77
78                // record time
79                _prevTime = currTime;
80            }
81        }
82    }
83
84private:
85    osg::TexMat* _texmat;
86
87    float _phaseS, _phaseT, _phaseScale;
88
89    double _delay;
90    double _prevTime;
91};
92
93
94osg::Node* createRectangle(osg::BoundingBox& bb,
95                           const std::string& filename)
96{
97    osg::Vec3 top_left(bb.xMin(),bb.yMax(),bb.zMax());
98    osg::Vec3 bottom_left(bb.xMin(),bb.yMax(),bb.zMin());
99    osg::Vec3 bottom_right(bb.xMax(),bb.yMax(),bb.zMin());
100    osg::Vec3 top_right(bb.xMax(),bb.yMax(),bb.zMax());
101   
102    // create geometry
103    osg::Geometry* geom = new osg::Geometry;
104
105    osg::Vec3Array* vertices = new osg::Vec3Array(4);
106    (*vertices)[0] = top_left;
107    (*vertices)[1] = bottom_left;
108    (*vertices)[2] = bottom_right;
109    (*vertices)[3] = top_right;
110    geom->setVertexArray(vertices);
111   
112    osg::Vec2Array* texcoords = new osg::Vec2Array(4);
113    (*texcoords)[0].set(0.0f, 0.0f);
114    (*texcoords)[1].set(1.0f, 0.0f);
115    (*texcoords)[2].set(1.0f, 1.0f);
116    (*texcoords)[3].set(0.0f, 1.0f);
117    geom->setTexCoordArray(0,texcoords);
118
119    osg::Vec3Array* normals = new osg::Vec3Array(1);
120    (*normals)[0].set(0.0f,-1.0f,0.0f);
121    geom->setNormalArray(normals);
122    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
123
124    osg::Vec4Array* colors = new osg::Vec4Array(1);
125    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
126    geom->setColorArray(colors);
127    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
128
129    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));
130
131    // disable display list so our modified tex coordinates show up
132    geom->setUseDisplayList(false);
133
134    // setup texture
135    osg::TextureRectangle* texture = new osg::TextureRectangle;
136
137    // load image
138    osg::Image* img = osgDB::readImageFile(filename);
139    texture->setImage(img);
140
141    // setup state
142    osg::StateSet* state = geom->getOrCreateStateSet();
143    state->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
144
145    // setup state
146    osg::TexMat* texmat = new osg::TexMat;
147    texmat->setScaleByTextureRectangleSize(true);
148    state->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON);
149
150    // turn off lighting
151    state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
152
153    // install 'update' callback
154    osg::Geode* geode = new osg::Geode;
155    geode->addDrawable(geom);
156    geode->setUpdateCallback(new TexturePanCallback(texmat));
157   
158    return geode;
159}
160
161
162osg::Geode* createText(const std::string& str,
163                       const osg::Vec3& pos)
164{
165    static std::string font("fonts/arial.ttf");
166
167    osg::Geode* geode = new osg::Geode;
168
169    osgText::Text* text = new osgText::Text;
170    geode->addDrawable(text);
171
172    text->setFont(font);
173    text->setPosition(pos);
174    text->setText(str);
175
176    return geode;
177}
178
179
180osg::Node* createHUD()
181{
182    osg::Group* group = new osg::Group;
183
184    // turn off lighting and depth test
185    osg::StateSet* state = group->getOrCreateStateSet();
186    state->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
187    state->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
188
189    // add text
190    osg::Vec3 pos(120.0f, 800.0f, 0.0f);
191    const osg::Vec3 delta(0.0f, -80.0f, 0.0f);
192
193    const char* text[] = {
194        "TextureRectangle Mini-HOWTO",
195        "- essentially behaves like Texture2D, *except* that:",
196        "- tex coords must be non-normalized (0..pixel) instead of (0..1),\nalternatively you can use osg::TexMat to scale normal non dimensional texcoords.",
197        "- wrap modes must be CLAMP, CLAMP_TO_EDGE, or CLAMP_TO_BORDER\n  repeating wrap modes are not supported",
198        "- filter modes must be NEAREST or LINEAR since\n  mipmaps are not supported",
199        "- texture borders are not supported",
200        "- defaults should be fine",
201        NULL
202    };
203    const char** t = text;
204    while (*t) {
205        group->addChild(createText(*t++, pos));
206        pos += delta;
207    }
208
209    // create HUD
210    osg::MatrixTransform* modelview_abs = new osg::MatrixTransform;
211    modelview_abs->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
212    modelview_abs->setMatrix(osg::Matrix::identity());
213    modelview_abs->addChild(group);
214
215    osg::Projection* projection = new osg::Projection;
216    projection->setMatrix(osg::Matrix::ortho2D(0,1280,0,1024));
217    projection->addChild(modelview_abs);
218
219    return projection;
220}
221
222
223osg::Node* createModel(const std::string& filename)
224{
225    osg::Group* root = new osg::Group;
226
227    if (filename != "X") {
228        osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
229        root->addChild(createRectangle(bb, filename)); // XXX
230    }
231
232    root->addChild(createHUD());
233
234    return root;
235}
236
237
238int main(int argc, char** argv)
239{
240    // use an ArgumentParser object to manage the program arguments.
241    osg::ArgumentParser arguments(&argc,argv);
242
243    // set up the usage document, in case we need to print out how to use this program.
244    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is a demo which demonstrates use of osg::TextureRectangle.");
245    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] <image> ...");
246    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
247   
248    // construct the viewer.
249    osgProducer::Viewer viewer(arguments);
250
251    // set up the value with sensible default event handlers.
252    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
253
254    // get details on keyboard and mouse bindings used by the viewer.
255    viewer.getUsage(*arguments.getApplicationUsage());
256
257    // if user request help write it out to cout.
258    if (arguments.read("-h") || arguments.read("--help"))
259    {
260        arguments.getApplicationUsage()->write(std::cout);
261        return 1;
262    }
263
264    // any option left unread are converted into errors to write out later.
265    arguments.reportRemainingOptionsAsUnrecognized();
266
267    // report any errors if they have occured when parsing the program aguments.
268    if (arguments.errors())
269    {
270        arguments.writeErrorMessages(std::cout);
271        return 1;
272    }
273
274    // create a model from the images.
275    osg::Node* rootNode = createModel((arguments.argc() > 1 ? arguments[1] : "Images/lz.rgb"));
276
277    // add model to viewer.
278    viewer.setSceneData(rootNode);
279
280    // create the windows and run the threads.
281    viewer.realize();
282
283    while (!viewer.done())
284    {
285        // wait for all cull and draw threads to complete.
286        viewer.sync();
287
288        // update the scene by traversing it with the the update visitor which will
289        // call all node update callbacks and animations.
290        viewer.update();
291
292        // fire off the cull and draw traversals of the scene.
293        viewer.frame();
294    }
295
296    // wait for all cull and draw threads to complete.
297    viewer.sync();
298
299    // run a clean up frame to delete all OpenGL objects.
300    viewer.cleanup_frame();
301
302    // wait for all the clean up frame to complete.
303    viewer.sync();
304   
305    return 0;
306}
Note: See TracBrowser for help on using the browser.