The following c++ code fully initializes a 3d object in my project using the irrlicht.dll 3d engine. Following that I have a class which can convert an avi movie into a texture which can be displayed on my 3d object. It would be extremely helpful if you could tell me how to instantiate the class, what to pass through it and how I can throw it onto my model. After the VideoTexture class I added my main.cpp which holds all of my current code on this project in case it is needed.
/* VideoTexture.cpp From the Microsoft DirectX SDK Modified by Matthew Fisher
VideoTexture is a DirectX-only object that allows you to use a video file as a source for textures in the scene. It is really just an interface to CTextureRenderer, a Microsoft class that handles the interaction with DirectShow. Note the this creates another (very intensive) thread to the program that handles the decompression, so applications should sleep for between 5 and 30 milliseconds each frame (just set the SleepBetweenFrames variable in God.cpp.) */
class CTextureRenderer : public CBaseVideoRenderer { public: CTextureRenderer(LPUNKNOWN pUnk,HRESULT *phr); ~CTextureRenderer();
public: HRESULT CheckMediaType(const CMediaType *pmt ); // Format acceptable? HRESULT SetMediaType(const CMediaType *pmt ); // Video format notification HRESULT DoRenderSample(IMediaSample *pMediaSample); // New video sample
LONG m_lVidWidth; // Video width LONG m_lVidHeight; // Video Height LONG m_lVidPitch; // Video Pitch VideoTexture *Parent; };
if (!(!g_pMC)) g_pMC->Stop(); if (!(!g_pMC)) g_pMC.Release(); if (!(!g_pME)) g_pME.Release(); if (!(!g_pMP)) g_pMP.Release(); if (!(!g_pGB)) g_pGB.Release(); }
// Create the filter graph if (FAILED(g_pGB.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC))) { FatalMB("CoCreate failed."); return E_FAIL; }
// Create the Texture Renderer object pCTR = new CTextureRenderer(NULL, &hr); if (FAILED(hr)) { Msg(TEXT("Could not create texture renderer object! hr=0x%x"), hr); return E_FAIL; } pCTR->Parent = this;
// Get a pointer to the IBaseFilter on the TextureRenderer, add it to graph pFTR = pCTR; if (FAILED(hr = g_pGB->AddFilter(pFTR, L"TEXTURERENDERER"))) { Msg(TEXT("Could not add renderer filter to graph! hr=0x%x"), hr); return hr; }
if (FAILED(hr = g_pGB->Render(SourcePin))) { Msg(TEXT("Could not render Source Pin. hr=0x%x"), hr); return hr; }
// Get the graph's media control, event & position interfaces g_pGB.QueryInterface(&g_pMC); g_pGB.QueryInterface(&g_pMP); g_pGB.QueryInterface(&g_pME); g_pGB.QueryInterface(&g_pMS);
// Start the graph running; if (FAILED(hr = g_pMC->Run())) { Msg(TEXT("Could not run the DirectShow graph! hr=0x%x"), hr); return hr; } return S_OK; }
void VideoTexture::Loop() { long lEventCode; long lParam1; long lParam2; HRESULT hr;
// Check for completion events hr = g_pME->GetEvent(&lEventCode, (LONG_PTR *) &lParam1, (LONG_PTR *) &lParam2, 0); if (SUCCEEDED(hr)) { if (EC_COMPLETE == lEventCode) { hr = g_pMP->put_CurrentPosition(0); }
// Free any memory associated with this event hr = g_pME->FreeEventParams(lEventCode, lParam1, lParam2); } }
// D3DXCreateTexture can silently change the parameters on us D3DSURFACE_DESC ddsd; if ( FAILED( hr = myTexture->GetLevelDesc( 0, &ddsd ) ) ) { Msg(TEXT("Could not get level Description of D3DX texture! hr = 0x%x"), hr); return hr; } TextureFormat = ddsd.Format; if (TextureFormat != D3DFMT_A8R8G8B8) { Msg(TEXT("Texture is format we can't handle! Format = 0x%x"), TextureFormat); return VFW_E_TYPE_NOT_ACCEPTED; }
return S_OK; }
CTextureRenderer::CTextureRenderer( LPUNKNOWN pUnk, HRESULT *phr ) : CBaseVideoRenderer(__uuidof(CLSID_TextureRenderer), NAME("Texture Renderer"), pUnk, phr) { // Store and AddRef the texture for our use. *phr = S_OK; }
//----------------------------------------------------------------------------- // CheckMediaType: This method forces the graph to give us an R8G8B8 video // type, making our copy to texture memory trivial. //----------------------------------------------------------------------------- HRESULT CTextureRenderer::CheckMediaType(const CMediaType *pmt) { HRESULT hr = E_FAIL; VIDEOINFO *pvi;
// Reject the connection if this is not a video type if( *pmt->FormatType() != FORMAT_VideoInfo ) { return E_INVALIDARG; }
class skyBox{ private: ISceneManager* sc; //scene IVideoDriver* dr; //driver char* name; //skybox name char path[50];
public: skyBox( ISceneManager* s, IVideoDriver* d, char p[50], char* n ) { sc=s; dr=d; name=n; strcpy(path,p); //path to all skyBox textures /* skyboxes should all be named in the format *up.bmp, *dn.bmp, *rt.bmp, *lt.bmp, *ft.bmp, *bk.bmp where * is all the same name ie blue2 */ } void start(){ //create skybox dr->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
class MyEventReceiver : public IEventReceiver { public:
MyEventReceiver(scene::ISceneNode* terrain, gui::IGUIStaticText* object1, gui::IGUIStaticText* object2 ) { // store pointer to terrain so we can change its drawing mode Terrain = terrain; Object1 = object1; Object2 = object2; }
bool OnEvent(SEvent event) { // check if user presses the key 'W' or 'D' if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) { switch (event.KeyInput.Key) { case irr::KEY_KEY_W: // switch wire frame mode Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe); Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false); return true; case irr::KEY_KEY_P: // switch wire frame mode Terrain->setMaterialFlag(video::EMF_POINTCLOUD, !Terrain->getMaterial(0).PointCloud); Terrain->setMaterialFlag(video::EMF_WIREFRAME, false); return true; case irr::KEY_KEY_D: // toggle detail map Terrain->setMaterialType( Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ? video::EMT_DETAIL_MAP : video::EMT_SOLID); return true; case irr::KEY_KEY_C: // toggle clear screen Object1->setVisible( Object1->isVisible() == 0 ? 1 : 0); Object2->setVisible( Object2->isVisible() == 0 ? 1 : 0);
/* To display something interesting, we load a Quake 2 model and display it. We only have to get the Mesh from the Scene Manager (getMesh()) and add a SceneNode to display the mesh. (addAnimatedMeshSceneNode()). Instead of writing the filename sydney.md2, it would also be possible to load a Maya object file (.obj), a complete Quake3 map (.bsp) or a Milshape file (.ms3d). By the way, that cool Quake 2 model called sydney was modelled by Brian Collins. */
// add irrlicht logo // guienv->addImage(driver->getTexture("media/irrlichtlogo2.png"), // core::position2d<s32>(10,10));
//set other font guienv->getSkin()->setFont(guienv->getFont("media/fontlucida.png"));
// add some help text //gui::IGUIStaticText* text = guienv->addStaticText( //L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map", //core::rect<s32>(10,440,250,475), true, true, 0, -1, true);
/* To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain. */
// create triangle selector for the terrain scene::ITriangleSelector* selector = smgr->createTerrainTriangleSelector(terrain, 0); terrain->setTriangleSelector(selector); selector->drop();
// create collision response animator and attach it to the camera scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(60,100,60), core::vector3df(0,0,0), core::vector3df(0,50,0)); camera->addAnimator(anim); anim->drop();
/* To make the user be able to switch between normal and wireframe mode, we create an instance of the event reciever from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples. */
//lt smgr->addLightSceneNode(0, core::vector3df(528000,10000,256000), video::SColorf(1.0f,1.0f,1.0f,1.0f), 600000.0f); //rt smgr->addLightSceneNode(0, core::vector3df(20000,10000,256000), video::SColorf(1.0f,1.0f,1.0f,1.0f), 600000.0f); //bk smgr->addLightSceneNode(0, core::vector3df(254000,10000,532000), video::SColorf(1.0f,1.0f,1.0f,1.0f), 600000.0f); */ /* Ok, now we have set up the scene, lets draw everything: We run the device in a while() loop, until the device does not want to run any more. This would be when the user closed the window or pressed ALT+F4 in windows. */
/* Another type of picking supported by the Irrlicht Engine is scene node picking based on bouding boxes. Every scene node has got a bounding box, and because of that, it's very fast for example to get the scene node which the camera looks at. Again, we ask the collision manager for this, and if we've got a scene node, we highlight it by disabling Lighting in its material, if it is not the billboard or the quake 3 level. */
if (selectedSceneNode) //selectedSceneNode->setMaterialFlag(video::EMF_LIGHTING, false);
lastSelectedSceneNode = selectedSceneNode;
driver->endScene();
// display frames per second in window title int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Terrain Renderer - Irrlicht Engine ["; str += driver->getName(); str += "] FPS:"; str += fps; // Also print terrain height of current camera position // We can use camera position because terrain is located at coordinate origin str += " Height: "; str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z);
int main() { void copyObject( int number, int distance, IAnimatedMesh* amesh, IAnimatedMeshSceneNode* anode, ISceneManager* sc ); /* The most important function of the engine is the 'createDevice' function. The Irrlicht Device can be created with it, which is the root object for doing everything with the engine. createDevice() has 7 paramters: deviceType: Type of the device. This can currently be the Null-device, the Software device, the second software renderer, D3D8, D3D9, or OpenGL. In this example we use EDT_SOFTWARE, but to try out, you might want to change it to EDT_BURNINGSVIDEO, EDT_NULL, EDT_DIRECT3D8 , EDT_DIRECT3D9, or EDT_OPENGL. windowSize: Size of the Window or FullscreenMode to be created. In this example we use 640x480. bits: Amount of bits per pixel when in fullscreen mode. This should be 16 or 32. This parameter is ignored when running in windowed mode. fullscreen: Specifies if we want the device to run in fullscreen mode or not. stencilbuffer: Specifies if we want to use the stencil buffer for drawing shadows. vsync: Specifies if we want to have vsync enabled, this is only useful in fullscreen mode. eventReceiver: An object to receive events. We do not want to use this parameter here, and set it to 0. */