Newton trouble.

BlitzMax Forums/BlitzMax Programming/Newton trouble.

Anyone who has the following mods:

Pub.Newton
Irrlicht.Core

Could you please show me an example of how to use the Newton dynamics engine? For example, creating some bodies (boxes or something) and having them collide in an irrlicht world.

I would really appreciate the help. Thanks!

Nevermind, I've cranked out some noob code. Here it is:

'my newton physics test

Framework BRL.Blitz 'core module
Import BRL.Random 'random number generator.
Import Pub.Newton 'newton dynamics interface module.
Import Irrlicht.Extended 'a slight extension by me that adds the CreateIrrlicht
                         'and ReleaseIrrlicht convenience functions.

SeedRnd MilliSecs() 'randomize based on the system timer -- the best way to get
                    'the most random results.

'irrlicht pointers
Global dvc:IrrlichtDevice
Global dvr:IVideoDriver
Global sne:ISceneManager

'create irrlicht context
Print "Successfully created Irrlicht Device context."
CreateIrrlicht EDT_OPENGL,640,480,32,True,True,True,dvc,dvr,sne

Print "Successfully generated font."
Global font:IGUIFont=dvc.getGUIEnvironment().getBuiltInFont()

'create skybox
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"))
Print "Successfully added skybox."

'create scene camera (viewpoint)
Global cam:ICameraSceneNode=sne.addCameraSceneNodeFPS(Null,100,95)
cam.setPosition(_VECTOR3DF(0,40,-200))
Print "Successfully added camera."

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

'load a map mesh, nothing fancy, just a flat surface grid
Global grid:IAnimatedMesh=sne.getMesh("grid.b3d")
If Not grid.isValid() Then
	Notify "Could not load mesh GRID.B3D.",True
	End
End If
'add map node to scene
Global map:ISceneNode=sne.addAnimatedMeshSceneNode(grid)
map.setMaterialTexture(0,dvr.getTexture("grid.jpg"))
map.SetScale(_VECTOR3DF(10,10,10))
map.setPosition(_VECTOR3DF(0,-100,0))
map.setMaterialFlag EMF_LIGHTING,True
Print "Successfully added map."

'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)
Print "Successfully generated dynamics world!"

