Brief Introduction
This lesson describes how to play a video in a three-dimensional scenario. We all know that the video is actually made up of a picture of a frame, so we parse the images in the video into a picture format and assign them to the surface of the geometry, allowing them to switch within a very short interval to achieve a dynamic effect. Implement
In this lesson, you use the API for Windows parsing video format AVI file, which comes from the code in the Nehe course, which readers can check out on MSDN to learn about:
First create the geometry that plays the AVI file (similar to the big screen of the movie)
osg::geode* Createbackgroundgeode (osg::texture2d *text)
{
Osg::geode *geode = new Osg::geode;
Osg::geometry *geometry = new Osg::geometry;
Geometry->setupdatecallback (new dynamictextureupdatecallback);
...
Geometry->setvertexarray (Vertexarray);
Geometry->settexcoordarray (0, Texturearray, Osg::array::bind_per_vertex);
Geometry->addprimitiveset (new OSG::D rawarrays (osg::P rimitiveset::quads, 0, Vertexarray->size ()));
Geometry->getorcreatestateset ()->settextureattributeandmodes (0, text);
Geometry->getorcreatestateset ()->setmode (gl_lighting, false);
Geode->adddrawable (geometry);
return geode;
}
Dynamic texture callback Dynamictextureupdatecallback enables dynamic modification of textures:
Class Dynamictextureupdatecallback:public OSG::D rawable::updatecallback
{public
:
Dynamictextureupdatecallback (): _lastupdate (0), _frame (0), _passedtimeinmillsecond (0)
{
_starttime = OSG:: Timer::instance ()->tick ();
_currenttime = _starttime;
}
void Update (Osg::nodevisitor* NV, OSG::D rawable* drawable)
{
Osg::geometry *geometry = dynamic_cast<osg:: Geometry*> (drawable);
if (!geometry)
...}}
;
Then create the geometry in the scene:
osg::node* Createbox ()
osg::node* createsphere ()
osg::node* Createcylinder ()
This part is similar to the 23rd lesson.
Add all the above geometry to a switch switch node to implement the toggle operation:
The effect of switching texture and switching nodes in the interaction with the keyboard:
Case (Osgga::guieventadapter::keydown):
{
if (ea.getkey () = = Osgga::guieventadapter::key_space)
{
if (!g_switchnode) return
false;
static int i = 0;
++i;
if (i > 2)
i = 0;
G_switchnode->setsinglechildon (i);
}
if (ea.getkey () = = Osgga::guieventadapter::key_e)
{
static bool flag = TRUE;
if (flag) {
g_switchnode->getorcreatestateset ()->settexturemode (0, gl_texture_gen_s, OSG:: Stateattribute::off);
G_switchnode->getorcreatestateset ()->settexturemode (0, gl_texture_gen_t, osg::stateattribute::off);
else{
G_switchnode->getorcreatestateset ()->settexturemode (0, gl_texture_gen_s, Osg::StateAttribute::O N);
G_switchnode->getorcreatestateset ()->settexturemode (0, gl_texture_gen_t, osg::stateattribute::on);
flag =!flag;
}
Add all of the above to the scene root node. To compile and run the program:
Attached: This lesson source code (source code may exist errors and deficiencies, for reference only)
#include ". /osgnehe.h "#include <QtCore/QTimer> #include <QtGui/QApplication> #include <QtGui/QVBoxLayout> Include <osgViewer/Viewer> #include <osgDB/ReadFile> #include <osgQt/GraphicsWindowQt> #include <osg/MatrixTransform> #include <osg/Texture2D> #include <osg/ShapeDrawable> #include <osg/ switch> #include <osg/AnimationPath> #include <osg/TexGen> #include <osg/TexGenNode> #include
<vfw.h> Avistreaminfo psi;
Pavistream Pavi;
Pgetframe PGF;
Bitmapinfoheader Bmih;
Long Lastframe;
int width;
int height;
Char *pdata;
int MPF;
Hdrawdib HDD;
Hbitmap Hbitmap;
HDC HDC = CreateCompatibleDC (0);
unsigned char* data = 0;
Osg::texture2d *g_texture2d = NULL;
Osg::image *g_textureimage = NULL;
Osg::switch *g_switchnode = NULL;
void Flipit (void* buffer) {void* b = buffer;
__asm { mov ecx, 256*256 mov ebx, b label:mov al,[ebx+0] mov ah,[ebx+2] mov [ebx+2],al mov [ebx+0],ah add ebx,3 Dec ecx jnz label}} void Openavi (LPCSTR szf
ile) {TCHAR title[100];
Avifileinit ();
if (Avistreamopenfromfilea (&pavi, Szfile, Streamtypevideo, 0, Of_read, NULL)!=0) {return;
Avistreaminfo (Pavi, &psi, sizeof (PSI));
Width=psi.rcframe.right-psi.rcframe.left;
Height=psi.rcframe.bottom-psi.rcframe.top;
Lastframe=avistreamlength (Pavi);
Mpf=avistreamsampletotime (pavi,lastframe)/lastframe;
bmih.bisize = sizeof (Bitmapinfoheader);
Bmih.biplanes = 1;
Bmih.bibitcount = 24;
Bmih.biwidth = 256;
Bmih.biheight = 256;
Bmih.bicompression = Bi_rgb;
Hbitmap = CreateDIBSection (hdc, (bitmapinfo*) (&BMIH), Dib_rgb_colors, (void**) (&data), NULL, NULL);
SelectObject (hdc, HBITMAP);
Pgf=avistreamgetframeopen (Pavi, NULL);
if (pgf==null) {return; } void GrabaViframe (int frame) {Lpbitmapinfoheader lpbi;
LPBI = (lpbitmapinfoheader) avistreamgetframe (PGF, frame);
Pdata= (char *) lpbi+lpbi->bisize+lpbi->biclrused * sizeof (RGBQUAD);
Drawdibdraw (HDD, HDC, 0, 0, 256, 256, LPBI, pdata, 0, 0, width, height, 0);
Flipit (data);
G_textureimage->setimage (256, 256, 1, 3, Gl_rgb, Gl_unsigned_byte, data, osg::image::no_delete);
G_texture2d->setimage (G_textureimage);
} void Closeavi (void) {DeleteObject (HBITMAP);
Drawdibclose (HDD);
Avistreamgetframeclose (PGF);
Avistreamrelease (Pavi);
Avifileexit ();
} void Initialize () {HDD = Drawdibopen ();
g_texture2d = new Osg::texture2d;
G_texture2d->setfilter (Osg::texture::mag_filter, osg::texture::nearest);
G_texture2d->setfilter (Osg::texture::min_filter, osg::texture::nearest);
G_textureimage = new Osg::image;
G_textureimage->allocateimage (256, 256, 1, GL_RGB, gl_unsigned_byte);
Openavi ("Data/face3.avi"); Class Dynamictextureupdatecallback:public OSG::D rawable::updateCallback {public:dynamictextureupdatecallback (): _lastupdate (0), _frame (0), _passedtimeinmillsecond (0) {_startTime
= Osg::timer::instance ()->tick ();
_currenttime = _starttime; } void Update (Osg::nodevisitor* NV, OSG::D rawable* drawable) {osg::geometry *geometry = Dynamic_cast<osg::geometr
Y*> (drawable);
if (!geometry) return; Osg::texture2d *texture2d = dynamic_cast<osg::texture2d *> (geometry->getorcreatestateset ()->
Gettextureattribute (0, osg::stateattribute::texture));
if (!texture2d) return; if (nv->getvisitortype () = = Osg::nodevisitor::update_visitor && nv->getframestamp () && nv->
Getframestamp ()->getframenumber ()!= _lastupdate) {_lastupdate = Nv->getframestamp ()->getFrameNumber ();
_currenttime = Osg::timer::instance ()->tick ();
float T = osg::timer::instance ()->delta_m (_starttime, _currenttime);
_passedtimeinmillsecond + = t; if (_passeDtimeinmillsecond >= MPF) {grabaviframe (_frame);
_frame++;
if (_frame >= lastframe) {_frame = 0;
} _passedtimeinmillsecond = 0;
}} osg::timer_t _starttime;
osg::timer_t _currenttime;
unsigned int _lastupdate;
unsigned int _frame;
int _passedtimeinmillsecond;
}; Drawing Geometry///////// osg::geode*
Createbackgroundgeode (osg::texture2d *text) {Osg::geode *geode = new Osg::geode;
Osg::geometry *geometry = new Osg::geometry;
Geometry->setupdatecallback (new Dynamictextureupdatecallback);
Osg::vec3array *vertexarray = new Osg::vec3array;
Osg::vec2array *texturearray = new Osg::vec2array;
Vertexarray->push_back (OSG::VEC3 (11.0f, 8.3f, -20.0f));
Vertexarray->push_back (OSG::VEC3 ( -11.0f, 8.3f, -20.0f)); Vertexarray->push_baCK (OSG::VEC3 ( -11.0f, -8.3f, -20.0f));
Vertexarray->push_back (OSG::VEC3 (11.0f, -8.3f, -20.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 0.0f));
Geometry->setvertexarray (Vertexarray);
Geometry->settexcoordarray (0, Texturearray, Osg::array::bind_per_vertex);
Geometry->addprimitiveset (new OSG::D rawarrays (osg::P rimitiveset::quads, 0, Vertexarray->size ()));
Geometry->getorcreatestateset ()->settextureattributeandmodes (0, text);
Geometry->getorcreatestateset ()->setmode (gl_lighting, false);
Geode->adddrawable (geometry);
return geode;
} osg::node* Createbox (/*osg::texture2d *text*/) {osg::matrixtransform *mtx = new Osg::matrixtransform;
Mtx->addupdatecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::x_axis, 1.5));
Osg::matrixtransform *mty = new Osg::matrixtransform; Mty->addupdAtecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::y_axis, 2.5));
Osg::matrixtransform *mtz = new Osg::matrixtransform;
Mtz->addupdatecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::z_axis, 3.5));
Osg::geode *geode = new Osg::geode;
Osg::geometry *geometry = new Osg::geometry;
Osg::vec3array *vertexarray = new Osg::vec3array;
Osg::vec2array *texturearray = new Osg::vec2array;
Osg::vec3array *normalarray = new Osg::vec3array;
for (int i = 0; i < 4; ++i) Normalarray->push_back (OSG::VEC3 (0.0f, 0.0f, 0.5f));
Texturearray->push_back (OSG::VEC2 (0.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, -1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, -1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, 1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, 1.0f, 1.0f)); for (int i = 0; i < 4; ++i) Normalarray->push_back (OSG::VEC3 (0.0f, 0.0f,-0.5f));
Texturearray->push_back (OSG::VEC2 (1.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 0.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, -1.0f, -1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, 1.0f, -1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, 1.0f,-1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, -1.0f, -1.0f));
for (int i = 0; i < 4; ++i) Normalarray->push_back (OSG::VEC3 (0.0f, 0.5f,0.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, 1.0f, -1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, 1.0f, 1.0f)); Vertexarray->push_back (OSG::VEC3 (1.0f, 1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, 1.0f, -1.0f));
for (int i = 0; i < 4; ++i) Normalarray->push_back (OSG::VEC3 (0.0f, -0.5f,0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 0.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, -1.0f, -1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, -1.0f, -1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, -1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, -1.0f, 1.0f));
for (int i = 0; i < 4; ++i) Normalarray->push_back (OSG::VEC3 (0.5f, 0.0f,0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 0.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, -1.0f, -1.0f)); Vertexarray->push_bacK (OSG::VEC3 (1.0f, 1.0f, -1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, 1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 (1.0f, -1.0f, 1.0f));
for (int i = 0; i < 4; ++i) Normalarray->push_back (OSG::VEC3 ( -0.5f, 0.0f,0.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 0.0f));
Texturearray->push_back (OSG::VEC2 (1.0f, 1.0f));
Texturearray->push_back (OSG::VEC2 (0.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, -1.0f, -1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, -1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, 1.0f, 1.0f));
Vertexarray->push_back (OSG::VEC3 ( -1.0f, 1.0f, -1.0f));
Geometry->setvertexarray (Vertexarray);
Geometry->setnormalarray (Normalarray, Osg::array::bind_per_vertex);
Geometry->settexcoordarray (0, Texturearray, Osg::array::bind_per_vertex);
Geometry->addprimitiveset (new OSG::D rawarrays (osg::P rimitiveset::quads, 0, Vertexarray->size ())); GeoMetRy->getorcreatestateset ()->setmode (gl_lighting, false);
Geode->adddrawable (geometry);
Mtx->addchild (mty);
Mty->addchild (MtZ);
Mtz->addchild (Geode);
return to MtX;
} osg::node* Createsphere () {osg::matrixtransform *mtx = new Osg::matrixtransform;
Mtx->addupdatecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::x_axis, 1.5));
Osg::matrixtransform *mty = new Osg::matrixtransform;
Mty->addupdatecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::y_axis, 2.5));
Osg::matrixtransform *mtz = new Osg::matrixtransform;
Mtz->addupdatecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::z_axis, 3.5));
Osg::geode *sphere = new Osg::geode;
Osg::shapedrawable *spheredrawable = new Osg::shapedrawable (New Osg::sphere (OSG::VEC3 (0,0,0), 1.3));
Sphere->adddrawable (spheredrawable);
Mtx->addchild (mty);
Mty->addchild (MtZ);
Mtz->addchild (Sphere);
return to MtX; } osg::node* Createcylinder () {osg::matrixtransform *mtx = new Osg::matRixtransform;
Mtx->addupdatecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::x_axis, 1.5));
Osg::matrixtransform *mty = new Osg::matrixtransform;
Mty->addupdatecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::y_axis, 2.5));
Osg::matrixtransform *mtz = new Osg::matrixtransform;
Mtz->addupdatecallback (New Osg::animationpathcallback (OSG::VEC3 (), Osg::z_axis, 3.5));
Osg::geode *cylinder = new Osg::geode;
Osg::shapedrawable *cylinderdrawable = new Osg::shapedrawable (New Osg::cylinder (OSG::VEC3 (0,0,0), 0.5, 2.0));
Cylinder->adddrawable (cylinderdrawable);
Mtx->addchild (mty);
Mty->addchild (MtZ);
Mtz->addchild (cylinder);
return to MtX; ///////////////////////////////////////////////////////////////////////////////////////////////////////Scene Interaction/// Class Manipulatorscenehandler:public Osgga::guieventhandler {Public:manipulatorscenehandler() {} virtual bool handle (const osgga::guieventadapter& EA, osgga::guiactionadapter& aa) {Osgviewer::view
Er *viewer = dynamic_cast<osgviewer::viewer*> (&AA);
if (!viewer) return false;
if (!viewer->getscenedata ()) return false;
if (ea.gethandled ()) return false; Switch (Ea.geteventtype ()) {case (Osgga::guieventadapter::keydown): {if (ea.getkey () = = Osgga::guieventadapter:
: Key_space) {if (!g_switchnode) return false;
static int i = 0;
++i;
if (i > 2) i = 0;
G_switchnode->setsinglechildon (i);
} if (Ea.getkey () = = osgga::guieventadapter::key_e) {static BOOL flag = TRUE; if (flag) {G_switchnode->getorcreatestateset ()->settexturemode (0, gl_texture_gen_s, Osg::stateattribute::off
);
G_switchnode->getorcreatestateset ()->settexturemode (0, gl_texture_gen_t, Osg::stateattribute::off); }else{G_switchnode->getorcreatestateset ()->Settexturemode (0, gl_texture_gen_s, osg::stateattribute::on);
G_switchnode->getorcreatestateset ()->settexturemode (0, gl_texture_gen_t, osg::stateattribute::on);
} flag =!flag;
}} Default:break;
return false;
}
}; //////////////////////////////////////////////////////////////////////////
///////////////////////////////////// Osgnehe Frame/////////////////////////////////////// Class Viewerwidget:public Qwidget, public osgviewer :: Viewer {public:viewerwidget (osg::node *scene = NULL) {qwidget* renderwidget = Getrenderwidget (creategraphicswind
ow (0,0,100,100), scene);
qvboxlayout* layout = new Qvboxlayout;
Layout->addwidget (Renderwidget);
Layout->setcontentsmargins (0, 0, 0, 1);
SetLayout (layout);
Connect (&_timer, SIGNAL (timeout ()), this, SLOT (update ()));
_timer.start (10); } qwidget* geTrenderwidget (osgqt::graphicswindowqt* GW, osg::node* scene) {osg::camera* Camera = This->getcamera ();
Camera->setgraphicscontext (GW);
Const osg::graphicscontext::traits* Traits = Gw->gettraits ();
Camera->setclearcolor (OSG::VEC4 (0.0, 0.0, 0.0, 1.0));
Camera->setviewport (New Osg::viewport (0, 0, traits->width, traits->height)); Camera->setprojectionmatrixasperspective (45.0f, static_cast<double> (traits->width)/static_cast<
Double> (Traits->height), 0.1f, 100.0f);
Camera->setviewmatrixaslookat (osg::vec3d (0, 0, 0), osg::vec3d (0, 0,-1), osg::vec3d (0, 1, 0));
This->setscenedata (Scene);
This->addeventhandler (new Manipulatorscenehandler);
return Gw->getglwidget (); osgqt::graphicswindowqt* Creategraphicswindow (int x, int y, int w, int h, const std::string& name= "", bool Window
Decoration=false) {osg::D isplaysettings* ds = osg::D isplaysettings::instance (). get (); Osg::ref_ptr<osg::graphicscontext::traits> Traits = new Osg::graphicscontext::traits;
Traits->windowname = name;
Traits->windowdecoration = windowdecoration;
traits->x = x;
Traits->y = y;
Traits->width = W;
Traits->height = h;
Traits->doublebuffer = true;
Traits->alpha = Ds->getminimumnumalphabits ();
Traits->stencil = Ds->getminimumnumstencilbits ();
Traits->samplebuffers = Ds->getmultisamples ();
Traits->samples = Ds->getnummultisamples ();
return new OSGQT::GRAPHICSWINDOWQT (Traits.get ());
virtual void PaintEvent (qpaintevent* event) {frame ();
} Protected:qtimer _timer;
};
osg::node* Buildscene () {initialize ();
Osg::group *root = new Osg::group;
Osg::switch *switchnode = new Osg::switch;
G_switchnode = Switchnode;
Switchnode->addchild (Createbox ());
Switchnode->addchild (Createcylinder ());
Switchnode->addchild (Createsphere ());
Switchnode->setsinglechildon (0);
Osg::texgen *texgen = new Osg::texgen;Texgen->setmode (OSG::TEXGEN::SPHERE_MAP);
Switchnode->getorcreatestateset ()->settextureattributeandmodes (0, Texgen);
Switchnode->getorcreatestateset ()->settextureattributeandmodes (0, g_texture2d);
Osg::matrixtransform *zoommt = new Osg::matrixtransform;
Zoommt->setmatrix (Osg::matrix::translate (0.0f, 0.0f, -10.0f));
Zoommt->addchild (Switchnode);
Root->addchild (Createbackgroundgeode (g_texture2d));
Root->addchild (ZOOMMT);
return root;
int main (int argc, char** argv) {qapplication app (argc, argv);
viewerwidget* viewwidget = new Viewerwidget (Buildscene ());
Viewwidget->setgeometry (100, 100, 640, 480);
Viewwidget->show ();
return App.exec ();
}