Physics

Starlight provides a default subsystem for conveniently working with Telescope's Bullet integration. Explaining all of how it works would require an explanation of Bullet itself, but we'll attempt a high-level overview of the most important things it does.

mutable struct PhysicsObjectInfo
  hx::AbstractFloat
  hy::AbstractFloat
  hz::AbstractFloat
  m::AbstractFloat
  isKinematic::Bool
  mx::AbstractFloat
  my::AbstractFloat
  mz::AbstractFloat
  PhysicsObjectInfo(hx = 0, hy = 0, hz = 0, m = 0, isKinematic = false, mx = 0, my = 0, mz = 0) = new(hx, hy, hz, m, isKinematic, mx, my, mz)
end

mutable struct Physics 
  ids::Dict{Number, PhysicsObjectInfo}
  Physics() = new(Dict{Number, PhysicsObjectInfo}())
end

function handleMessage!(p::Physics, m::TICK)
  TS_BtStepSimulation()
  for (id, pinfo) in p.ids
    pos = TS_BtGetPosition(id)
    # TODO: this is a bad hack for working specifically with rectangular objects, needs improvement
    getEntityById(id).pos = XYZ(pos.x - pinfo.hx, pos.y - pinfo.hy, pos.z - pinfo.hz)
  end
  while true
    col = TS_BtGetNextCollision()
    if col.id1 == -1 && col.id2 == -1 break end
    e1 = getEntityById(col.id1)
    e2 = getEntityById(col.id2)
    handleMessage!(e1, col)
    handleMessage!(e2, col)
  end
end

function awake!(p::Physics)
  listenFor(p, TICK)
end

function shutdown!(p::Physics)
  unlistenFrom(p, TICK)
end

Basically there is a struct, PhysicsObjectInfo, that Starlight uses to keep track of the physics entities created using its API (which is not shown, but uses Telescope's Bullet-related APIs). The tick handler tells Bullet to update its internal state ("simulation"), then takes care of updating the positions of any objects that have moved as well as dispatching collision events.

Note that for now collision handlers (handleMessage! methods where the message has type TS_CollisionEvent) are invoked directly by the physics system rather than through the message dispatcher. Changing this would be complicated, since it requires the message dispatcher to know about "message recipients" or some such (since all it does currently is broadcast based on message type), which would also require changes to listenFor and unlistenFrom. However there are in fact plans to make those changes, since ideally all events would go through the dispatcher, and doing so would both simplify the existing physics code and make it easier to implement alternative physics subsystems.