root/OpenSceneGraph/trunk/examples/osgtexture2D/osgtexture2D.cpp @ 12912

Revision 12912, 26.1 kB (checked in by robert, 3 years ago)

Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength?
parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which
defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided.

With the introduction of RowLength? support in osg::Image it is now possible to create a sub image where
the t size of the image are smaller than the row length, useful for when you have a large image on the CPU
and which to use a small portion of it on the GPU. However, when these sub images are created the data
within the image is no longer contiguous so data access can no longer assume that all the data is in
one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous,
and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the
new Image::DataIterator? for stepping through each block on memory assocatied with the image.

To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to
check DataContiguous? and handle the case or use access via the DataIerator? or by row by row. To achieve
this a relatively large number of files has had to be modified, in particular the texture classes and
image plugins that doing writing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgtexture2D.
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/MatrixTransform>
23#include <osg/Texture2D>
24#include <osg/DrawPixels>
25#include <osg/PolygonOffset>
26#include <osg/Geode>
27
28#include <osgDB/Registry>
29#include <osgDB/ReadFile>
30
31#include <osgText/Text>
32
33#include <osgViewer/Viewer>
34
35///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36//
37// filter wall and animation callback.
38//
39
40class FilterCallback : public osg::NodeCallback
41{
42public:
43
44    FilterCallback(osg::Texture2D* texture,osgText::Text* text,double delay=1.0):
45        _texture(texture),
46        _text(text),
47        _delay(delay),
48        _currPos(0),
49        _prevTime(0.0)
50    {
51        // start with a mip mapped mode to ensure that
52        _minFilterList.push_back(osg::Texture2D::LINEAR_MIPMAP_LINEAR);
53        _magFilterList.push_back(osg::Texture2D::LINEAR);
54        _textList.push_back("Tri-linear mip mapping (default filtering)\nsetFilter(MIN_FILTER,LINEAR_MIP_LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");
55
56        _minFilterList.push_back(osg::Texture2D::NEAREST);
57        _magFilterList.push_back(osg::Texture2D::NEAREST);
58        _textList.push_back("Nearest filtering\nsetFilter(MIN_FILTER,NEAREST)\nsetFilter(MAG_FILTER,NEAREST)");
59       
60        _minFilterList.push_back(osg::Texture2D::LINEAR);
61        _magFilterList.push_back(osg::Texture2D::LINEAR);
62        _textList.push_back("Linear filtering\nsetFilter(MIN_FILTER,LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");
63       
64        _minFilterList.push_back(osg::Texture2D::NEAREST_MIPMAP_NEAREST);
65        _magFilterList.push_back(osg::Texture2D::LINEAR);
66        _textList.push_back("nearest mip mapping (default filtering)\nsetFilter(MIN_FILTER,)\nsetFilter(MAG_FILTER,LINEAR)");
67
68        _minFilterList.push_back(osg::Texture2D::LINEAR_MIPMAP_NEAREST);
69        _magFilterList.push_back(osg::Texture2D::LINEAR);
70        _textList.push_back("bi-linear mip mapping\nsetFilter(MIN_FILTER,LINEAR_MIPMAP_NEAREST)\nsetFilter(MAG_FILTER,LINEAR)");
71
72        _minFilterList.push_back(osg::Texture2D::NEAREST_MIPMAP_LINEAR);
73        _magFilterList.push_back(osg::Texture2D::LINEAR);
74        _textList.push_back("bi-linear mip mapping\nsetFilter(MIN_FILTER,NEAREST_MIPMAP_LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");
75
76       
77        setValues();
78    }
79
80    virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
81    {
82        if (nv->getFrameStamp())
83        {
84            double currTime = nv->getFrameStamp()->getSimulationTime();
85            if (currTime-_prevTime>_delay)
86            {
87                // update filter modes and text.
88                setValues();
89               
90                // advance the current positon, wrap round if required.
91                _currPos++;
92                if (_currPos>=_minFilterList.size()) _currPos=0;                   
93               
94                // record time
95                _prevTime = currTime;
96            }
97        }
98    }
99   
100    void setValues()
101    {
102        _texture->setFilter(osg::Texture2D::MIN_FILTER,_minFilterList[_currPos]);
103        _texture->setFilter(osg::Texture2D::MAG_FILTER,_magFilterList[_currPos]);
104
105        _text->setText(_textList[_currPos]);
106    }
107
108protected:
109
110    typedef std::vector<osg::Texture2D::FilterMode> FilterList;
111    typedef std::vector<std::string>                TextList;
112
113    osg::ref_ptr<osg::Texture2D>    _texture;
114    osg::ref_ptr<osgText::Text>     _text;
115    double                          _delay;
116   
117    FilterList                      _minFilterList;
118    FilterList                      _magFilterList;
119    TextList                        _textList;
120   
121    unsigned int                    _currPos;
122    double                          _prevTime;
123   
124};
125
126osg::Node* createFilterWall(osg::BoundingBox& bb,const std::string& filename)
127{
128    osg::Group* group = new osg::Group;
129   
130    // left hand side of bounding box.
131    osg::Vec3 top_left(bb.xMin(),bb.yMin(),bb.zMax());
132    osg::Vec3 bottom_left(bb.xMin(),bb.yMin(),bb.zMin());
133    osg::Vec3 bottom_right(bb.xMin(),bb.yMax(),bb.zMin());
134    osg::Vec3 top_right(bb.xMin(),bb.yMax(),bb.zMax());
135    osg::Vec3 center(bb.xMin(),(bb.yMin()+bb.yMax())*0.5f,(bb.zMin()+bb.zMax())*0.5f);   
136    float height = bb.zMax()-bb.zMin();
137   
138    // create the geometry for the wall.
139    osg::Geometry* geom = new osg::Geometry;
140   
141    osg::Vec3Array* vertices = new osg::Vec3Array(4);
142    (*vertices)[0] = top_left;
143    (*vertices)[1] = bottom_left;
144    (*vertices)[2] = bottom_right;
145    (*vertices)[3] = top_right;
146    geom->setVertexArray(vertices);
147   
148    osg::Vec2Array* texcoords = new osg::Vec2Array(4);
149    (*texcoords)[0].set(0.0f,1.0f);
150    (*texcoords)[1].set(0.0f,0.0f);
151    (*texcoords)[2].set(1.0f,0.0f);
152    (*texcoords)[3].set(1.0f,1.0f);
153    geom->setTexCoordArray(0,texcoords);
154
155    osg::Vec3Array* normals = new osg::Vec3Array(1);
156    (*normals)[0].set(1.0f,0.0f,0.0f);
157    geom->setNormalArray(normals);
158    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
159   
160    osg::Vec4Array* colors = new osg::Vec4Array(1);
161    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
162    geom->setColorArray(colors);
163    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
164
165    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));
166   
167    osg::Geode* geom_geode = new osg::Geode;
168    geom_geode->addDrawable(geom);
169    group->addChild(geom_geode);
170   
171   
172    // set up the texture state.   
173    osg::Texture2D* texture = new osg::Texture2D;
174    texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
175    texture->setImage(osgDB::readImageFile(filename));
176   
177    osg::StateSet* stateset = geom->getOrCreateStateSet();
178    stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
179   
180    // create the text label.
181   
182    osgText::Text* text = new osgText::Text;
183    text->setFont("fonts/arial.ttf");
184    text->setPosition(center);
185    text->setCharacterSize(height*0.03f);
186    text->setAlignment(osgText::Text::CENTER_CENTER);
187    text->setAxisAlignment(osgText::Text::YZ_PLANE);
188   
189    osg::Geode* text_geode = new osg::Geode;
190    text_geode->addDrawable(text);
191   
192    osg::StateSet* text_stateset = text_geode->getOrCreateStateSet();
193    text_stateset->setAttributeAndModes(new osg::PolygonOffset(-1.0f,-1.0f),osg::StateAttribute::ON);
194   
195    group->addChild(text_geode);
196
197    // set the update callback to cycle through the various min and mag filter modes.
198    group->setUpdateCallback(new FilterCallback(texture,text));
199   
200    return group;
201   
202}
203
204///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
205//
206// anisotropic wall and animation callback.
207//
208
209class AnisotropicCallback : public osg::NodeCallback
210{
211public:
212
213    AnisotropicCallback(osg::Texture2D* texture,osgText::Text* text,double delay=1.0):
214        _texture(texture),
215        _text(text),
216        _delay(delay),
217        _currPos(0),
218        _prevTime(0.0)
219    {
220
221        _maxAnisotropyList.push_back(1.0f);
222        _textList.push_back("No anisotropic filtering (default)\nsetMaxAnisotropy(1.0f)");
223       
224        _maxAnisotropyList.push_back(2.0f);
225        _textList.push_back("Anisotropic filtering\nsetMaxAnisotropy(2.0f)");
226       
227        _maxAnisotropyList.push_back(4.0f);
228        _textList.push_back("Anisotropic filtering\nsetMaxAnisotropy(4.0f)");
229       
230        _maxAnisotropyList.push_back(8.0f);
231        _textList.push_back("Anisotropic filtering\nsetMaxAnisotropy(8.0f)");
232       
233        _maxAnisotropyList.push_back(16.0f);
234        _textList.push_back("Higest quality anisotropic filtering\nsetMaxAnisotropy(16.0f)");
235
236        setValues();
237    }
238
239    virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
240    {
241        if (nv->getFrameStamp())
242        {
243            double currTime = nv->getFrameStamp()->getSimulationTime();
244            if (currTime-_prevTime>_delay)
245            {
246                // update filter modes and text.
247                setValues();
248               
249                // advance the current positon, wrap round if required.
250                _currPos++;
251                if (_currPos>=_maxAnisotropyList.size()) _currPos=0;                   
252               
253                // record time
254                _prevTime = currTime;
255            }
256        }
257    }
258   
259    void setValues()
260    {
261        _texture->setMaxAnisotropy(_maxAnisotropyList[_currPos]);
262
263        _text->setText(_textList[_currPos]);
264    }
265
266protected:
267
268    typedef std::vector<float>          AnisotropyList;
269    typedef std::vector<std::string>    TextList;
270
271    osg::ref_ptr<osg::Texture2D>    _texture;
272    osg::ref_ptr<osgText::Text>     _text;
273    double                          _delay;
274   
275    AnisotropyList                  _maxAnisotropyList;
276    TextList                        _textList;
277   
278    unsigned int                    _currPos;
279    double                          _prevTime;
280   
281};
282
283osg::Node* createAnisotripicWall(osg::BoundingBox& bb,const std::string& filename)
284{
285    osg::Group* group = new osg::Group;
286   
287    // left hand side of bounding box.
288    osg::Vec3 top_left(bb.xMin(),bb.yMax(),bb.zMin());
289    osg::Vec3 bottom_left(bb.xMin(),bb.yMin(),bb.zMin());
290    osg::Vec3 bottom_right(bb.xMax(),bb.yMin(),bb.zMin());
291    osg::Vec3 top_right(bb.xMax(),bb.yMax(),bb.zMin());
292    osg::Vec3 center((bb.xMin()+bb.xMax())*0.5f,(bb.yMin()+bb.yMax())*0.5f,bb.zMin());   
293    float height = bb.yMax()-bb.yMin();
294   
295    // create the geometry for the wall.
296    osg::Geometry* geom = new osg::Geometry;
297   
298    osg::Vec3Array* vertices = new osg::Vec3Array(4);
299    (*vertices)[0] = top_left;
300    (*vertices)[1] = bottom_left;
301    (*vertices)[2] = bottom_right;
302    (*vertices)[3] = top_right;
303    geom->setVertexArray(vertices);
304   
305    osg::Vec2Array* texcoords = new osg::Vec2Array(4);
306    (*texcoords)[0].set(0.0f,1.0f);
307    (*texcoords)[1].set(0.0f,0.0f);
308    (*texcoords)[2].set(1.0f,0.0f);
309    (*texcoords)[3].set(1.0f,1.0f);
310    geom->setTexCoordArray(0,texcoords);
311
312    osg::Vec3Array* normals = new osg::Vec3Array(1);
313    (*normals)[0].set(0.0f,0.0f,1.0f);
314    geom->setNormalArray(normals);
315    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
316   
317    osg::Vec4Array* colors = new osg::Vec4Array(1);
318    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
319    geom->setColorArray(colors);
320    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
321
322    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));
323   
324    osg::Geode* geom_geode = new osg::Geode;
325    geom_geode->addDrawable(geom);
326    group->addChild(geom_geode);
327   
328   
329    // set up the texture state.   
330    osg::Texture2D* texture = new osg::Texture2D;
331    texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
332    texture->setImage(osgDB::readImageFile(filename));
333   
334    osg::StateSet* stateset = geom->getOrCreateStateSet();
335    stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
336   
337    // create the text label.
338   
339    osgText::Text* text = new osgText::Text;
340    text->setFont("fonts/arial.ttf");
341    text->setPosition(center);
342    text->setCharacterSize(height*0.03f);
343    text->setColor(osg::Vec4(1.0f,0.0f,1.0f,1.0f));
344    text->setAlignment(osgText::Text::CENTER_CENTER);
345    text->setAxisAlignment(osgText::Text::XY_PLANE);
346   
347    osg::Geode* text_geode = new osg::Geode;
348    text_geode->addDrawable(text);
349   
350    osg::StateSet* text_stateset = text_geode->getOrCreateStateSet();
351    text_stateset->setAttributeAndModes(new osg::PolygonOffset(-1.0f,-1.0f),osg::StateAttribute::ON);
352   
353    group->addChild(text_geode);
354
355    // set the update callback to cycle through the various min and mag filter modes.
356    group->setUpdateCallback(new AnisotropicCallback(texture,text));
357   
358    return group;
359   
360}
361
362///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
363//
364// wrap wall and animation callback.
365//
366class WrapCallback : public osg::NodeCallback
367{
368public:
369
370    WrapCallback(osg::Texture2D* texture,osgText::Text* text,double delay=1.0):
371        _texture(texture),
372        _text(text),
373        _delay(delay),
374        _currPos(0),
375        _prevTime(0.0)
376    {
377
378        _wrapList.push_back(osg::Texture2D::CLAMP);
379        _textList.push_back("Default tex coord clamp\nsetWrap(WRAP_S,CLAMP)");
380       
381        _wrapList.push_back(osg::Texture2D::CLAMP_TO_EDGE);
382        _textList.push_back("Clamp to edge extension\nsetWrap(WRAP_S,CLAMP_TO_EDGE)");
383       
384        _wrapList.push_back(osg::Texture2D::CLAMP_TO_BORDER);
385        _textList.push_back("Clamp to border color extension\nsetWrap(WRAP_S,CLAMP_TO_BORDER)");
386       
387        _wrapList.push_back(osg::Texture2D::REPEAT);
388        _textList.push_back("Repeat wrap\nsetWrap(WRAP_S,REPEAT)");
389       
390        _wrapList.push_back(osg::Texture2D::MIRROR);
391        _textList.push_back("Mirror wrap extension\nsetWrap(WRAP_S,MIRROR)");
392
393        setValues();
394    }
395
396    virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
397    {
398        if (nv->getFrameStamp())
399        {
400            double currTime = nv->getFrameStamp()->getSimulationTime();
401            if (currTime-_prevTime>_delay)
402            {
403                // update filter modes and text.
404                setValues();
405               
406                // advance the current positon, wrap round if required.
407                _currPos++;
408                if (_currPos>=_wrapList.size()) _currPos=0;                   
409               
410                // record time
411                _prevTime = currTime;
412            }
413        }
414    }
415   
416    void setValues()
417    {
418        _texture->setWrap(osg::Texture2D::WRAP_S,_wrapList[_currPos]);
419        _texture->setWrap(osg::Texture2D::WRAP_T,_wrapList[_currPos]);
420
421        _text->setText(_textList[_currPos]);
422    }
423
424protected:
425
426    typedef std::vector<osg::Texture2D::WrapMode> WrapList;
427    typedef std::vector<std::string>              TextList;
428
429    osg::ref_ptr<osg::Texture2D>    _texture;
430    osg::ref_ptr<osgText::Text>     _text;
431    double                          _delay;
432   
433    WrapList                        _wrapList;
434    TextList                        _textList;
435   
436    unsigned int                    _currPos;
437    double                          _prevTime;
438   
439};
440
441osg::Node* createWrapWall(osg::BoundingBox& bb,const std::string& filename)
442{
443    osg::Group* group = new osg::Group;
444   
445    // left hand side of bounding box.
446    osg::Vec3 top_left(bb.xMax(),bb.yMax(),bb.zMax());
447    osg::Vec3 bottom_left(bb.xMax(),bb.yMax(),bb.zMin());
448    osg::Vec3 bottom_right(bb.xMax(),bb.yMin(),bb.zMin());
449    osg::Vec3 top_right(bb.xMax(),bb.yMin(),bb.zMax());
450    osg::Vec3 center(bb.xMax(),(bb.yMin()+bb.yMax())*0.5f,(bb.zMin()+bb.zMax())*0.5f);   
451    float height = bb.zMax()-bb.zMin();
452   
453    // create the geometry for the wall.
454    osg::Geometry* geom = new osg::Geometry;
455   
456    osg::Vec3Array* vertices = new osg::Vec3Array(4);
457    (*vertices)[0] = top_left;
458    (*vertices)[1] = bottom_left;
459    (*vertices)[2] = bottom_right;
460    (*vertices)[3] = top_right;
461    geom->setVertexArray(vertices);
462   
463    osg::Vec2Array* texcoords = new osg::Vec2Array(4);
464    (*texcoords)[0].set(-1.0f,2.0f);
465    (*texcoords)[1].set(-1.0f,-1.0f);
466    (*texcoords)[2].set(2.0f,-1.0f);
467    (*texcoords)[3].set(2.0f,2.0f);
468    geom->setTexCoordArray(0,texcoords);
469
470    osg::Vec3Array* normals = new osg::Vec3Array(1);
471    (*normals)[0].set(-1.0f,0.0f,0.0f);
472    geom->setNormalArray(normals);
473    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
474   
475    osg::Vec4Array* colors = new osg::Vec4Array(1);
476    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
477    geom->setColorArray(colors);
478    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
479
480    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));
481   
482    osg::Geode* geom_geode = new osg::Geode;
483    geom_geode->addDrawable(geom);
484    group->addChild(geom_geode);
485   
486   
487    // set up the texture state.   
488    osg::Texture2D* texture = new osg::Texture2D;
489    texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
490    texture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,0.5f)); // only used when wrap is set to CLAMP_TO_BORDER
491    texture->setImage(osgDB::readImageFile(filename));
492   
493    osg::StateSet* stateset = geom->getOrCreateStateSet();
494    stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
495    stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
496    stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
497   
498    // create the text label.
499   
500    osgText::Text* text = new osgText::Text;
501    text->setFont("fonts/arial.ttf");
502    text->setPosition(center);
503    text->setCharacterSize(height*0.03f);
504    text->setAlignment(osgText::Text::CENTER_CENTER);
505    text->setAxisAlignment(osgText::Text::YZ_PLANE);
506   
507    osg::Geode* text_geode = new osg::Geode;
508    text_geode->addDrawable(text);
509   
510    osg::StateSet* text_stateset = text_geode->getOrCreateStateSet();
511    text_stateset->setAttributeAndModes(new osg::PolygonOffset(-1.0f,-1.0f),osg::StateAttribute::ON);
512   
513    group->addChild(text_geode);
514
515    // set the update callback to cycle through the various min and mag filter modes.
516    group->setUpdateCallback(new WrapCallback(texture,text));
517   
518    return group;
519   
520}
521
522///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
523//
524// sublooad wall and animation callback.
525//
526
527class ImageUpdateCallback : public osg::NodeCallback
528{
529public:
530
531    ImageUpdateCallback(osg::Texture2D* texture,osgText::Text* text,double delay=1.0):
532        _texture(texture),
533        _text(text),
534        _delay(delay),
535        _currPos(0),
536        _prevTime(0.0)
537    {
538
539#if 1       
540        osg::ref_ptr<osg::Image> originalImage = osgDB::readImageFile("Images/dog_left_eye.jpg");
541
542        osg::ref_ptr<osg::Image> subImage = new osg::Image;
543        subImage->setUserData(originalImage.get()); // attach the originalImage as user data to prevent it being deleted.
544
545        // now assign the appropriate portion data from the originalImage
546        subImage->setImage(originalImage->s()/2, originalImage->t()/2, originalImage->r(), // half the width and height
547                           originalImage->getInternalTextureFormat(), // same internal texture format
548                           originalImage->getPixelFormat(),originalImage->getDataType(), // same pixel foramt and data type
549                           originalImage->data(originalImage->s()/4,originalImage->t()/4), // offset teh start point to 1/4 into the image
550                           osg::Image::NO_DELETE, // don't attempt to delete the image data, leave this to the originalImage
551                           originalImage->getPacking(), // use the the same packing
552                           originalImage->s()); // use the width of the original image as the row width
553
554
555        subImage->setPixelBufferObject(new osg::PixelBufferObject(subImage.get()));
556
557#if 0
558        OSG_NOTICE<<"orignalImage iterator"<<std::endl;
559        for(osg::Image::DataIterator itr(originalImage.get()); itr.valid(); ++itr)
560        {
561            OSG_NOTICE<<"  "<<(void*)itr.data()<<", "<<itr.size()<<std::endl;
562        }
563
564        OSG_NOTICE<<"subImage iterator, size "<<subImage->s()<<", "<<subImage->t()<<std::endl;
565        unsigned int i=0;
566        for(osg::Image::DataIterator itr(subImage.get()); itr.valid(); ++itr, ++i)
567        {
568            OSG_NOTICE<<"  "<<i<<", "<<(void*)itr.data()<<", "<<itr.size()<<std::endl;
569
570            for(unsigned char* d=const_cast<unsigned char*>(itr.data()); d<(itr.data()+itr.size()); ++d)
571            {
572                *d = 255-*d;
573            }
574        }
575#endif   
576
577       
578        _imageList.push_back(subImage.get());
579
580#else
581        _imageList.push_back(osgDB::readImageFile("Images/dog_left_eye.jpg"));
582#endif
583        _textList.push_back("Subloaded Image 1 - dog_left_eye.jpg");
584       
585        _imageList.push_back(osgDB::readImageFile("Images/dog_right_eye.jpg"));
586        _textList.push_back("Subloaded Image 2 - dog_right_eye.jpg");
587       
588        setValues();
589    }
590
591    virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
592    {
593        if (nv->getFrameStamp())
594        {
595            double currTime = nv->getFrameStamp()->getSimulationTime();
596            if (currTime-_prevTime>_delay)
597            {
598                // update filter modes and text.
599                setValues();
600               
601                // advance the current positon, wrap round if required.
602                _currPos++;
603                if (_currPos>=_imageList.size()) _currPos=0;                   
604               
605                // record time
606                _prevTime = currTime;
607            }
608        }
609    }
610   
611    void setValues()
612    {
613        // Note, as long as the images are the same dimensions subloading will be used
614        // to update the textures.  If dimensions change then the texture objects have
615        // to be deleted and re-recreated.
616        //
617        // The load/subload happens during the draw traversal so doesn't happen on
618        // the setImage which just updates internal pointers and modifed flags.
619
620        _texture->setImage(_imageList[_currPos].get());
621       
622        //_texture->dirtyTextureObject();
623
624        _text->setText(_textList[_currPos]);
625    }
626
627protected:
628
629   
630    typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
631    typedef std::vector<std::string>                TextList;
632
633    osg::ref_ptr<osg::Texture2D>    _texture;
634    osg::ref_ptr<osgText::Text>     _text;
635    double                          _delay;
636   
637    ImageList                       _imageList;
638    TextList                        _textList;
639   
640    unsigned int                    _currPos;
641    double                          _prevTime;
642   
643};
644
645osg::Node* createSubloadWall(osg::BoundingBox& bb)
646{
647    osg::Group* group = new osg::Group;
648   
649    // left hand side of bounding box.
650    osg::Vec3 top_left(bb.xMin(),bb.yMax(),bb.zMax());
651    osg::Vec3 bottom_left(bb.xMin(),bb.yMax(),bb.zMin());
652    osg::Vec3 bottom_right(bb.xMax(),bb.yMax(),bb.zMin());
653    osg::Vec3 top_right(bb.xMax(),bb.yMax(),bb.zMax());
654    osg::Vec3 center((bb.xMax()+bb.xMin())*0.5f,bb.yMax(),(bb.zMin()+bb.zMax())*0.5f);   
655    float height = bb.zMax()-bb.zMin();
656   
657    // create the geometry for the wall.
658    osg::Geometry* geom = new osg::Geometry;
659   
660    osg::Vec3Array* vertices = new osg::Vec3Array(4);
661    (*vertices)[0] = top_left;
662    (*vertices)[1] = bottom_left;
663    (*vertices)[2] = bottom_right;
664    (*vertices)[3] = top_right;
665    geom->setVertexArray(vertices);
666   
667    osg::Vec2Array* texcoords = new osg::Vec2Array(4);
668    (*texcoords)[0].set(0.0f,1.0f);
669    (*texcoords)[1].set(0.0f,0.0f);
670    (*texcoords)[2].set(1.0f,0.0f);
671    (*texcoords)[3].set(1.0f,1.0f);
672    geom->setTexCoordArray(0,texcoords);
673
674    osg::Vec3Array* normals = new osg::Vec3Array(1);
675    (*normals)[0].set(0.0f,-1.0f,0.0f);
676    geom->setNormalArray(normals);
677    geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
678   
679    osg::Vec4Array* colors = new osg::Vec4Array(1);
680    (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
681    geom->setColorArray(colors);
682    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
683
684    geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));
685   
686    osg::Geode* geom_geode = new osg::Geode;
687    geom_geode->addDrawable(geom);
688    group->addChild(geom_geode);
689   
690   
691    // set up the texture state.   
692    osg::Texture2D* texture = new osg::Texture2D;
693    texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
694    texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
695    texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
696   
697    osg::StateSet* stateset = geom->getOrCreateStateSet();
698    stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
699   
700    // create the text label.
701   
702    osgText::Text* text = new osgText::Text;
703    text->setDataVariance(osg::Object::DYNAMIC);
704    text->setFont("fonts/arial.ttf");
705    text->setPosition(center);
706    text->setCharacterSize(height*0.03f);
707    text->setAlignment(osgText::Text::CENTER_CENTER);
708    text->setAxisAlignment(osgText::Text::XZ_PLANE);
709   
710    osg::Geode* text_geode = new osg::Geode;
711    text_geode->addDrawable(text);
712   
713    osg::StateSet* text_stateset = text_geode->getOrCreateStateSet();
714    text_stateset->setAttributeAndModes(new osg::PolygonOffset(-1.0f,-1.0f),osg::StateAttribute::ON);
715   
716    group->addChild(text_geode);
717
718    // set the update callback to cycle through the various min and mag filter modes.
719    group->setUpdateCallback(new ImageUpdateCallback(texture,text));
720   
721    return group;
722   
723}
724
725
726osg::Node* createModel()
727{
728
729    // create the root node which will hold the model.
730    osg::Group* root = new osg::Group();
731   
732    // turn off lighting
733    root->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
734
735    osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
736
737    root->addChild(createFilterWall(bb,"Images/lz.rgb"));
738    root->addChild(createAnisotripicWall(bb,"Images/primitives.gif"));
739    root->addChild(createWrapWall(bb,"Images/tree0.rgba"));
740    root->addChild(createSubloadWall(bb));
741   
742    return root;
743}
744
745int main(int , char **)
746{
747    // construct the viewer.
748    osgViewer::Viewer viewer;
749
750    // add model to viewer.
751    viewer.setSceneData( createModel() );
752
753    return viewer.run();
754}
Note: See TracBrowser for help on using the browser.