Skip to content

Instantly share code, notes, and snippets.

@AXKuhta
Last active March 7, 2023 05:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save AXKuhta/2406f722c7ffb3ca24ce79b4be613fe1 to your computer and use it in GitHub Desktop.
Save AXKuhta/2406f722c7ffb3ca24ce79b4be613fe1 to your computer and use it in GitHub Desktop.
OpenB3D and Newton Dynamics
Import OpenB3DMax.B3DGLGraphics
' TODO: Tweakable keybindings and speeds
Function MouseLook(pivot:TMesh, camera:TCamera, time:Long )
Local elapsed:Long
Repeat
elapsed=MilliSecs()-time
Until elapsed>0
time=time+elapsed
Local dt#=elapsed*60.0/1000.0
Local x_speed:Float, y_speed:Float
x_speed=((MouseX()-320)-x_speed)/8+x_speed
y_speed=((MouseY()-240)-y_speed)/8+y_speed
MoveMouse 320,240
TurnEntity pivot,0,(-x_speed),0 'turn player Left/Right
TurnEntity camera,y_speed,0,0 'tilt camera
End Function
Function Move(ent:TMesh)
If KeyDown( KEY_W )=True Then MoveEntity ent, 0, 0, 0.05
If KeyDown( KEY_A )=True Then MoveEntity ent, -0.05, 0, 0
If KeyDown( KEY_S )=True Then MoveEntity ent, 0,0, -0.05
If KeyDown( KEY_D )=True Then MoveEntity ent, 0.05, 0, 0
End Function
Framework BRL.StandardIO
Import Newton.Dynamics
Import OpenB3DMax.B3DGLGraphics
Import "NewtonFunctions.bmx"
Import "CameraFunctions.bmx"
Graphics3D 800, 600, 32, 2
Local Player:TMesh = CreateCylinder()
Local Camera:TCamera = CreateCamera(Player)
Local Light:TLight = CreateLight()
Local SkyDome:TMesh = CreateSphere()
PositionEntity Light, 0, 100, 0
PositionEntity Player, 0, 5, -10
ScaleEntity SkyDome, -500, -500, -500
EntityColor SkyDome, 40, 46, 80
Local PhysWorld:TNWorld = TNWorld.Create()
Local NCube:TNCube = CreateNCube(PhysWorld, 1, 0, 30, 0)
Local NPlane:TNPlane = CreateNPlane(PhysWorld, 0, -5, 0)
EntityColor NPLane.Mesh, 47, 85, 195
For Local i=0 To 10
For Local j=0 To 10
For Local k=0 To 1
CreateNCube(PhysWorld, 1, i*3, j*2.2, k*3)
Next
Next
Next
PhysWorld.InvalidateCache()
While Not KeyHit(KEY_ESCAPE)
PhysWorld.Update(1.0/60.0)
MouseLook(Player, Camera, MilliSecs())
Move(Player)
RenderWorld()
BeginMax2D
DebugNBody(NCube)
EndMax2D
Flip()
Wend
SuperStrict
Import Newton.Dynamics
Import OpenB3DMax.B3DGLGraphics
Function CreateNCube:TNCube(World:TNWorld, Sides:Float, x:Float, y:Float, z:Float, Mass:Float = 1.0)
Local Shape:TNCollision = World.CreateBox(Sides*2, Sides*2, Sides*2)
Local Matrix:TNMatrix = TNMatrix.GetIdentityMatrix()
Matrix.positX = x
Matrix.positY = y
Matrix.positZ = z
Local Box:TNCube = New TNCube
World.CreateDynamicBody(Shape, Matrix, Box)
'ScaleEntity Box.Mesh, 0.5, 0.5, 0.5
Box.SetMassProperties(Mass, Shape)
Box.SetLinearDamping(0.0)
Shape.Destroy()
Return Box
End Function
' It's more like a surface rather than a plane, because the length is finite
Function CreateNPlane:TNPlane(World:TNWorld, x:Float, y:Float, z:Float, length:Int = 100)
' These points are X, Y and Z of the physical plane basically
Local Points:Float[] = [ ..
-length+x, 0.0+y, length+z, ..
length+x, 0.0+y, length+z, ..
length+x, 0.0+y, -length+z, ..
-length+x, 0.0+y, -length+z ]
' Create a collision tree
Local Tree:TNTreeCollision = World.CreateTreeCollision(0)
' Start building the collision mesh
Tree.BeginBuild()
' Add the face one at a time
Tree.AddFace(4, Points, 12, 0)
' Finish building the collision
Tree.EndBuild(1)
' Create a body with a collision
Local Matrix:TNMatrix = TNMatrix.GetIdentityMatrix()
Local Plane:TNPlane = New TNPlane
World.CreateDynamicBody(Tree, Matrix, Plane)
PositionEntity Plane.Mesh, x, y, z
' Don't forget to destroy the collision tree after you no longer need it
Tree.Destroy()
Return Plane
End Function
' This is a static object that has no update function but participates in the simulation
Type TStaticBody Extends TNBody
Field Mesh:TMesh
End Type
' This is a dynamic object that by default only has gravity in the update function
Type TFreeFallBody Extends TNBody
Field Mesh:TMesh
' This function gets called before the each sim pass of an awake body
Method OnForceAndTorque(Timestamp:Float, ThreadIndex:Int)
' apply gravity force to the body
Local Mass:Float
Local Ixx:Float
Local Iyy:Float
Local Izz:Float
GetMassMatrix(Mass, Ixx, Iyy, Izz)
SetForce(0.0, -9.8 * Mass, 0.0, 0.0)
' And we can update the visual mesh position here too
Local Matrix:TNMatrix = New TNMatrix
Self.GetMatrix(Matrix)
MQ_ApplyNewtonTransform_(TEntity.GetInstance(Mesh), Matrix)
End Method
End Type
'
Type TNCube Extends TFreeFallBody
Method New()
Mesh = CreateCube()
End Method
' TODO: Can we destroy the cube? Do we need to implement the Destroy() method?
End Type
'
Type TNPlane Extends TStaticBody
Method New()
Mesh = CreatePlane()
End Method
End Type
Function DebugNBody(Body:TNBody)
Local Pitch:Float, Yaw:Float, Roll:Float
Local Pitch1:Float, Yaw1:Float, Roll1:Float
Local Matrix:TNMatrix = New TNMatrix
Body.GetMatrix(Matrix)
DrawText "X: " + Matrix.positX, 20, 20
DrawText "Y: " + Matrix.positY, 20, 30
DrawText "Z: " + Matrix.positZ, 20, 40
Matrix.GetEulerAngles(Pitch, Yaw, Roll, Pitch1, Yaw1, Roll1)
DrawText "P: " + Pitch*57.2, 20, 60
DrawText "Y: " + Yaw*57.2, 20, 70
DrawText "R: " + Roll*57.2, 20, 80
'DrawText "P1: " + Pitch1*57.2, 20, 100
'DrawText "Y1: " + Yaw1*57.2, 20, 110
'DrawText "R1: " + Roll1*57.2, 20, 120
End Function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment