amerkoleci / JoltPhysicsSharp

JoltPhysics C# bindings
MIT License
238 stars 34 forks source link

Null reference exception when calling GetWorldTransform(bodyID) #57

Closed PhilT closed 8 months ago

PhilT commented 8 months ago

Not sure if this is a JoltC, Jolt C# or my own issue but calling bodyInterface.GetWorldTransform(bodyID) with a valid bodyID causes a NullReference exception. I can call other methods such as GetRotation or GetPosition and they work correctly. If it should work let me know and I'll post an example but it's not much different to the HelloWorld example just using GetWorldTransform.

amerkoleci commented 8 months ago

Hi, I've tried in HelloWorld and no issue happens, can you reproduce a test case?

PhilT commented 8 months ago

Thanks for checking. My example is in F# so perhaps that's the issue. I've tried to reduce it to the minimum possible:

#r "nuget: JoltPhysicsSharp, 2.3.1"

open JoltPhysicsSharp
open System.Numerics

module Layers =
  let NON_MOVING = ObjectLayer(0us)
  let MOVING = ObjectLayer(1us)

module BroadPhaseLayers =
  let NON_MOVING = BroadPhaseLayer(byte 0)
  let MOVING = BroadPhaseLayer(byte 1)

let createBox (dimensions: Vector3) =
  let mutable size = dimensions
  new BoxShape(&size)

if not (Foundation.Init(0u, false)) then (failwith "Unable to start JoltPhysicSharp")

let pairFilterTable = new ObjectLayerPairFilterTable(2u)
pairFilterTable.EnableCollision(Layers.NON_MOVING, Layers.MOVING)
pairFilterTable.EnableCollision(Layers.MOVING, Layers.NON_MOVING)

let broadPhaseTable = new BroadPhaseLayerInterfaceTable(2u, 2u)
broadPhaseTable.MapObjectToBroadPhaseLayer(Layers.NON_MOVING, BroadPhaseLayers.NON_MOVING)
broadPhaseTable.MapObjectToBroadPhaseLayer(Layers.MOVING, BroadPhaseLayers.MOVING)

let settings = PhysicsSystemSettings(
  ObjectLayerPairFilter = pairFilterTable,
  BroadPhaseLayerInterface = broadPhaseTable,
  ObjectVsBroadPhaseLayerFilter = new ObjectVsBroadPhaseLayerFilterTable(broadPhaseTable, 2u, pairFilterTable, 2u)
)

let physicsSystem = new PhysicsSystem(settings)

let floorShape = createBox (Vector3(1000f, 1f, 1000f))
let cubeShape = createBox (Vector3(0.5f, 0.5f, 0.5f))

let bodyInterface = physicsSystem.BodyInterface

let mutable position = Vector3.Zero
let mutable rotation = Quaternion.Identity
let floorSettings = new BodyCreationSettings(floorShape, &position, &rotation, MotionType.Static, Layers.NON_MOVING)
let floorId = bodyInterface.CreateAndAddBody(floorSettings, Activation.DontActivate)

let createCube x =
  let mutable pos = Vector3(x, 200f, 1f)
  let mutable cubeRotation = Quaternion.Identity

  let cubeSettings = new BodyCreationSettings(cubeShape, &pos, &cubeRotation, MotionType.Dynamic, Layers.MOVING)
  let body = bodyInterface.CreateBody(cubeSettings)
  bodyInterface.AddBody(&body, Activation.Activate)
  body.ID

let deltaTime = 1f / 60f

let mutable cubeId = createCube 10f

let rec loop () =
  let error = physicsSystem.Step(deltaTime, 1)
  assert (error = PhysicsUpdateError.None)

  if bodyInterface.IsActive(&cubeId) then
    printfn "Cube ID: %A" cubeId
    let position = bodyInterface.GetWorldTransform(&cubeId).Translation
    printfn "Position: %A" position
    System.Threading.Thread.Sleep(16)
    loop ()

loop ()

Foundation.Shutdown()

Can be run with dotnet fsi script.fsx.

Output:

Cube ID: 16777217
System.NullReferenceException: Object reference not set to an instance of an object.
   at JoltPhysicsSharp.BodyInterface.GetWorldTransform(BodyID& bodyID) in /_/src/JoltPhysicsSharp/BodyInterface.cs:line 244
   at FSI_0002.loop() in /data/code/matter/src/spikes/jolt_physics.fsx:line 65
   at <StartupCode$FSI_0002>.$FSI_0002.main@() in /data/code/matter/src/spikes/jolt_physics.fsx:line 70
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Stopped due to error

Changing let position = bodyInterface.GetWorldTransform(&cubeId).Translation to let position = bodyInterface.GetPosition(&cubeId) and it works fine.

Cube ID: 16777217
Position: Double3 { X = 10, Y = 199.99728393554688, Z = 1 }
Cube ID: 16777217
Position: Double3 { X = 10, Y = 199.99183654785156, Z = 1 }
Cube ID: 16777217
Position: Double3 { X = 10, Y = 199.98367309570312, Z = 1 }
Cube ID: 16777217
Position: Double3 { X = 10, Y = 199.97279357910156, Z = 1 }
Cube ID: 16777217
Position: Double3 { X = 10, Y = 199.95919799804688, Z = 1 }
Cube ID: 16777217
Position: Double3 { X = 10, Y = 199.94290161132812, Z = 1 }
Cube ID: 16777217
Position: Double3 { X = 10, Y = 199.92388916015625, Z = 1 }
Cube ID: 16777217
Position: Double3 { X = 10, Y = 199.9021759033203, Z = 1 }
Cube ID: 16777217
...

Any ideas?

amerkoleci commented 8 months ago

Hi, I found the issue, just grab the new 2.3.3 release and tell me if it works please.

PhilT commented 8 months ago

That's working. Thank you so much.

I see it's now returning an RMatrix, the double float version right.