Irrlicht and Newton

BlitzMax Forums/BlitzMax Programming/Irrlicht and Newton

here is the example using the sydney model with the AnimatedMeshToCollisionTree function. you should be able to change the node at the top right before the initScene() function to test out other meshes. i did comment out the set the world size part of the AnimatedMeshToCollisionTree function. please note that different vertex types will cause problems with the function. i will see if i can whip up a more compatible function sometime tomorrow.
SuperStrict
Framework PUB.Newton
Import Irrlicht.Core
Import BRL.PNGLoader
StartNewton()

Local device:IrrlichtDevice = IrrlichtDevice.create(EDT_OPENGL , Dimension2di.create(640 , 480) , 16 , False , False , False , Null)
Global driver:IVideoDriver = device.getVideoDriver()
Global smgr:ISceneManager = device.getSceneManager() 
'Local Tex:ITexture = driver.getTexture("brlLogo.png")
Local camera:ICameraSceneNode = smgr.addCameraSceneNodeFPS()
camera.setPosition(Vector3df.createFromVals(-19,-49,-30))
camera.setRotation(Vector3df.createFromVals(0 , 0 , 0))
Local light:ILightSceneNode = smgr.addLightSceneNode( Null , Vector3df.createfromVals(-20 , -40 , -30))

Global nWorld:Byte Ptr = NewtonCreate(PhysicsAlloc , PhysicsFree)

' ------------------------------------
' new stuff
' ------------------------------------

' ------------------------------------
' TODO: edit this section for different meshes/nodes
' ------------------------------------
Global mesh:IAnimatedMesh=smgr.getMesh("sydney.md2")
Global node:IAnimatedMeshSceneNode=smgr.addAnimatedMeshSceneNode(mesh)
node.setAnimationSpeed(0)
node.setPosition(_VECTOR3DF(-25,-40,0))

' ------------------------------------
' setup node in newton
' ------------------------------------
Local meshcollision:Byte Ptr = NewtonCreateTreeCollision(nWorld, Null)
Local meshBody:Byte Ptr = AnimatedMeshToNewtonCollisionTree(nWorld, mesh, meshcollision)
Local MeshMat:Float[16]

NewtonBodySetUserData(meshBody,Byte Ptr(node.handle))
'// set a destrutor For this rigid body
NewtonBodySetDestructorCallback(meshBody, PhysicsBodyDestructor)
'// set the transformation For this rigid body
GetMatrix(node ,Varptr MeshMat[0])
NewtonBodySetMatrix(meshBody,Varptr MeshMat[0])
newtonReleaseCollision(nWorld , meshcollision)
' ------------------------------------
	
initScene()

' ------------------------------------

Local Timer:Int = MilliSecs()
While (device.run())
	Timer:+MilliSecs()
	NewtonUpdate(nWorld , 0.001)
	Timer = MilliSecs()
	'NewtonBodyGetMatrix(box , Varptr Mat[0])
	'SetMatrix(node , Mat)
	driver.beginScene(True , True , SColor.createFromVals(0,200 , 200 , 200))
	smgr.drawAll()
	
	driver.endScene()
Wend
StopNewton()

