OK, I have gathered code from multiple sources here and there and I am trying to wrap my head around Newton. I have it up and running but for some reason my registered physics callback functions only get called once. From reading the Newton docs that may be due to the fact that (from the engine's) perspective my objects do not need to be updated.
Anyway, I spent all day on this yesterday so if anyone has any ideas / help I'd appreciate it. I'm especially interested in any info folks might have on making sure I am doing 2D properly (assuming I can get my object moving around the screen!)
Here is my code:
SuperStrict
Import misc.Newton ' Module from LeadWerks
Type ImageNode
Field Image:TImage
Field x:Int , y:Int , z:Int = 0
Field rotX:Float , rotY:Float , rotZ:Float = 0.0
Field mass:Float
Function Create:ImageNode(ImgStr:String , tmpX:Int , tmpY:Int , tmpRot:Int)
Local tmpN:ImageNode = New ImageNode
tmpN.Image = LoadImage(ImgStr)
tmpN.x = tmpX
tmpN.y = tmpY
tmpN.rotZ = tmpRot
MidHandleImage tmpN.Image
Return tmpN
End Function
Method draw()
SetRotation rotZ
DrawImage image , x , y
SetRotation 0
End Method
End Type
Rem
Max2DGetMatrix is the function to get the matrix from the Max2D Image And pass it
to an array to be used by Newton. Max2DSetMatrix is the function to pass the Matrix from Newton
to the Max2D Image
EndRem
Function Max2DGetMatrix(NImageNode:ImageNode , NewtonMat:Float Ptr)
Local Euler:Float[3]
Euler[0] = NImageNode.rotX * (Pi / 180.0)
Euler[1] = NImageNode.rotY * (Pi / 180.0)
Euler[2] = NImageNode.rotZ * (Pi / 180.0)
NewtonSetEulerAngle(Varptr Euler[0] , Varptr newtonMat[0])
Newtonmat[12] = NImageNode.X
newtonMat[13] = NImageNode.Y
NewtonMat[14] = NImageNode.Z
End Function
Function Max2DSetMatrix(NImageNode:ImageNode , NewtonMat:Float Ptr)
Local Euler:Float[3]
NewtonGetEulerAngle(Varptr NewtonMat[0] , Varptr Euler[0])
NImageNode.x = NewtonMat[12]
NImageNode.y = NewtonMat[13]
NImageNode.z = NewtonMat[14]
NImageNode.rotX = Euler[0] * (180 / Pi)
NImageNode.rotY = Euler[1] * (180 / Pi)
NImageNode.rotZ = Euler[2] * (180 / Pi)
End Function
Graphics 1024, 768, 0, 60
If StartNewton() Then
Local Test:ImageNode = ImageNode.create("water.png" , 400 , 400 , 10)
Local newtonWorld:Byte Ptr = newtonCreate(MemAllocate, MemRelease)
Local collision:Byte Ptr = Null
collision = newtonCreateBox(newtonWorld, ImageWidth(Test.Image) , ImageHeight(Test.Image) , 1 , Null)
Local myBox:Byte Ptr = NewtonCreateBody(newtonWorld, collision)
NewtonReleaseCollision newtonWorld, collision
newtonBodySetMassMatrix myBox, 5.0 , 1.0 , 1.0 , 1.0
Local Mat:Float[16]
Max2DGetMatrix Test, Varptr Mat[0]
newtonBodySetMatrix(myBox, Varptr Mat[0])
Local force:Float[3]
force[0] = 1.0#
force[1] = 1.0#
force[2] = 1.0#
newtonBodySetForce(myBox, Varptr force[0])
Local Omega:Float[] = [50.0 , 10.0 , 10.0]
newtonBodySetOmega(myBox , Varptr omega[0])
Local testHandle:Int = HandleFromObject(Test)
Local testHandlePtr:Int Ptr = Varptr(testHandle)
newtonBodySetUserData(myBox, testHandlePtr)
newtonBodySetTransformCallBack(myBox, PhysicsSetTransform)
newtonBodySetForceandTorqueCallback(myBox, PhysicsApplyForceAndTorque)
NewtonBodySetDestructorCallback (myBox, PhysicsBodyDestructor);
newtonWorldUnFreezeBody newtonWorld, myBox
Local iTicks:Int = 0
Local iStart:Int = 0
Repeat
iStart = MilliSecs()
'newtonUpdate(newtonWorld , FPS.Calc())
newtonUpdate(newtonWorld , .01#)
Cls
DrawText String(iTicks), 1, 1
newtonBodyGetMatrix(myBox, Varptr Mat[0])
For Local i2:Int = 0 To 15
DrawText mat[i2] , 10 , (i2 * 10) + 64
Next
'DrawText Test.rotZ , 10 , 200
'NewtonWorldForEachBodyDo newtonWorld, iterator
Test.draw
Flip
iTicks = MilliSecs() - iStart
Until KeyHit(KEY_ESCAPE) Or AppTerminate()
StopNewton
End If
Rem
Function iterator (newtonBody:Byte Ptr)
Local bp:Byte Ptr = newtonBodyGetUserData(newtonBody)
Local iHandle:Int = bp[0]
Local tmpNode:ImageNode = ImageNode(HandleToObject(iHandle))
' Get latest newton stuff for our object
newtonBodyGetMatrix(tmpNNode , Varptr tmpMat[0])
Local Euler:Float[] = [0.0 , 0.0 , tmpImageNode.rotZ]
Max2DSetMatrix(tmpImageNode , Varptr tmpMat[0])
newtonBodyGetMatrix
'newtonBodyGetMatrix(tmpNode , Varptr tmpMat[0])
'Local Euler:Float[] = [0.0 , 0.0 , tmpImageNode.rotZ]
'Max2DSetMatrix(tmpImageNode , Varptr tmpMat[0])
End Function
End Rem
'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
Function PhysicsSetTransform(newtonBody:Byte Ptr , tmpMat:Float Ptr)
' This never even gets called!
Local bp:Byte Ptr = newtonBodyGetUserData(newtonBody)
Local iHandle:Int = bp[0]
Local tmpNode:ImageNode = ImageNode(HandleToObject(iHandle))
newtonBodyGetMatrix(newtonBody, Varptr tmpMat[0])
'Local Euler:Float[] = [0.0 , 0.0 , tmpImageNode.rotZ]
Max2DSetMatrix(tmpNode, Varptsr tmpMat[0])
End Function
Function PhysicsApplyForceAndTorque(tmpNNode:Byte Ptr)
' This only gets called once
'DebugStop
Local Mass:Float
Local Ixx:Float
Local Iyy:Float
Local Izz:Float
newtonBodyGetMassMatrix(tmpNNode , Varptr Mass , Varptr Ixx , Varptr Iyy , Varptr Izz)
Local force:Float[] = [0.0 , mass * 9.8 , 0.0]
newtonBodySetForce(tmpNNode , Varptr force[0])
End Function
Function PhysicsBodyDestructor(tmpNNode:Byte Ptr)
DebugStop
End Function
Type FPS
' FPS_Counter <> Runs and displays the FPS
Global Counter:Int, Time:Int, TFPS:Int
Function Calc%()
Counter:+1
If Time < MilliSecs()
TFPS = Counter' <- Frames/Sec
Time = MilliSecs() + 1000'Update
Counter = 0
EndIf
Return TFPS
EndFunction
Function Display()
DrawText "FPS: "+FPS.Calc(),10,220
End Function
EndType
|