Irrlicht and Newton

BlitzMax Forums/BlitzMax Programming/Irrlicht and Newton

Pretty neat, eh?

'my second newton physics test
'using newton collision trees

Framework BRL.Blitz          'core module
Import BRL.Random            'random number generator.
Import Pub.NewtonAndIrrlicht 'Imports Newton, Irrlicht, and some
                             'nice interface functions


Print "HELLO WORLD!!!"

ms=MilliSecs()
SeedRnd ms 'randomize seed based on the system timer -- the best way to get
           'the most random results.
Print "Seeded random number generator with system clock. ("+ms+")"

'irrlicht pointers
Global dvc:IrrlichtDevice      'the core irrlicht device class
Global dvr:IVideoDriver        'the video driver class
Global sne:ISceneManager       'the scene manager class
Global msm:IMeshManipulator    'the mesh manipulator class
Global csr:ICursorControl      'the cursor manipulator class
Global rcv:SmoothEventReceiver 'the input event receiver

'newton pointers and matricies
Global boxlist:TList
Global collision:Byte Ptr
Global boxcollision:Byte Ptr

'create irrlicht context
DebugCreateIrrlicht False,True,fullScn,rAccel,dvc,dvr,sne,rcv
msm=sne.getMeshManipulator()
csr=dvc.getCursorControl()
dvc.SetResizeable True
Print "Successfully created Irrlicht Device context."

Global font:IGUIFont=dvc.getGUIEnvironment().getFont("fontcourier.bmp")
Print "Successfully generated font."

dvr.beginScene True,True
	font.draw "LOADING...",_RECTI(3,3,300,50),_SCOLOR(255,255,255,255)
dvr.endScene()

'create skybox
If rAccel Then
	sne.addSkyBoxSceneNode( ..
	 dvr.getTexture("up.jpg"), ..
	  dvr.getTexture("down.jpg"), ..
	   dvr.getTexture("left.jpg"), ..
	    dvr.getTexture("right.jpg"), ..
	     dvr.getTexture("back.jpg"), ..
	      dvr.getTexture("front.jpg"))
End If
Print "Successfully added skybox."

'create scene camera (viewpoint)
Global cam:ICameraSceneNode=sne.addCameraSceneNodeFPS(Null,92,64,64)
cam.setPosition(_VECTOR3DF(0,20,-10))
Print "Successfully added camera."

'add a light source
sne.addLightSceneNode(Null,_VECTOR3DF(0,50,0))
Print "Successfully added light source."

'attach the newton api lib
If Not StartNewton() Then
	Print "Could not attach dynamics engine API."
	Notify "Could not attach dynamics engine API.",True
	End
End If
Print "Successfully attached dynamics engine API!"

'create a newton world using custom memory handlers by pointing
'to the functions; null argument selects standard memory handlers
Global world:Byte Ptr=NewtonCreate(MemAllocate,MemRelease)
NewtonSetMinimumFrameRate world,500
sim_gravity=9800 'scale up 1000 from 9.8 meter/sec^2

'Set the solver and friction models to perfect.  All calculations are resolved as
'many times as is neccessary to eliminate all drift errors before iterating.  Slower
'but much more accurate.
NewtonSetSolverModel world,0
NewtonSetFrictionModel world,0


Print "Successfully generated dynamics world!"

'load a mesh for the collision tree
Global amesh:IAnimatedMesh=sne.getMesh("testlevel.b3d")
Global mesh:IMesh=amesh.getMesh(0)
msm.ScaleMesh(mesh,_VECTOR3DF(10,10,10))
Global meshnode:ISceneNode=sne.addMeshSceneNode(mesh)
'meshnode.setScale _VECTOR3DF(10,10,10)

Local meshcollision:Byte Ptr=NewtonCreateTreeCollision(world,Null)
Local meshbody:Byte Ptr=MeshToNewtonCollisionTree(world,mesh,meshcollision,True)
Local meshmat#[16]

'Local wmn#[3]
'Local wmx#[3]
'NewtonBodyGetMatrix meshbody,Varptr mat[0]
'NewtonCollisionCalculateAABB meshcollision,Varptr mat[0],Varptr wmn[0],Varptr wmx[0]
'wmx[2]:+200
'NewtonSetWorldSize world,Varptr wmn[0],Varptr wmx[0]

NewtonBodySetUserData meshbody,Byte Ptr(meshnode.handle)
NewtonBodySetDestructorCallback meshbody,BodyDestructor
GetEulerMatrix meshnode,meshmat
NewtonBodySetMatrix meshbody,Varptr meshmat[0]
NewtonReleaseCollision world,meshcollision
Print "Successfully added geo-collision tree."

'Print "Successfully generated cube collision object."
Global boxmesh:IMesh=sne.getMesh("smallcube.3ds").getMesh(0)
msm.ScaleMesh(boxmesh,_VECTOR3DF(.1,.1,.1))
Global tex:ITexture=dvr.getTexture("wall.jpg")
'boxcollision=NewtonCreateTreeCollision(world,Null)
'MeshToNewtonCollisionTree world,boxmesh,boxcollision,False,False
boxcollision=NewtonCreateBox(world,4,4,4,Null)

csr.setVisible False
'okay, here we go
WriteStdout "Begin simulation..."
fps=0
str$=""
timestep!=0''Local intMat[16]
msdn=False

Repeat
	If rcv.IsMouseButtonDown(0) And Not msdn Then
		AddBox
		msdn=True
	Else If Not rcv.IsMouseButtonDown(0) And msdn=True
		msdn=False
	End If
	If rcv.IsKeyDownUp(EKEY_ESCAPE) Then dvc.closeDevice()
	
	'update world euler matrix
	timestep=NewtonGetTimeStep(world)
	NewtonUpdate world,timestep
	
	NodeDestructor 'destroy the deleted/released nodes
	
	dvr.beginScene True,True
		sne.drawAll() 'draw scene
		
		'draw general data
		fps=dvr.getFPS()
		str="renderer ~q"
		 str:+dvr.getName()+"~q   physics ~qNewton Dynamics v"
		  str:+NewtonWorldGetVersion(world)+"~q   "
		   str:+"FPS = "+fps+"   TimeStep = "+timestep
		font.draw str,_RECTI(5,5,300,50),_SCOLOR(255,0,0,0)
		str="renderer ~q"
		 str:+dvr.getName()+"~q   physics ~qNewton Dynamics v"
		  str:+NewtonWorldGetVersion(world)+"~q   "
		   str:+"FPS = "+fps+"   TimeStep = "+timestep
		font.draw str,_RECTI(3,3,300,50),_SCOLOR(255,255,255,64)
		
		'draw debug data
		curralloced=GCMemAlloced()
		font.draw "CoreMem="+(curralloced/1024)+"KB   "+..
		 "SimMem="+(nMemSize/1024)+..
		  "KB   TotalMem="+((curralloced+nMemSize)/1024)+..
		   "KB   Note: Irrlicht uses a seperate memory system.",..
		    _RECTI(5,21,300,50),_SCOLOR(255,0,0,0)
		font.draw "CoreMem="+(curralloced/1024)+"KB   "+..
		 "SimMem="+(nMemSize/1024)+..
		  "KB   TotalMem="+((curralloced+nMemSize)/1024)+..
		   "KB   Note: Irrlicht uses a seperate memory system.",..
		    _RECTI(3,19,300,50),_SCOLOR(255,255,255,64)
	dvr.endScene()
	
	GCCollect
Until Not dvc.run()
Print "ended properly."

'now we clean up
NewtonReleaseCollision world,boxcollision
NewtonDestroyAllBodies world 'destroy all bodies in dynamics world
Print "Successfully destroyed all physical bodies."
NewtonDestroy world 'destroy dynamics world
Print "Successfully destroyed dynamics world."
NodeDestructor
Print "Successfully destroyed scene nodes."
ReleaseIrrlicht dvc 'release irrlicht context
Print "Successfully released Irrlicht Device context."
StopNewton 'drop newton api
Print "Successfully dropped dynamics engine API."

End

Function AddBox:Byte Ptr()
	Local boxnode:ISceneNode
	Local box:Byte Ptr
	boxnode=sne.addMeshSceneNode(boxmesh)
	boxnode.setPosition(cam.getPosition())
	boxnode.setMaterialFlag EMF_LIGHTING,True
	boxnode.setMaterialTexture(0,tex)
	GCCollect
	
	GetEulerMatrix boxnode,mat
	box=NewtonCreateBody(world,boxcollision)
	NewtonBodySetMassMatrix box,1#,1#,1#,1#
	NewtonBodySetMatrix box,Varptr mat[0]
	omega=[Float(Rnd(-10,10)),Float(Rnd(-10,10)),Float(Rnd(-10,10))]
	NewtonBodySetOmega box,Varptr omega[0]
	NewtonBodySetAutoFreeze box,1
	NewtonBodySetUserData box,Byte Ptr(boxnode.handle)
	NewtonBodySetDestructorCallback box,BodyDestructor
	NewtonBodySetTransformCallback box,NSetTransform
	NewtonBodySetForceAndTorqueCallback box,ApplyForceAndTorque
	GCCollect
	
	Return box