Rem '''''''''''''''''''''''''''''''''''/////////////////////////////////////   The Convertion Matrix Functions
		GetMatrix is the function to get the matrix from the Irrlecht SceneNode And pass it
	to an array to be used by Newton.
		SetMatrix is the function to pass the Matrix from Newton to the Irrlicht SceneNode
EndRem
Function GetMatrix(NSceneNode:ISceneNode , NewtonMat:Float Ptr)
	Local Euler:Float[3]
	Euler[0] = NSceneNode.getRotation().getX() * (Pi / 180.0)
	Euler[1] = NSceneNode.getRotation().getY() * (Pi / 180.0)
	Euler[2] = NSceneNode.getRotation().getZ() * (Pi / 180.0)
	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 SetMatrix(NSceneNode:ISceneNode , NewtonMat:Float Ptr)
	Local Euler:Float[3]
	NewtonGetEulerAngle(Varptr NewtonMat[0] , Varptr Euler[0])
	NSceneNode.setPosition(Vector3df.createFromVals(NewtonMat[12] , NewtonMat[13] , NewtonMat[14]))
	NSceneNode.setRotation(Vector3df.createfromVals(Euler[0] * (180 / Pi) , Euler[1] * (180 / Pi) , Euler[2] * (180 / Pi)))
End Function
Rem 
					THE FUNCTIONS FROM TUTORIAL 2
End Rem
Function	PhysicsAlloc:Byte Ptr(sizeInBytes:Int)
	Return MemAlloc(sizeInBytes)
End Function
Function    PhysicsFree( memptr:Byte Ptr, sizeInBytes:Int)
	MemFree (memptr)
End Function
' set the tranformation of a rigid body
Function  PhysicsApplyForceAndTorque (Body:Byte Ptr)
	Local mass:Float
	Local Ixx:Float
	Local Iyy:Float
	Local Izz:Float
	NewtonBodyGetMassMatrix (body,Varptr mass, Varptr Ixx, Varptr Iyy, Varptr Izz);
	'Local force:Float[] =  [0.0, -mass * 9.8 , 0.0]
	' GG: messed with the mass multiplier to make it look like the tutorial.  have no idea why this is different.
	Local force:Float[] =  [0.0, -mass * 410 , 0.0]
	NewtonBodySetForce (body, Varptr force[0])
End Function
Function  PhysicsSetTransform (body:Byte Ptr, NewtonMat:Float Ptr)
	Local primitive:ISceneNode
	'// get the graphic Object form the rigid body
	' GG: changed to recreate the scenenode based on the C++ object handle
	primitive = ISceneNode.CreateFromHandle(Int(newtonBodyGetUserData(body)),False)
		
	'// set the transformation matrix For this rigid body
	newtonBodyGetMatrix(body , Varptr NewtonMat[0])
	SetMatrix(Primitive , Varptr NewtonMat[0])	
End Function
Function PhysicsBodyDestructor(body:Byte Ptr)
	Local primitive:ISceneNode
	'// get the graphic Object form the rigid body
	' GG: changed to recreate the scenenode based on the C++ object handle
	primitive = ISceneNode.CreateFromHandle(Int(newtonBodyGetUserData(body)),False)
	'// destroy the graphic Object
	primitive.remove()
	
End Function
Function CleanUp ()
	'// destroy the Newton world
	NewtonDestroy (nWorld);
	
End Function

Function InitScene()
	Global Texture:ITexture = Driver.getTexture("doc/brllogo.png") 
	Global box:ISceneNode
	Global IFloor:ISceneNode
	Global boxBody:Byte Ptr
	Global floorBody:Byte Ptr
	Global collision:Byte Ptr
	Global Mat:Float[16]
	'// create the newton world
	
	'// set the linear solver model For faster speed 
	NewtonSetSolverModel(nWorld, 8)
	'// set the adpative friction model For faster speed 
	NewtonSetFrictionModel(nWorld, 1)
	
	'// Set the termination Function
	'atexit(CleanUp);   '//// I Haven't Found The Apropriaty Function for Irrlicht
	
	' ------------------------------------
	' floor
	' ------------------------------------
	'// create the the Floor graphic objects
	IFloor = smgr.addCubeSceneNode(100 )
	'IFloor.setMaterialFlag(EMF_LIGHTING,True)
	IFloor.setMaterialTexture(0 , texture)
	IFloor.setPosition(Vector3df.createFromVals(0,-100 , 0))
	collision = newtonCreateBox(nWorld , 100.0 , 100.0 , 100.0 , Null)
	FloorBody = newtonCreateBody(nWorld , collision)
	
	'// set the transformation For this rigid body
	GetMatrix(IFloor ,Varptr Mat[0])
	NewtonBodySetMatrix(floorBody,Varptr Mat[0])
	
	'// save the pointer To the graphic Object with the body.
	' GG: changed to store the scenenode C++ object handle instead of a reference to the BMAX object with falls out of scope
	NewtonBodySetUserData(floorBody,Byte Ptr(IFloor.handle))
	
	'// set a destrutor For this rigid body
	NewtonBodySetDestructorCallback(floorBody, PhysicsBodyDestructor);
	' ------------------------------------
			
	' ------------------------------------
	' boxes
	' ------------------------------------
	'// set the initial size
	'size = dVector(0.5f, 0.5f, 0.5f);    Not really nesesery(I think so)
	'// create the collision 
	newtonReleaseCollision(nWorld , collision)
	collision = NewtonCreateBox(nWorld, 0.5 , 0.5, 0.5 , Null) 
	Local location:Float[] = [0.0 , 0.0 , 0.0]
	location[0] = -10.0   'FOR  X
	For Local k:Int = 0 To 9
		location[2] = 0.0	'For Z
		For Local J:Int = 0 To 9
			location[1] = 2.0	'For Y
			For Local i:Int = 0  To 9
				box = smgr.addCubeSceneNode(0.5)
				box.setMaterialFlag(EMF_LIGHTING,True)
				box.SetMaterialTexture(0 , Texture)
				box.setPosition(Vector3df.createFromVals(location[0] ,location[1] , location[2]))
				boxBody = newtonCreateBody(nWorld , collision)				
				' GG: changed to store the scenenode C++ object handle instead of a reference to the BMAX object with falls out of scope
				newtonBodySetUserData(boxBody ,Byte Ptr(box.handle))		
				'// set a destrutor For this rigid body
				NewtonBodySetDestructorCallback(boxBody, PhysicsBodyDestructor)
				'// set the tranform call back Function
				NewtonBodySetTransformCallback(boxBody, PhysicsSetTransform)
				'// set the force And torque call back funtion
				NewtonBodySetForceAndTorqueCallback(boxBody, PhysicsApplyForceAndTorque)
				'// set the mass matrix
				'//NewtonBodySetMassMatrix (boxBody, 1.0f, 1.0f / 6.0f, 1.0f / 6.0f, 1.0f  / 6.0f);
				NewtonBodySetMassMatrix(boxBody, 1.0, 1.0, 1.0, 1.0)				
				'// set the matrix For tboth the rigid nody And the graphic body
				GetMatrix(box , Varptr Mat[0])
				NewtonBodySetMatrix(boxBody,Varptr Mat[0])
				PhysicsSetTransform(boxBody, Varptr Mat[0])
				Location[1] :+ 0.5 * 2.0
			Next
			Location[2] :- 0.5 * 4.0 	
		Next
		location[0] :- 0.5 * 4.0 
	Next
	'// Release the collsion geometry when Not need it
	NewtonReleaseCollision(nWorld, collision)
	' ------------------------------------	
EndFunction

Function AnimatedMeshToNewtonCollisionTree:Byte Ptr(nWorld:Byte Ptr,g_map:IAnimatedMesh,g_newtonMap:Byte Ptr)
	NewtonTreeCollisionBeginBuild(g_newtonmap)
	Local cMeshBuffer:Int,j:Int
	Local v1i:Int,v2i:Int,v3i:Int
	Local mb:IMeshBuffer
	
	Local vArray:Float[9]	'vertex array (3*3 floats)
	
	Local tmpCount:Int = 0
	
	For cMeshBuffer=0 To g_map.getMesh(0).getMeshBufferCount() - 1
		
		mb = g_map.getMesh(0).getMeshBuffer(cMeshBuffer)
		
		Local mb_vertices:Array_S3DVertex=mb.getVertices()
		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]
			
			vArray[0]=mb_vertices.elementAt(v1i).getPos().getX()
			vArray[1]=mb_vertices.elementAt(v1i).getPos().getY()
			vArray[2]=mb_vertices.elementAt(v1i).getPos().getZ()
			vArray[3]=mb_vertices.elementAt(v2i).getPos().getX()
			vArray[4]=mb_vertices.elementAt(v2i).getPos().getY()
			vArray[5]=mb_vertices.elementAt(v2i).getPos().getZ()
			vArray[6]=mb_vertices.elementAt(v3i).getPos().getX()
			vArray[7]=mb_vertices.elementAt(v3i).getPos().getY()
			vArray[8]=mb_vertices.elementAt(v3i).getPos().getZ()
			
			NewtonTreeCollisionAddFace(g_newtonmap, 3,Varptr vArray[0], 12, j)
		Next
		
	Next
	NewtonTreeCollisionEndBuild(g_newtonmap,0)
	Local g_newtonmapbody:Byte Ptr=NewtonCreateBody(nWorld,g_newtonmap)
	
Rem
After loading the bsp mesh in irrlicht we must create a newton collision tree consisting of all the triangles
in the bsp mesh. To do this we loop through the indices list And add vertices 3 at a time into newton. I should
mention here that I was lazy when writing this And just used a straight cast To video::S3DVertex2TCoords - this is because
bsp meshes have lightmap textures on them. If you are using a mesh with only 1 set of texture co-ordinates (like
a landscape Or .x level) Then use (video::S3DVertex).
Newton requires 2 pointers For every Object - a NewtonBody* For the rigid body, And a NewtonCollision* that
describes the objects geometry. After creating the tree collision geometry, we create a body For the map And
assign it To the collision. Bodys which have a tree collision For their geometry are static And their mass
will be ignored by newton - so you can only use meshes For your scenery!
End Rem
	Rem
	'set the newton world size based on the bsp size
	Local boxP0:Float[3] 
	Local boxP1:Float[3] 
	Local matrix:Float[16] 
	NewtonBodyGetMatrix g_newtonmapbody,Varptr matrix[0]
	NewtonCollisionCalculateAABB g_newtonmap,Varptr matrix[0],Varptr boxP0[0],Varptr boxP1[0]
	'pad the box
	boxP0[0]:-10
	boxP1[0]:+10
	boxP0[1]:-10
	boxP1[1]:+10
	boxP0[2]:-10
	boxP1[2]:+10
	NewtonSetWorldSize nWorld,Varptr boxP0[0],Varptr boxP1[0]
	EndRem
Rem
After loading the map, we can calculate the bounding box surrounding it And set the newton world size To
match. Newton should automatically disable anything which falls out of the map this way.
End Rem
	Return g_newtonmapbody
End Function