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