'add some cubes
WriteStdout "Adding cube nodes..."
Global boxnode:ISceneNode[20]
For j=0 To 19
	boxnode[j]=sne.addCubeSceneNode()
	boxnode[j].setPosition(_VECTOR3DF(Rnd(-100#,100#),Rnd(-100#,100#),Rnd(-100#,100#)))
	boxnode[j].setMaterialTexture(0,dvr.getTexture("grid.jpg"))
	boxnode[j].setMaterialFlag EMF_LIGHTING,True
Next
Print "done!"

Local collision:Byte Ptr=NewtonCreateBox(world,1#,1#,1#,Null)
Print "Successfully generated cube collision object."

WriteStdout "Generating cube collision bodies..."
Global box:Byte Ptr[20]
Local mat:Float[16]
Local omega:Float[3]
For j=0 To 19
	GetEulerMatrix boxnode[j],mat
	box[j]=NewtonCreateBody(world,collision)
	NewtonBodySetMassMatrix box[j],1#,1#,1#,1#
	NewtonBodySetMatrix box[j],Varptr mat[0]
	omega[0]=Rnd(-5#,5#)
	omega[1]=Rnd(-5#,5#)
	omega[2]=Rnd(-5#,5#)
	NewtonBodySetOmega box[j],Varptr omega[0]
Next
Print "done!"

'okay, here we go
WriteStdout "Begin simulation..."
fps=0
str$=""
timestep!=0

Repeat
	timestep=NewtonGetTimeStep(world)*1.2
	NewtonUpdate world,timestep
	
	For j=0 To 19
		NewtonBodyGetMatrix box[j],Varptr Mat[0]
		SetEulerMatrix boxnode[j],Mat
	Next

	dvr.beginScene(True,True)
		sne.drawAll()
	
		fps=dvr.getFPS()
		str="renderer is ~q"
		str:+dvr.getName()+"~q   dynamics engine is ~qNewton Dynamics Engine v"
		str:+NewtonWorldGetVersion(world)+"~q   "
		str:+"the frame per second count is "+fps+"   timestep is "+timestep
		font.draw str,_RECTI(10,10,300,50),_SCOLOR(255,255,255,255)
	dvr.endScene()
Until Not dvc.run()
Print "ended properly."

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

End

'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

'Overrides Newton's local memory functions with BMax native wrappers.
Function MemAllocate:Byte Ptr(sizeInBytes:Int)
	Return MemAlloc(sizeInBytes)
End Function
Function MemRelease(memptr:Byte Ptr,sizeInBytes:Int)
	MemFree(memptr)
End Function


Oh and here's Irrlicht.Extended :
Module Irrlicht.Extended

Import Irrlicht.Core
Import BRL.System
Private
	OnEnd byebye
	Function byebye()
		Print "Goodbye."
	End Function
Public

Function CreateIrrlicht(renderer,rezx,rezy,bits,fullscrn,stencil,vsync,DVC:IrrlichtDevice Var,DVR:IVideoDriver Var,SCN:ISceneManager Var)
	DVC=IrrlichtDevice.create(..
	 renderer,_DIMENSION2DI(rezx,rezy),rezdepth,..
	  fullscrn,stencil,vsync)
	
	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()
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


Problem is, a) they won't collide with each other, and b) they won't fall. Can someone enlighten me about this? I am brand new with Newton.

Hmm, still having a bit 'o trouble. The bodies go through eachother, and they don't fall. Any newton people have an idea about what causes this?

AAOOGAH! I GOT IT WORKING!

Have a look! :)

'my newton physics test

Framework BRL.Blitz 'core module
Import BRL.Random 'random number generator.
Import Pub.Newton 'newton dynamics interface module.
Import Rat.FormatString 'my text format module.
Import Irrlicht.Extended 'a slight extension by me that adds the CreateIrrlicht
                         'and ReleaseIrrlicht convenience functions.

Print "HELLO WORLD!!!"

ms=MilliSecs()
SeedRnd ms 'randomize 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
Global dvr:IVideoDriver
Global sne:ISceneManager

'newton pointers and matricies
Global box:Byte Ptr[30]
Global mat:Float[16]
Global omega:Float[3]
Global collision:Byte Ptr

'create irrlicht context
CreateIrrlicht EDT_OPENGL,1024,786,16,True,False,False,dvc,dvr,sne
Print "Successfully created Irrlicht Device context."

Global font:IGUIFont=dvc.getGUIEnvironment().getFont("fontlucida.png")
Print "Successfully generated font."

'create skybox
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"))
Print "Successfully added skybox."

'create scene camera (viewpoint)
Global cam:ICameraSceneNode=sne.addCameraSceneNodeFPS(Null,100,6)
cam.setPosition(_VECTOR3DF(0,.4,-2))
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)
Local wmn#[]=[-9#,-9#,-9#]
Local wmx#[]=[9#,9#,9#]
NewtonSetWorldSize world,Varptr wmn[0],Varptr wmx[0]

Print "Successfully generated dynamics world!"

'create a floor
Local afloor:ISceneNode=sne.addCubeSceneNode(6)
afloor.setMaterialFlag EMF_LIGHTING,False
afloor.setMaterialTexture 0,dvr.getTexture("grid.jpg")
afloor.setPosition _VECTOR3DF(0,-6,0)
collision=NewtonCreateBox(world,6#,6#,6#,Null)
Local floorbody:Byte Ptr=newtonCreateBody(world,collision)

'initialize floor
GetEulerMatrix afloor,Mat
NewtonBodySetMatrix floorbody,Varptr Mat[0]
NewtonBodySetUserData floorbody,Byte Ptr(afloor.handle)
NewtonBodySetDestructorCallback floorbody,pBodyDestructor
Print "Successfully added floor body."

NewtonReleaseCollision world,collision
Print "Successfully released floor collision object."

'add some cubes
WriteStdout "Adding cube nodes..."
Global boxnode:ISceneNode[30]
For j=0 To 29
	boxnode[j]=sne.addCubeSceneNode(.8#)
	boxnode[j].setPosition(_VECTOR3DF(Rnd(-3#,3#),Rnd(6#),Rnd(-3#,3#)))
	boxnode[j].setMaterialTexture(0,dvr.getTexture("grid.jpg"))
	boxnode[j].setMaterialFlag EMF_LIGHTING,True
	GCCollect
Next
Print "done!"

collision=NewtonCreateBox(world,.8#,.8#,.8#,Null)
Print "Successfully generated cube collision object."

'put the cubes in the dynamics world
WriteStdout "Generating cube collision bodies..."
For j=0 To 29
	GetEulerMatrix boxnode[j],mat
	box[j]=NewtonCreateBody(world,collision)
	NewtonBodySetMassMatrix box[j],1#,1#,1#,1#
	NewtonBodySetMatrix box[j],Varptr mat[0]
	omega[0]=Rnd(-.5#,.5#)
	omega[1]=Rnd(-.5#,.5#)
	omega[2]=Rnd(-.5#,.5#)
	NewtonBodySetOmega box[j],Varptr omega[0]
	NewtonBodySetAutoFreeze box[j],1
	NewtonBodySetUserData box[j],Byte Ptr(boxnode[j].handle)
	NewtonBodySetDestructorCallback box[j],pBodyDestructor
	NewtonBodySetTransformCallback box[j],pSetTransform
	NewtonBodySetForceAndTorqueCallback box[j],pApplyForceAndTorque
	GCCollect
Next
Print "done!"

NewtonReleaseCollision world,collision
Print "Successfully released box collision object."

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

Repeat
	dvr.beginScene(True,True)
		sne.drawAll() 'draw scene
		
		'draw general data
		fps=dvr.getFPS()
		str="renderer is ~q"
		str:+dvr.getName()+"~q   dynamics engine is ~qNewton Dynamics Engine v"
		str:+NewtonWorldGetVersion(world)+"~q   "
		str:+"the frame per second count is "+fps+"   timestep is "+timestep
		font.draw str,_RECTI(3,3,300,50),_SCOLOR(255,255,255,255)
		
		'update body matricies and draw matrix data on screen
		font.draw "NOTE: Matrix coefficients are multiplied by ten.         "+..
		 "       MemAllocated="+GCMemAlloced()+"Bytes (note that the renderer uses seperate memory system.)",..
		  _RECTI(3,23,300,50),_SCOLOR(255,255,255,255)
		For j=0 To 19
			NewtonBodyGetMatrix box[j],Varptr Mat[0]
			intMat=GetIntMatrix(Mat)
			SetEulerMatrix boxnode[j],Mat
			str="NodeEulerMat["+j+"]="+getSingleArrayStr(intMat)+..
			 "   IsNodeActive="+NewtonBodyGetSleepingState(box[j])
			font.draw str,_RECTI(3,43+j*20,300,50),_SCOLOR(255,255,255,255)
		Next
		
		'update world matrix
		timestep=NewtonGetTimeStep(world)
		NewtonUpdate world,timestep
	dvr.endScene()
	
	GCCollect
Until Not dvc.run()
Print "ended properly."

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

End

Function GetIntMatrix[](Mat#[])
	Local tmpMat#[]=Mat
	Local intMat[tmpMat.length]
	For j=0 To tmpMat.length-1
		intMat[j]=tmpMat[j]*10
	Next
	Return intMat
End Function

'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.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

'These override Newton's local memory functions with native function wrappers.
Function MemAllocate:Byte Ptr(sizeInBytes:Int)
	Return MemAlloc(sizeInBytes)
End Function
Function MemRelease(memptr:Byte Ptr,sizeInBytes:Int) 'sizeInBytes:Int is a placeholder.
	MemFree(memptr)
	GCCollect
End Function

'body event callbacks
Function  pApplyForceAndTorque(Body:Byte Ptr)
	Local mass#,Ixx#,Iyy#,Izz#
	NewtonBodyGetMassMatrix(body,Varptr mass, Varptr Ixx, Varptr Iyy, Varptr Izz)
	Local force#[]=[0.0,-mass*410,0.0]
	NewtonBodySetForce body,Varptr force[0]
End Function
Function  pSetTransform(body:Byte Ptr,NewtonMat# Ptr)
	Local primitive:ISceneNode
	primitive=ISceneNode.CreateFromHandle(Int(newtonBodyGetUserData(body)),False)
	
	newtonBodyGetMatrix body,Varptr NewtonMat[0]
	SetEulerMatrix2(Primitive,Varptr NewtonMat[0])
End Function
Function pBodyDestructor(body:Byte Ptr)
	Local primitive:ISceneNode
	
	primitive=ISceneNode.CreateFromHandle(Int(newtonBodyGetUserData(body)),False)
	primitive.remove()
End Function


Pretty cool, the way they pile up and roll of the edges, huh? I swear, I love physics simulation so much I'll play ANY game that has it just to watch the ragdolls and boxes and stuff. I actually played Doom 3 just to see the ragdoll physics. I mean I cared more about Doom 3's ragdoll physics than the amazing graphics everyone raves about!

Newton is the best system out there, even better than PhysX and Havok. For example, PhysX doesn't even have support for a cylinder primitive. Julio has some BSP algorithms in there that are useful for lots of non-physics stuff as well. I finally just ported all my intersection and raycasting routines over to Newton, since he has done such a good job optimizing it. For example, you can build a BSP out of a mesh, for raycasting that is an order of magnitude faster than testing each triangle. He even added some routines to perform a fast calculate of BSP triangles within a bounding box, for fast shadows or decals. Also, an upcoming version will use a GE Force 8800 to process physics on the gfx card.

Cool stuff! I sure hope my old junker can take it. :(

MORE AND MORE! Now there are spheres as well, and they all reset up at the top when they leave the world after falling off the main box. It's a continuous display now! Kinda proud. :)

'my newton physics test

Framework BRL.Blitz      'core module
Import BRL.Random        'random number generator.
Import BRL.LinkedList    'linked list handler
Import Pub.Newton        'newton dynamics interface module.
Import Irrlicht.Extended 'a slight extension by me that adds the CreateIrrlicht
                         'and ReleaseIrrlicht convenience functions.
Print "HELLO WORLD!!!"

ms=MilliSecs()
SeedRnd ms 'randomize 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
Global dvr:IVideoDriver
Global sne:ISceneManager

'newton pointers and matricies
Global nMemSize,nNodeDestroyList:TList=New TList
Global box:Byte Ptr[30]
Global ball:Byte Ptr[30]
Global mat#[16]
Global omega#[3]
Global collision:Byte Ptr

'create irrlicht context
CreateIrrlicht EDT_OPENGL,640,480,32,False,True,True,dvc,dvr,sne
Print "Successfully created Irrlicht Device context."

dvc.SetResizeable True

Global font:IGUIFont=dvc.getGUIEnvironment().getFont("fontlucida.png")
Print "Successfully generated font."

'create skybox
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"))
Print "Successfully added skybox."

'create scene camera (viewpoint)
Global cam:ICameraSceneNode=sne.addCameraSceneNodeMaya(Null,32,16,16)
cam.setPosition(_VECTOR3DF(0,-.4,-12))
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)

'set the world size to a cube that is [36,36,36]
Local wmn#[]=[-18#,-18#,-18#]
Local wmx#[]=[18#,18#,18#]
NewtonSetWorldSize world,Varptr wmn[0],Varptr wmx[0]

'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

'set an event callback for bodies leaving the world
NewtonSetBodyLeaveWorldEvent world,BodyLeftWorld

Print "Successfully generated dynamics world!"

'create a floor
Local afloor:ISceneNode=sne.addCubeSceneNode(6)
afloor.setMaterialFlag EMF_LIGHTING,True
afloor.setMaterialTexture 0,dvr.getTexture("mossrock.jpg")
afloor.setMaterialTexture 1,dvr.getTexture("terraintex.jpg")
afloor.setMaterialType(EMT_DETAIL_MAP)
afloor.setPosition _VECTOR3DF(0,-6,0)
collision=NewtonCreateBox(world,6#,6#,6#,Null)
Local floorbody:Byte Ptr=newtonCreateBody(world,collision)

'initialize floor
GetEulerMatrix afloor,Mat
NewtonBodySetMatrix floorbody,Varptr Mat[0]
NewtonBodySetUserData floorbody,Byte Ptr(afloor.handle)
NewtonBodySetDestructorCallback floorbody,BodyDestructor
Print "Successfully added floor body."

NewtonReleaseCollision world,collision
Print "Successfully released floor collision object."

'add some cubes
WriteStdout "Adding cube nodes..."
Global boxnode:ISceneNode[30]
For j=0 To 29
	boxnode[j]=sne.addCubeSceneNode(.8#)
	boxnode[j].setPosition(_VECTOR3DF(Rnd(-3#,3#),Rnd(9#),Rnd(-3#,3#)))
	boxnode[j].setMaterialTexture(0,dvr.getTexture("terraintex.jpg"))
	boxnode[j].setMaterialFlag EMF_LIGHTING,True
	GCCollect
Next
Print "done!"

collision=NewtonCreateBox(world,.8#,.8#,.8#,Null)
Print "Successfully generated cube collision object."

'put the cubes in the dynamics world
WriteStdout "Generating cube collision bodies..."
For j=0 To 29
	GetEulerMatrix boxnode[j],mat
	box[j]=NewtonCreateBody(world,collision)
	NewtonBodySetMassMatrix box[j],1#,1#,1#,1#
	NewtonBodySetMatrix box[j],Varptr mat[0]
	omega[0]=Rnd(-5#,5#)
	omega[1]=Rnd(-5#,5#)
	omega[2]=Rnd(-5#,5#)
	NewtonBodySetOmega box[j],Varptr omega[0]
	NewtonBodySetAutoFreeze box[j],1
	NewtonBodySetUserData box[j],Byte Ptr(boxnode[j].handle)
	NewtonBodySetDestructorCallback box[j],BodyDestructor
	NewtonBodySetTransformCallback box[j],NSetTransform
	NewtonBodySetForceAndTorqueCallback box[j],ApplyForceAndTorque
	GCCollect
Next
Print "done!"

NewtonReleaseCollision world,collision
Print "Successfully released cube collision object."

'add some balls
WriteStdout "Adding sphere nodes..."
Global ballnode:ISceneNode[30]
For j=0 To 29
	ballnode[j]=sne.addSphereSceneNode(.4#)
	ballnode[j].setPosition(_VECTOR3DF(Rnd(-3#,3#),Rnd(9#),Rnd(-3#,3#)))
	ballnode[j].setMaterialTexture(0,dvr.getTexture("terraintex.jpg"))
	ballnode[j].setMaterialFlag EMF_LIGHTING,True
	GCCollect
Next
Print "done!"

collision=NewtonCreateSphere(world,.4#,.4#,.4#,Null)
Print "Successfully generated sphere collision object."

'put the balls in the dynamics world
WriteStdout "Generating sphere collision bodies..."
For j=0 To 29
	GetEulerMatrix ballnode[j],mat
	ball[j]=NewtonCreateBody(world,collision)
	NewtonBodySetMassMatrix ball[j],1#,1#,1#,1#
	NewtonBodySetMatrix ball[j],Varptr mat[0]
	omega[0]=Rnd(-5#,5#)
	omega[1]=Rnd(-5#,5#)
	omega[2]=Rnd(-5#,5#)
	NewtonBodySetOmega ball[j],Varptr omega[0]
	NewtonBodySetAutoFreeze ball[j],1
	NewtonBodySetUserData ball[j],Byte Ptr(ballnode[j].handle)
	NewtonBodySetDestructorCallback ball[j],BodyDestructor
	NewtonBodySetTransformCallback ball[j],NSetTransform
	NewtonBodySetForceAndTorqueCallback ball[j],ApplyForceAndTorque
	GCCollect
Next
Print "done!"

NewtonReleaseCollision world,collision
Print "Successfully released sphere collision object."

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

Repeat
'	For j=0 To 29
'		NewtonBodyGetMatrix box[j],Varptr Mat[0]
'		intMat=GetIntMatrix(Mat)
'		SetEulerMatrix boxnode[j],Mat
'	Next
	
	'delete unwanted nodes
	DestroyReleasedNodes
	
	'update world matrix
	timestep=NewtonGetTimeStep(world)
	NewtonUpdate world,timestep
	
	dvr.beginScene(True,True)
		sne.drawAll() 'draw scene
		
		'draw general data
		fps=dvr.getFPS()
		str="renderer is ~q"
		str:+dvr.getName()+"~q   dynamics engine is ~qNewton Dynamics Engine v"
		str:+NewtonWorldGetVersion(world)+"~q   "
		str:+"the frame per second count is "+fps+"   timestep is "+timestep
		font.draw str,_RECTI(3,3,300,50),_SCOLOR(255,255,255,255)
		
		'update body matricies and draw matrix data on screen
		font.draw ..
		 "       CoreMem="+(GCMemAlloced()/1024)+"KB "+..
		  "SimMem="+(nMemSize/1024)+"KB TotalMem="+((GCMemAlloced()+nMemSize)/1024)+"KB (note that Irrlicht uses a seperate memory system, so we can't track it's usage)",..
		  _RECTI(3,19,300,50),_SCOLOR(255,255,255,255)
	dvr.endScene()
	
	GCCollect
Until Not dvc.run()
Print "ended properly."

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

End

Function DestroyReleasedNodes()
	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

'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.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

'These override Newton's local memory functions with native function wrappers.
Function MemAllocate:Byte Ptr(size:Int)
	nMemSize:+size
	Return MemAlloc(size)
End Function
Function MemRelease(memptr:Byte Ptr,size:Int)
	nMemSize:-size
	MemClear memptr,size
	MemFree memptr
	GCCollect
End Function

'body event callbacks
Function  ApplyForceAndTorque(Body:Byte Ptr)
	Local mass#,Ixx#,Iyy#,Izz#
	NewtonBodyGetMassMatrix(body,Varptr mass, Varptr Ixx, Varptr Iyy, Varptr Izz)
	Local force#[]=[0.0,-mass*410,0.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)
	Local node:ISceneNode=ISceneNode.CreateFromHandle(Int(newtonBodyGetUserData(body)),False)
	node.setPosition _VECTOR3DF(Rnd(-3#,3#),Rnd(6#,9#),Rnd(-3#,3#))
	GetEulerMatrix node,mat
	
	NewtonBodySetMatrix body,Varptr mat[0]
End Function
Function BodyDestructor(body:Byte Ptr)
	Local NodeHandle:Int
	
	NodeHandle=Int(newtonBodyGetUserData(body))
	nNodeDestroyList.AddLast NodeHandle
End Function