wxMax and Irrlitcht Engine
BlitzMax Forums/BlitzMax Programming/wxMax and Irrlitcht Engine
| ||
Hi, Is it possible to run irrlitcht in a canvas of wxmax? I've been looking into it and I can't find anyone that's tried it and I'm a noob with irrlitcht and graphics. Any code or help would be much appreciated. |
| ||
This is the code I used for wxMax and MiniB3D:SuperStrict Framework wx.wxApp Import wx.wxFrame Import wx.wxPanel Import wx.wxGLCanvas Import sidesign.minib3d Global Cube:TMesh Global old_ms:Int=MilliSecs() Global renders:Int Global fps:Int Global prog:MyApp = New MyApp prog.Run() Type MyApp Extends wxAppMain Field frame:wxFrame Field panel:wxPanel Field canvas:TMiniB3D Global shouldExit:Int = False Method OnInit:Int() frame = New wxFrame.Create(,,"MiniB3d Sample", 0, 0, 512, 512) frame.Center() panel = New wxPanel.Create(frame, wxID_ANY, 0, 0, 512, 512) canvas = TMiniB3D(New TMiniB3D.Create(panel, wxID_ANY, GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER, 0, 0, 512, 512)) frame.show() Return True End Method Method MainLoop:Int() While True While Not Pending() And ProcessIdle() ; Wend While Pending() If Not Dispatch() Then shouldExit = True Exit End If Wend If shouldExit Then While pending() dispatch() Wend Return 0 End If TurnEntity cube, 0, 1, 0 RenderWorld renders=renders+1 If MilliSecs()-old_ms>=1000 old_ms=MilliSecs() fps=renders renders=0 EndIf Text 0, 0, "FPS: "+fps Flip Wend EndMethod End Type Type TMiniB3D Extends wxGLCanvas Field init:Int = 0 Method OnPaint(event:wxPaintEvent) If init = 0 Then SetGraphics CanvasGraphics( Self ) TGlobal.width = 512 TGlobal.height = 512 TGlobal.depth = 16 TGlobal.mode = 0 TGlobal.GraphicsInit() init = 1 Local Camera:TCamera = CreateCamera() PositionEntity Camera, 0, 0, -10 Local Light:TLight = CreateLight(1) cube:TMesh=CreateCube() Local sphere:TMesh=CreateSphere() Local cylinder:TMesh=CreateCylinder() Local cone:TMesh=CreateCone() PositionEntity cube,-6,0,0 PositionEntity sphere,-2,0,0 PositionEntity cylinder,2,0,0 PositionEntity cone,6,0,0 RenderWorld End If End Method End Type It shouldn't be too hard to swap out MiniB3D with the Irrlitcht Wrapper. |
| ||
I've had a look and the problem is SetGraphics CanvasGraphics( Self ) , irrlicht doesn't have a similar function. All I can find is ib3d_Graphics3DParams( params :SIrrlichtCreationParameters ) and then creating params with setWindowId(hwnd:Int) but wxmax using Self.GetHandle() gives window hwnd as byte ptr so that was a dead end too. I also tryed Self.GetID() but that resulted in all irrlicht objects returning null so can't of been correct. I found an example of irrlicht working with maxgui and tested and it works perfectly: ' this is an example showing how to display Irrlicht in a panel on a MaxGUI form. i have modified it a bit ' by adding an eventreceiver to the Irrlicht instance to show how MaxGUI and Irrlicht events can coexist. ' it is important to note that there still is probably some issues to work out, but for now this works. ' ' NOTE: press the 'w' key to toggle wireframe Strict Framework Irrlicht.Core Import brl.eventqueue Import BRL.Basic Import maxgui.maxgui Import maxgui.win32maxguiex Local window:TGadget Local panel:TGadget Local windowWidth:Int = 640 Local windowHeight:Int = 380 window=CreateWindow("Irrlicht Win32 BlitzMax window example",100,100,windowWidth,windowHeight,Null,WINDOW_TITLEBAR | WINDOW_CLIENTCOORDS | WINDOW_HIDDEN) ' create window To put irrlicht in Local hIrrlichtWindow:TGadget=CreatePanel(50,80,320,220,window,PANEL_ACTIVE|PANEL_BORDER) Local HTMLWindow:TGadget=CreateHTMLView(380,80,250,220,window) ' create ok button Local Ok:TGadget=CreateButton("OK - Close",windowWidth - 160,windowHeight - 40,150,30,window) Local go:TGadget=CreateButton("GO URL",windowWidth - 320,windowHeight - 40,150,30,window) ' this is not in the original, but is here to show you can have a textbox and enter into it ' without the events posting to Irrlicht Local tb:TGadget=CreateTextField(windowWidth - 260,windowHeight - 70,250,20,window) ' create some text CreateLabel("This is Irrlicht running inside a Win32 MaxGUI window.",20,20,400,40,window) Local param:SIrrlichtCreationParameters=SIrrlichtCreationParameters.create() param.setWindowId(QueryGadget(hIrrlichtWindow,QUERY_HWND)) param.setDriverType(EDT_OPENGL) ' create the device from the params object Local device:IrrlichtDevice= .. IrrlichtDevice.createFromParams(param) ' the original does not have this. this is just to show that you can mix events between MaxGUI and Irrlicht. Type MyEventReceiver Extends IEventReceiver Field box:ISceneNode Method setBox(b:ISceneNode) box=b EndMethod Method OnEvent:Int(event:SEvent) ' check If user presses the key 'W' If event.getEventType()=EET_KEY_INPUT_EVENT And event.getKeyPressedDown()=False Local key:Int=event.getKeyInputKey() Select key ' switch wire frame mode Case EKEY_KEY_W box.setMaterialFlag(EMF_WIREFRAME, box.getMaterial(0).getWireframe()=False) Return True EndSelect EndIf Return False EndMethod ' we must override the generate function in order for instantiation to work properly ' must return IEventReceiver Function generate:IEventReceiver() Return New MyEventReceiver EndFunction EndType ' setup a simple 3d scene Local smgr:ISceneManager=device.getSceneManager() Local Driver:IVideoDriver=device.getVideoDriver() Local cam:ICameraSceneNode=smgr.addCameraSceneNode(); cam.setTarget(_VECTOR3DF(0,0,0)) Local anim:ISceneNodeAnimator=smgr.createFlyCircleAnimator(_VECTOR3DF(0,10,0),30.0) cam.addAnimator(anim) anim.drop() Local cube:ISceneNode=smgr.addCubeSceneNode(25) cube.setMaterialTexture(0,Driver.getTexture("../media/rockwall.bmp")) cube.setMaterialFlag(EMF_LIGHTING,False) smgr.addSkyBoxSceneNode( .. Driver.getTexture("../media/irrlicht2_up.jpg"), .. Driver.getTexture("../media/irrlicht2_dn.jpg"), .. Driver.getTexture("../media/irrlicht2_lf.jpg"), .. Driver.getTexture("../media/irrlicht2_rt.jpg"), .. Driver.getTexture("../media/irrlicht2_ft.jpg"), .. Driver.getTexture("../media/irrlicht2_bk.jpg")) ' create the event receiver that toggles wireframe Local receiver:IEventReceiver=IEventReceiver.create(MyEventReceiver.generate) MyEventReceiver(receiver).setBox(cube) device.setEventReceiver(receiver) ' show And execute dialog ShowGadget(window) ' do message queue ' Instead of this, you can also simply use your own message loop ' using GetMessage, DispatchMessage And whatever. Calling ' Device->run() will cause Irrlicht To dispatch messages internally too. ' You need Not call Device->run() If you want To do your own message ' dispatching loop, but Irrlicht will Not be able To fetch ' user Input Then And you have To do it on your own using the BlitzMax ' event mechanism. While(device.run()) Driver.beginScene(True, True) smgr.drawAll() Driver.endScene() If PeekEvent() Then PollEvent() Select EventID() Case EVENT_WINDOWCLOSE Exit Case EVENT_GADGETACTION If EventSource()=Ok PostEvent(CreateEvent(EVENT_WINDOWCLOSE,Ok)) ElseIf EventSource()=go Local url:String If GadgetText(tb)<>"" Then url=GadgetText(tb) Else url="http://www.blitzmax.com" HtmlViewGo( HTMLWindow,url ) ElseIf EventSource()=tb 'Print "textbox" Else ' pass it on to Irrlicht ' you would need to determine the event and pass it on Local event:SEvent=SEvent.create() event.setEventType(EET_KEY_INPUT_EVENT) event.setKeyInputKey(EKEY_KEY_W) device.postEventFromUser(event) EndIf Default 'PostEvent(CreateEvent(EventID()),True) If EventID()=EVENT_KEYDOWN Local event:SEvent=SEvent.create() event.setEventType(EET_KEY_INPUT_EVENT) event.setKeyInputKey(EventData()) device.postEventFromUser(event) EndIf End Select End If Wend ' the alternative, own message dispatching loop without Device->run() would ' look like this: Rem While True If PeekEvent() Then PollEvent() Select EventID() Case EVENT_WINDOWCLOSE Exit Case EVENT_GADGETACTION If EventSource()=Ok PostEvent(CreateEvent(EVENT_WINDOWCLOSE,Ok)) End If End Select End If '// advance virtual time device.GetTimer().Tick() '// draw engine picture driver.beginScene(True, True, 0) smgr.drawAll() driver.endScene() Wend EndRem device.closeDevice() device.drop() This is my attempt to combine wxmax and irrlicht, it doesn't work. SuperStrict Framework wx.wxApp Import wx.wxFrame Import wx.wxTimer Import wx.wxPanel Import wx.wxglmax2D Import Irrlicht.Core Const Menu_Exit:Int = 100 New Window.run() Type Window Extends wxApp Field Frame:WinFrame Method OnInit:Int() Frame = WinFrame(New WinFrame.Create(Null, -1, "Terrain Editor", , , 800, 600)) Frame.show(True) SetTopWindow(Frame) Return True End Method End Type Type WinFrame Extends wxFrame Field Canvas:WinCanvas Method OnInit() Local FileMenu:wxMenu = wxMenu.CreateMenu() Local MenuBar:wxMenuBar = wxMenuBar.CreateMenuBar() Local Panel:wxPanel = New wxPanel.Create( Self ) Canvas = WinCanvas(New WinCanvas.Create(Panel, -1, GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER,0,0,800,600)) ConnectAny(wxEVT_CLOSE, OnClose) FileMenu.Append(Menu_Exit, "Exit~tAlt-X", "Quit this program") MenuBar.Append(FileMenu, "&File") SetMenuBar(MenuBar) CreateStatusBar(1) SetStatusText("Terrain Editor") End Method Function OnClose(event:wxEvent) WinFrame(event.parent).Canvas.timer.Stop() event.Skip() End Function End Type Type WinCanvas Extends wxGLCanvas Field Timer:wxTimer Field Driver:IVideoDriver Field smgr:ISceneManager Field device:IrrlichtDevice Method OnInit() SetBackgroundStyle(wxBG_STYLE_CUSTOM) Timer = New wxTimer.Create(Self) ConnectAny(wxEVT_TIMER, OnTick) Timer.Start(17) ' ********** Local width:Int, height:Int GetSize(width , height) Local param:SIrrlichtCreationParameters=SIrrlichtCreationParameters.Create() param.setWindowId(Self.GetID()) param.setDriverType(EDT_OPENGL) ' setup a simple 3d scene device:IrrlichtDevice= .. IrrlichtDevice.createFromParams(param) smgr:ISceneManager=device.getSceneManager() Driver:IVideoDriver=device.getVideoDriver() Local cam:ICameraSceneNode=smgr.addCameraSceneNode(); cam.setTarget(_VECTOR3DF(0,0,0)) Local anim:ISceneNodeAnimator=smgr.createFlyCircleAnimator(_VECTOR3DF(0,10,0),30.0) cam.addAnimator(anim) anim.drop() Local cube:ISceneNode=smgr.addCubeSceneNode(25) cube.setMaterialTexture(0,Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/rockwall.bmp")) cube.setMaterialFlag(EMF_LIGHTING,False) smgr.addSkyBoxSceneNode( .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/irrlicht2_up.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/irrlicht2_dn.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/irrlicht2_lf.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/irrlicht2_rt.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/irrlicht2_ft.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/irrlicht2_bk.jpg")) End Method Method OnPaint(event:wxPaintEvent) Render() End Method Method Render() Driver.beginScene(True, True) smgr.drawAll() Driver.endScene() End Method Function OnTick(event:wxEvent) wxWindow(event.parent).Refresh() End Function End Type |
| ||
What's the error that you get? |
| ||
Using param.setWindowId(Self.GetID()) resulted in all irrlicht objects returning null so can't of been correct. and using param.setWindowId(Self.GetHandle()) gives cannot convert byte ptr into int |
| ||
param.setWindowId(Int(Self.GetHandle())) Does that do the trick? |
| ||
It fixed one problem, it now outputs the scene to the window, except now there is another problem it wont load the textures properly. It loads the texture and returns true BUT it just displays white. It must be something todo with the wxGLCanvas because the exact same code works fine with maxgui but fails when loaded into a canvas. New Code: SuperStrict Framework wx.wxApp Import wx.wxFrame Import wx.wxTimer Import wx.wxPanel Import WX.wxglmax2D Import Irrlicht.Core Const Menu_Exit:Int = 100 New Window.run() Type Window Extends wxApp Field Frame:WinFrame Method OnInit:Int() Frame = WinFrame(New WinFrame.Create(Null, -1, "Terrain Editor", , , 800, 600)) Frame.show(True) SetTopWindow(Frame) Return True End Method End Type Type WinFrame Extends wxFrame Field Canvas:WinCanvas Method OnInit() Local FileMenu:wxMenu = wxMenu.CreateMenu() Local MenuBar:wxMenuBar = wxMenuBar.CreateMenuBar() Local Panel:wxPanel = New wxPanel.Create( Self ) Canvas = WinCanvas(New WinCanvas.Create(Panel, -1, GRAPHICS_BACKBUFFER|GRAPHICS_DEPTHBUFFER,0,0,800,600)) ConnectAny(wxEVT_CLOSE, OnClose) FileMenu.Append(Menu_Exit, "Exit~tAlt-X", "Quit this program") MenuBar.Append(FileMenu, "&File") SetMenuBar(MenuBar) CreateStatusBar(1) SetStatusText("Terrain Editor") End Method Function OnClose(event:wxEvent) WinFrame(event.parent).Canvas.timer.Stop() event.Skip() End Function End Type Type WinCanvas Extends wxGLCanvas Field Timer:wxTimer Field Driver:IVideoDriver Field smgr:ISceneManager Field device:IrrlichtDevice Field tex:ITexture Method OnInit() 'SetBackgroundStyle(wxBG_STYLE_CUSTOM) Timer = New wxTimer.Create(Self) ConnectAny(wxEVT_TIMER, OnTick) Timer.Start(10) ' ********** Local width:Int, height:Int GetSize(width , height) Local param:SIrrlichtCreationParameters=SIrrlichtCreationParameters.Create() param.setWindowId(Int(Self.GetHandle())) param.setDriverType(EDT_OPENGL) ' setup a simple 3d scene device:IrrlichtDevice= .. IrrlichtDevice.createFromParams(param) smgr:ISceneManager=device.getSceneManager() Driver:IVideoDriver=device.getVideoDriver() Local cam:ICameraSceneNode=smgr.addCameraSceneNode(); cam.setTarget(_VECTOR3DF(0,0,0)) Local anim:ISceneNodeAnimator=smgr.createFlyCircleAnimator(_VECTOR3DF(0,10,0),30.0) cam.addAnimator(anim) anim.drop() Local cube:ISceneNode = smgr.addCubeSceneNode(25) 'tex = Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/irrlicht2_up.jpg") tex = Driver.getTexture("Z:\new.bmp") Print cube.setMaterialTexture(1,tex) Print cube.setMaterialFlag(EMF_LIGHTING , False) Print cube.getmaterialcount() Print Driver.getTextureCount() 'cube.render() smgr.addSkyBoxSceneNode( .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_up.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_dn.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_lf.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_rt.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_ft.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_bk.jpg")) 'SetGraphics CanvasGraphics2D( Self ) End Method Method OnPaint(event:wxPaintEvent) Render() End Method Method Render() device.run() Driver.beginScene(True , true) smgr.drawAll() Driver.endScene() End Method Function OnTick(event:wxEvent) 'Print "tick" wxWindow(event.parent).Refresh() End Function End Type |
| ||
Okay this is were I ended up finding something weird with wxMax. Using OnInit() method for the GLCanvas actually does not work entirely and you need to make your own Init thing within the OnPaint() method. I am not sure exactly why you need to do it like this, but this should do the trick: (I am running blind here since I don't have Irrlicht but if you still have issues after this, it should be fairly easy to hammer out).Type WinCanvas Extends wxGLCanvas Field Timer:wxTimer Field Driver:IVideoDriver Field smgr:ISceneManager Field device:IrrlichtDevice Field tex:ITexture Field Init:Int = 0 Method OnPaint(event:wxPaintEvent) If Init = 0 Then 'SetBackgroundStyle(wxBG_STYLE_CUSTOM) Timer = New wxTimer.Create(Self) ConnectAny(wxEVT_TIMER, OnTick) Timer.Start(10) ' ********** Local width:Int, height:Int GetSize(width , height) Local param:SIrrlichtCreationParameters=SIrrlichtCreationParameters.Create() param.setWindowId(Int(Self.GetHandle())) param.setDriverType(EDT_OPENGL) ' setup a simple 3d scene device:IrrlichtDevice= .. IrrlichtDevice.createFromParams(param) smgr:ISceneManager=device.getSceneManager() Driver:IVideoDriver=device.getVideoDriver() Local cam:ICameraSceneNode=smgr.addCameraSceneNode(); cam.setTarget(_VECTOR3DF(0,0,0)) Local anim:ISceneNodeAnimator=smgr.createFlyCircleAnimator(_VECTOR3DF(0,10,0),30.0) cam.addAnimator(anim) anim.drop() Local cube:ISceneNode = smgr.addCubeSceneNode(25) 'tex = Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples\media/irrlicht2_up.jpg") tex = Driver.getTexture("Z:\new.bmp") Print cube.setMaterialTexture(1,tex) Print cube.setMaterialFlag(EMF_LIGHTING , False) Print cube.getmaterialcount() Print Driver.getTextureCount() 'cube.render() smgr.addSkyBoxSceneNode( .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_up.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_dn.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_lf.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_rt.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_ft.jpg"), .. Driver.getTexture("C:\Program Files (x86)\Blitzmax-SVN\mod\irrlicht.mod\examples/media/irrlicht2_bk.jpg")) 'SetGraphics CanvasGraphics( Self ) '!!!!!!!!!!!!!!!!!!!!!!!YOU MIGHT HAVE TO UNCOMMENT THAT!!!!!!!!!!!!!!!!!!!!!!!!!!!' Init = 1 EndIf device.run() Driver.beginScene(True , True) smgr.drawAll() Driver.endScene() End Method Function OnTick(event:wxEvent) 'Print "tick" wxWindow(event.parent).Refresh() End Function End Type Just copy that whole type over your old GLCanvas type and hopefully it will work for you Last edited 2012 |
| ||
Hey I realized I totally spaced and forgot Init = 1 so it doesn't run through it again xD Code above is fixed |
| ||
I tried your code and got some very interesting results. With Init = 1 in, it was exactly the same as before, no textures. But when init = 1 wasn't in, when it reloaded the whole engine and textures for every frame, it displayed correctly, well apart from it being really slow and the animation resetting every frame. So this leads me to believe either wxmax or irrlicht is cleaning up the textures after the first frame, does anyone have an idea about what could be causing this? |