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? |