End Function


Pub.NewtonAndIrrlicht:
Rem
bbdoc: Irrlicht and Newton Integration Helper
End Rem
Module Pub.NewtonAndIrrlicht
ModuleInfo "Author: Bill Whitacre (ninjarat), GMan"
ModuleInfo "History: Added functions used in Newton Examples and converted to Irrlicht graphics."

Import BRL.LinkedList
Import Pub.Newton
Import Irrlicht.Extended

Global nMemSize,nNodeDestroyList:TList=New TList
Global mat#[16]
Global omega#[3]
Global sim_gravity#=9.8

'Excellent Euler Matrix converter functions.  Not by me, and I would give credit where
'it was called for, except I honestly don't know who did this.
Function GetEulerMatrix(NSceneNode:ISceneNode,NewtonMat#[])
	Local Euler#[3]
	Euler[0]=NSceneNode.getRotation().getX()*(Pi/180#)
	Euler[1]=NSceneNode.getRotation().getY()*(Pi/180#)
	Euler[2]=NSceneNode.getRotation().getZ()*(Pi/180#)
	NewtonSetEulerAngle(Varptr Euler[0],Varptr NewtonMat[0])
	
	NewtonMat[12]=NSceneNode.getPosition().getX()
	NewtonMat[13]=NSceneNode.getPosition().getY()
	NewtonMat[14]=NSceneNode.getPosition().getZ()
End Function
Function SetEulerMatrix(NSceneNode:ISceneNode,NewtonMat#[])
	Local Euler#[3]
	NewtonGetEulerAngle(Varptr NewtonMat[0],Varptr Euler[0])
	NSceneNode.setPosition _VECTOR3DF(NewtonMat[12],NewtonMat[13],NewtonMat[14])
	NSceneNode.setRotation _VECTOR3DF(Euler[0]*(180/Pi),Euler[1]*(180/Pi),Euler[2]*(180/Pi))
End Function
'pointer edition euler matrix functions
Function GetEulerMatrix2(NSceneNode:ISceneNode,NewtonMat:Float Ptr)
	Local Euler#[3]
	Euler[0]=NSceneNode.getRotation().getX()*(Pi/180)
	Euler[1]=NSceneNode.getRotation().getY()*(Pi/180)
	Euler[2]=NSceneNode.getRotation().getZ()*(Pi/180)
	NewtonSetEulerAngle Varptr Euler[0],Varptr newtonMat[0]
	Newtonmat[12]=NSceneNode.getPosition().getX()
	newtonMat[13]=NSceneNode.getPosition().getY()
	NewtonMat[14]=NSceneNode.getPosition().getZ()	
End Function
Function SetEulerMatrix2(NSceneNode:ISceneNode,NewtonMat:Float Ptr)
	Local Euler#[3]
	NewtonGetEulerAngle Varptr NewtonMat[0],Varptr Euler[0]
	NSceneNode.setPosition _VECTOR3DF(NewtonMat[12],NewtonMat[13],NewtonMat[14])
	NSceneNode.setRotation _VECTOR3DF(Euler[0]*(180/Pi),Euler[1]*(180/Pi),Euler[2]*(180/Pi))
End Function

'These override Newton's local memory functions with native function wrappers.
Function MemAllocate:Byte Ptr(size:Int)
?Debug
	origMemSize=nMemSize
?
	nMemSize:+size
?Debug
	Print "Allocated "+size+"Bytes memory on top of "+origMemSize+" for sim.  nNewMemSize="+nMemSize
	origMemSize=Null
?
	GCCollect

	Return MemAlloc(size)
End Function
Function MemRelease(memptr:Byte Ptr,size:Int)
?Debug
	origMemSize=nMemSize
?
	nMemSize:-size
	MemClear memptr,size
	MemFree memptr
?Debug
	Print "Released "+size+"/"+origMemSize+"Bytes memory for sim.  nNewMemSize="+nMemSize
	origMemSize=Null
?
	GCCollect
End Function

'body event callbacks
Function  ApplyForceAndTorque(Body:Byte Ptr) 'gravity callback
	Local mass#,Ixx#,Iyy#,Izz#
	NewtonBodyGetMassMatrix(body,Varptr mass, Varptr Ixx, Varptr Iyy, Varptr Izz)
	Local force#[]=[0#,Iyy*mass*-sim_gravity,0#]
	NewtonBodySetForce body,Varptr force[0]
End Function
Function  NSetTransform(body:Byte Ptr,NewtonMat# Ptr) 'the N prefix is because the
                                           'set transform function is already used
                                             'by this language for something else.
	Local node:ISceneNode
	node=ISceneNode.CreateFromHandle(Int(newtonBodyGetUserData(body)),False)
	
	newtonBodyGetMatrix body,Varptr NewtonMat[0]
	SetEulerMatrix2 node,Varptr NewtonMat[0]
End Function
Function BodyLeftWorld(body:Byte Ptr) 'What do we do if we've gone off the edge of the
                                      'world?  Answer: We get dropped back in.
	Local node:ISceneNode=ISceneNode.CreateFromHandle(Int(newtonBodyGetUserData(body)),False)
	node.setPosition _VECTOR3DF(Rnd(-1#,1#),Rnd(9#,12#),Rnd(-1#,1#))
	GetEulerMatrix node,mat
	
	NewtonBodySetMatrix body,Varptr mat[0]
End Function
Function BodyDestructor(body:Byte Ptr) 'if a physical body is destroyed, we add it's
                                       'graphics node to the destructor list.
	Local NodeHandle:Int
	
	NodeHandle=Int(newtonBodyGetUserData(body))
	nNodeDestroyList.AddLast NodeHandle
End Function

'Destructor for the released scene nodes.  Call every time any node(s) is destroyed.
Function NodeDestructor()
	If nNodeDestroyList.Count()>0 Then
		Local tempNode:ISceneNode
		Local objarr:Object[]=ListToArray(nNodeDestroyList)
		Local intarr[objarr.length]
		For j=0 To objarr.length-1
			intarr[j]=objarr[j]
		Next
		For del=EachIn intarr
			tempNode=ISceneNode.CreateFromHandle(del,False)
			tempNode.remove
		Next
		nNodeDestroyList=New TList;tempNode=Null;objarr=Null;intarr=Null
		GCCollect
	End If
End Function

'Fixed by gman.  That guy's showing up in the credits for sure.  Thank you G!
Function AnimatedMeshToNewtonCollisionTree:Byte Ptr(world:Byte Ptr,map:IAnimatedMesh,newtonMap:Byte Ptr,createbox=True,createbody=True)
	NewtonTreeCollisionBeginBuild(newtonmap)
	Local cMeshBuffer,j
	Local mb:IMeshBuffer
	
	Local vArray#[9]	'vertex array (3*3 floats)
	For cMeshBuffer=0 To map.getMesh(0).getMeshBufferCount() - 1
		mb = map.getMesh(0).getMeshBuffer(cMeshBuffer)
		Local vertType=mb.getVertexType()
		Local arr_standardVerts:Array_S3DVertex=Null
		Local arr_2TCoordVerts:Array_S3DVertex2TCoords=Null
		Local arr_TangentVerts:Array_S3DVertexTangents=Null

		If vertType=EVT_STANDARD
			arr_standardVerts=mb.getVertices()
		Else If vertType=EVT_2TCOORDS
			arr_2TCoordVerts=mb.getVertices2TCoords()
		Else If vertType=EVT_TANGENTS
			arr_TangentVerts=mb.getVerticesTangents()
		EndIf
		
		Local mb_indices:Array_u16=mb.getIndices()
		
		'add each triangle from the mesh
		For j=0 To mb.getIndexCount() - 1 Step 3
			v1i=mb_indices.elementAt(j)[0]
			v2i=mb_indices.elementAt(j+1)[0]
			v3i=mb_indices.elementAt(j+2)[0]

			Local v1:Vertex=Null
			Local v2:Vertex=Null
			Local v3:Vertex=Null
			
			If vertType=EVT_STANDARD Then
				v1=Vertex(arr_standardVerts.elementAt(v1i))
				v2=Vertex(arr_standardVerts.elementAt(v2i))
				v3=Vertex(arr_standardVerts.elementAt(v3i))
			Else If vertType=EVT_2TCOORDS Then
				v1=Vertex(arr_2TCoordVerts.elementAt(v1i))
				v2=Vertex(arr_2TCoordVerts.elementAt(v2i))
				v3=Vertex(arr_2TCoordVerts.elementAt(v3i))
			Else If vertType=EVT_TANGENTS Then
				v1=Vertex(arr_tangentVerts.elementAt(v1i))
				v2=Vertex(arr_tangentVerts.elementAt(v2i))
				v3=Vertex(arr_tangentVerts.elementAt(v3i))
			EndIf
			
			vArray[0]=v1.getPos().getX()
			vArray[1]=v1.getPos().getY()
			vArray[2]=v1.getPos().getZ()
			vArray[3]=v2.getPos().getX()
			vArray[4]=v2.getPos().getY()
			vArray[5]=v2.getPos().getZ()
			vArray[6]=v3.getPos().getX()
			vArray[7]=v3.getPos().getY()
			vArray[8]=v3.getPos().getZ()
			
			NewtonTreeCollisionAddFace(newtonmap, 3,Varptr vArray[0], 12, j)
		Next
	Next
	NewtonTreeCollisionEndBuild(newtonmap,0)
	If createbody Then
		Local newtonmapbody:Byte Ptr=NewtonCreateBody(world,newtonmap)
		If createbox Then
			'set the newton world size based on the mesh size
			Local boxP0#[3] 
			Local boxP1#[3] 
			NewtonBodyGetMatrix newtonmapbody,Varptr mat[0]
			NewtonCollisionCalculateAABB newtonmap,Varptr mat[0],Varptr boxP0[0],Varptr boxP1[0]
			'pad the box
			boxP0[0]:-60
			boxP1[0]:+60
			boxP0[1]:-60
			boxP1[1]:+60
			boxP0[2]:-60
			boxP1[2]:+60
			NewtonSetWorldSize world,Varptr boxP0[0],Varptr boxP1[0]
		End If
		Return newtonmapbody
	End If
	
	Return Null
End Function
Function MeshToNewtonCollisionTree:Byte Ptr(world:Byte Ptr,map:IMesh,newtonMap:Byte Ptr,createbox=True,createbody=True)
	NewtonTreeCollisionBeginBuild(newtonmap)
	Local cMeshBuffer,j
	Local mb:IMeshBuffer
	
	Local vArray#[9]	'vertex array (3*3 floats)
	For cMeshBuffer=0 To map.getMeshBufferCount() - 1
		mb = map.getMeshBuffer(cMeshBuffer)
		Local vertType=mb.getVertexType()
		Local arr_standardVerts:Array_S3DVertex=Null
		Local arr_2TCoordVerts:Array_S3DVertex2TCoords=Null
		Local arr_TangentVerts:Array_S3DVertexTangents=Null

		If vertType=EVT_STANDARD
			arr_standardVerts=mb.getVertices()
		Else If vertType=EVT_2TCOORDS
			arr_2TCoordVerts=mb.getVertices2TCoords()
		Else If vertType=EVT_TANGENTS
			arr_TangentVerts=mb.getVerticesTangents()
		EndIf
		
		Local mb_indices:Array_u16=mb.getIndices()
		
		'add each triangle from the mesh
		For j=0 To mb.getIndexCount() - 1 Step 3
			v1i=mb_indices.elementAt(j)[0]
			v2i=mb_indices.elementAt(j+1)[0]
			v3i=mb_indices.elementAt(j+2)[0]

			Local v1:Vertex=Null
			Local v2:Vertex=Null
			Local v3:Vertex=Null
			
			If vertType=EVT_STANDARD Then
				v1=Vertex(arr_standardVerts.elementAt(v1i))
				v2=Vertex(arr_standardVerts.elementAt(v2i))
				v3=Vertex(arr_standardVerts.elementAt(v3i))
			Else If vertType=EVT_2TCOORDS Then
				v1=Vertex(arr_2TCoordVerts.elementAt(v1i))
				v2=Vertex(arr_2TCoordVerts.elementAt(v2i))
				v3=Vertex(arr_2TCoordVerts.elementAt(v3i))
			Else If vertType=EVT_TANGENTS Then
				v1=Vertex(arr_tangentVerts.elementAt(v1i))
				v2=Vertex(arr_tangentVerts.elementAt(v2i))
				v3=Vertex(arr_tangentVerts.elementAt(v3i))
			EndIf
			
			vArray[0]=v1.getPos().getX()
			vArray[1]=v1.getPos().getY()
			vArray[2]=v1.getPos().getZ()
			vArray[3]=v2.getPos().getX()
			vArray[4]=v2.getPos().getY()
			vArray[5]=v2.getPos().getZ()
			vArray[6]=v3.getPos().getX()
			vArray[7]=v3.getPos().getY()
			vArray[8]=v3.getPos().getZ()
			
			NewtonTreeCollisionAddFace(newtonmap,3,Varptr vArray[0],12,j)
		Next
	Next
	NewtonTreeCollisionEndBuild(newtonmap,0)
	
	If createbody Then
		Local newtonmapbody:Byte Ptr=NewtonCreateBody(world,newtonmap)
		If createbox Then
			'set the newton world size based on the mesh size
			Local boxP0#[3] 
			Local boxP1#[3] 
			NewtonBodyGetMatrix newtonmapbody,Varptr mat[0]
			NewtonCollisionCalculateAABB newtonmap,Varptr mat[0],Varptr boxP0[0],Varptr boxP1[0]
			'pad the box
			boxP0[0]:-80
			boxP1[0]:+80
			boxP0[1]:-80
			boxP1[1]:+80
			boxP0[2]:-80
			boxP1[2]:+80
			NewtonSetWorldSize world,Varptr boxP0[0],Varptr boxP1[0]
		End If
		Return newtonmapbody
	End If
	
	Return Null
End Function


Irrlicht.Extended:
Module Irrlicht.Extended

Import Irrlicht.AddOns
Import BRL.System
Private
	OnEnd byebye
	Function byebye()
		Print "Goodbye."
	End Function
	
	Global eventrcv:SmoothEventReceiver=SmoothEventReceiver.createReceiver()
Public

Function DebugCreateIrrlicht(stencil,vsync,fullScn% Var,rAccel% Var,dvc:IrrlichtDevice Var,dvr:IVideoDriver Var,sne:ISceneManager Var,rcv:SmoothEventReceiver Var)
	fsn=Confirm("Run in fullscreen?")
	rac=Confirm("Click OK to use HW Driven rendering acceleration.  If you~n~r"+..
	 "don't, a software renderer will be used instead.")
	If rac Then
		Select Confirm("Default driver is Direct3D (v8.x to v9.x).  Use OpenGL(1.x.x) instead?")
			Case True CreateIrrlicht EDT_OPENGL,640,480,16,fsn,stencil,vsync,dvc,dvr,sne,eventrcv
		Case False
			Select Confirm( ..
			 "Use Direct3D 9.0?  Cancel will default to older driver (Direct3D 8.1).~n~r"+..
			  "D3D 8.1 is not fully functional in the rendering techniques this program uses, so~n~r"+..
			   "rendering errors may occur.  Most commonly reported is the inexplicable failiure to~n~r"+..
			    "render seemingly random polygons on the sphere mesh primitives.  The physics~n~r"+..
			     "simulation is entirely independent of the renderer, so it should be the same regardless.")
				Case True CreateIrrlicht EDT_DIRECT3D9,640,480,16,fsn,stencil,vsync,dvc,dvr,sne,eventrcv
				Case False CreateIrrlicht EDT_DIRECT3D8,640,480,16,fsn,stencil,vsync,dvc,dvr,sne,eventrcv
			End Select
		End Select
	Else
		If Confirm("Use high quality software renderer?  WARNING: This will be VERY SLOW!") Then
			CreateIrrlicht EDT_SOFTWARE2,640,480,16,fsn,stencil,vsync,dvc,dvr,sne,eventrcv
		Else
			CreateIrrlicht EDT_SOFTWARE,640,480,16,fsn,stencil,vsync,dvc,dvr,sne,eventrcv
		End If
	End If
	fullScn=fsn
	rAccel=rac
	rcv=eventrcv
End Function

Function CreateIrrlicht(renderer,rezx,rezy,bits,fullscrn,stencil,vsync,DVC:IrrlichtDevice Var,DVR:IVideoDriver Var,SCN:ISceneManager Var,RCV:SmoothEventReceiver Var)
	DVC=IrrlichtDevice.create(..
	 renderer,_DIMENSION2DI(rezx,rezy),rezdepth,..
	  fullscrn,stencil,vsync,eventrcv)
	
	If DVC.handle=0 Then
		Print "Could not create 3D device!"
		Notify "Could not create 3D device!",True
		End
	Else
		Print "Created 3D device successfully!"
	End If
	
	DVR=DVC.getVideoDriver()
	SCN=DVC.getSceneManager()
	RCV=eventrcv
End Function

Function ReleaseIrrlicht(DVC:IrrlichtDevice)
	DVC.drop()
	DVC=Null
	If DVC Then
		Print "3D device was not released successfully!"
		Notify "3D device was not released successfully!",True
		End
	Else
		Print "3D device was released successfully!"
	End If
End Function