1 // OpenSG Tutorial Example: Changing Texture on Background
3 // This example shows how to change the texture displayed on a
4 // TextureBackground in each frame. This could be used to play back a video.
6 #ifdef OSG_BUILD_ACTIVE
10 #include <OSGSimpleGeometry.h>
11 #include <OSGGLUTWindow.h>
12 #include <OSGSimpleSceneManager.h>
14 #include <OSGTextureObjChunk.h>
15 #include <OSGBaseFunctions.h>
17 #include <OSGTextureBackground.h>
22 #include <OpenSG/OSGConfig.h>
23 #include <OpenSG/OSGGLUT.h>
24 #include <OpenSG/OSGSimpleGeometry.h>
25 #include <OpenSG/OSGGLUTWindow.h>
26 #include <OpenSG/OSGSimpleSceneManager.h>
28 #include <OpenSG/OSGTextureObjChunk.h>
29 #include <OpenSG/OSGBaseFunctions.h>
31 #include <OpenSG/OSGTextureBackground.h>
32 #include <OpenSG/OSGImage.h>
34 #endif // OSG_BUILD_ACTIVE
36 // The pointer to the transformation
38 OSG::TransformRefPtr trans
;
40 // The pointer to the dynamic image and the texture
42 OSG::ImageRefPtr image
;
43 OSG::TextureObjChunkRefPtr texObj
;
45 // Some helper flags for different code pathes
46 // flag to indicate whether the images are power-of-two (POT) in size or not
50 // flag to indicate whether NPOT textures are available
51 // Purely informative, the code doesn't really care.
56 // flag to indicate that only a small part of the image should be changed
57 // per frame. The random image generation can get slow for large
60 bool changeOnlyPart
= false;
62 // The SimpleSceneManager to manage simple applications
64 OSG::SimpleSceneManagerRefPtr mgr
;
66 // forward declaration so we can have the interesting stuff upfront
68 int setupGLUT(int *argc
, char *argv
[]);
71 // Grab/update the image
72 // This just update the image's data and tells the texture that it changed.
73 // For a video this would grab the next frame
75 void grabImage(OSG::Image
*img
)
77 OSG::UInt8
* data
= img
->editData();
79 // for this example, just fill it with random junk
82 // Just change a small rectangular area
83 OSG::UInt32 x
= rand() % (img
->getWidth() - 100);
84 OSG::UInt32 y
= rand() % (img
->getHeight() - 100);
85 OSG::UInt32 w
= rand() % 100;
86 OSG::UInt32 h
= rand() % 100;
87 OSG::UInt32 bpp
= img
->getBpp();
88 OSG::UInt32 bpl
= img
->getWidth() * bpp
;
89 OSG::UInt32 bytes
= w
* bpp
;
91 data
+= y
* bpl
+ x
* bpp
;
93 OSG::UInt8 val
= ((rand() & 0x7f) + 0x80);
95 for(OSG::UInt32 i
= h
; i
> 0; --i
, data
+= bpl
)
99 for(OSG::UInt32 j
= bytes
; j
> 0; --j
)
103 // If only a part of the image changed, only that part needs to
104 // be updated. The speed of the update operation is pretty
105 // directly dependent on the amount of data changed.
106 texObj
->imageContentChanged(x
, x
+ w
, y
, y
+ h
);
111 // Fill the whole picture
113 for(OSG::UInt32 i
= img
->getHeight(); i
> 0; --i
)
115 OSG::UInt8 val
= ((rand() & 0x3f) + 0x80);
117 for(OSG::UInt32 j
= img
->getWidth() * img
->getBpp(); j
> 0; --j
)
121 // Everything changed
122 texObj
->imageContentChanged();
131 // update the geometry
134 OSG::Real32 t
= glutGet(GLUT_ELAPSED_TIME
);
136 m
.setTransform(OSG::Vec3f(OSG::osgSin(t
/ 1000.f
),
137 OSG::osgCos(t
/ 1000.f
),
138 OSG::osgSin(t
/ 1000.f
)),
140 OSG::Quaternion( OSG::Vec3f(0,1,0), t
/ 1000.f
));
158 // Initialize GLUT & OpenSG and set up the scene
159 int main(int argc
, char **argv
)
162 OSG::osgInit(argc
,argv
);
165 int winid
= setupGLUT(&argc
, argv
);
168 // the connection between GLUT and OpenSG
169 OSG::GLUTWindowRefPtr gwin
= OSG::GLUTWindow::create();
171 gwin
->setGlutId(winid
);
175 OSG::NodeRefPtr torus
= OSG::makeTorus( .5, 2, 16, 32 );
176 OSG::NodeRefPtr scene
= OSG::Node::create();
178 trans
= OSG::Transform::create();
180 scene
->setCore(trans
);
181 scene
->addChild(torus
);
183 // Create the parts needed for the video background
184 OSG::UInt32 width
= 640;
185 OSG::UInt32 height
= 480;
187 // get the desired size from the command line
190 width
= atoi(argv
[1]);
191 height
= atoi(argv
[2]);
194 // To check OpenGL extensions, the Window needs to have run through
195 // frameInit at least once. This automatically happens when rendering,
196 // but we can't wait for that here.
201 // Now we can check for OpenGL extensions
202 hasNPOT
= gwin
->hasExtension("GL_ARB_texture_non_power_of_two");
204 // Print what we've got
205 SLOG
<< "Got " << (isPOT
?"":"non-") << "power-of-two images and "
206 << (hasNPOT
?"can":"cannot") << " use NPOT textures, changing "
207 << (changeOnlyPart
?"part":"all")
211 // Ok, now for the meat of the code...
212 // first we need an Image to hold the picture(s) to show
213 image
= OSG::Image::create();
215 // set the image's size and type, and allocate memory
216 // this example uses RGB. On some systems (e.g. Windows) BGR
217 // or BGRA might be faster, it depends on how the images are
220 image
->set(OSG::Image::OSG_RGB_PF
, width
, height
);
224 // Now create the texture to be used for the background
225 texObj
= OSG::TextureObjChunk::create();
227 // Associate image and texture
228 texObj
->setImage(image
);
230 // Set filtering modes. LINEAR is cheap and good if the image size
231 // changes very little (i.e. the window is about the same size as
234 texObj
->setMinFilter(GL_LINEAR
);
235 texObj
->setMagFilter(GL_LINEAR
);
237 // Set the wrapping modes. We don't need repetition, it might actually
238 // introduce artifactes at the borders, so switch it off.
240 texObj
->setWrapS(GL_CLAMP_TO_EDGE
);
241 texObj
->setWrapT(GL_CLAMP_TO_EDGE
);
243 // Newer versions of OpenGL can handle NPOT textures directly.
244 // OpenSG will do that internally automatically.
246 // Older versions need POT textures. By default OpenSG
247 // will scale an NPOT texture to POT while defining it.
248 // For changing textures that's too slow.
249 // So tell OpenSG not to scale the image and adjust the texture
250 // coordinates used by the TextureBackground (see below).
252 texObj
->setScale(false);
254 // Create the background
256 OSG::TextureBackgroundRefPtr back
= OSG::TextureBackground::create();
258 // Set the texture to use
259 back
->setTexture(texObj
);
261 // if the image is NPOT and we don't have hardware support for it
262 // adjust the texture coordinates.
263 if(isPOT
== false && hasNPOT
== false)
265 OSG::UInt32 potWidth
= OSG::osgNextPower2(width
);
266 OSG::UInt32 potHeight
= OSG::osgNextPower2(height
);
268 OSG::Real32 tcRight
= OSG::Real32(width
) / OSG::Real32(potWidth
);
269 OSG::Real32 tcTop
= OSG::Real32(height
) / OSG::Real32(potHeight
);
271 back
->editMFTexCoords()->push_back(OSG::Vec2f( 0.f
, 0.f
));
272 back
->editMFTexCoords()->push_back(OSG::Vec2f(tcRight
, 0.f
));
273 back
->editMFTexCoords()->push_back(OSG::Vec2f(tcRight
, tcTop
));
274 back
->editMFTexCoords()->push_back(OSG::Vec2f( 0.f
, tcTop
));
277 OSG::commitChanges();
279 // create the SimpleSceneManager helper
280 mgr
= OSG::SimpleSceneManager::create();
282 // tell the manager what to manage
283 mgr
->setWindow(gwin
);
284 mgr
->setRoot (scene
);
285 mgr
->setStatistics(true);
287 // replace the background
288 // This has to be done after the viewport has been created, which the
289 // SSM does in setRoot().
291 OSG::ViewportRefPtr vp
= gwin
->getPort(0);
293 vp
->setBackground(back
);
296 // show the whole scene
307 // GLUT callback functions
310 // react to size changes
311 void reshape(int w
, int h
)
318 // react to mouse button presses
319 void mouse(int button
, int state
, int x
, int y
)
322 mgr
->mouseButtonRelease(button
, x
, y
);
324 mgr
->mouseButtonPress(button
, x
, y
);
329 // react to mouse motions with pressed buttons
330 void motion(int x
, int y
)
332 mgr
->mouseMove(x
, y
);
338 void keyboard(unsigned char k
, int x
, int y
)
352 // setup the GLUT library which handles the windows for us
353 int setupGLUT(int *argc
, char *argv
[])
355 glutInit(argc
, argv
);
357 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
358 int winid
= glutCreateWindow("OpenSG");
360 glutReshapeFunc(reshape
);
361 glutDisplayFunc(display
);
362 glutMouseFunc(mouse
);
363 glutMotionFunc(motion
);
365 glutKeyboardFunc(keyboard
);
367 // call the redraw function whenever there's nothing else to do
368 glutIdleFunc(update
);
381 OSG::commitChanges();