Collisions do not work
For my test case, I made a 3x1x3 floor with mass 0 centered on (0, 0, 0), and a 1x1x1 cube with mass 1 at (0, 2, 0). I created a PhysicsWorld and added both with addRigidBody, but if I keep calling world.stepSimulation(), I can see the cube phase through the floor.
// MotionState implementation:
class GameMotionState(private val go: GameObject) : MotionState {
override fun getWorldTransform(worldTransform: Transform) {
worldTransform.basis put Mat3(go.transform.rotation.bullet()) // transforms between my vec/quat/mat and bullet types
worldTransform.origin put go.transform.translation.bullet()
}
override fun setWorldTransform(worldTransform: Transform) {
go.transform.translation = Vector3(worldTransform.origin)
go.transform.rotation = Quaternion(worldTransform.basis)
}
}
// RigidBody creation:
internal fun makeRigidBody(): RigidBody {
val btShape = shape.getShape(gameObject.transform.scale) // creates a CollisionShape stretched with the scale from transform
var inertia = Vec3(0f)
if (mass == 0f) {
// apply inertia if needed
inertia = Vec3().also { btShape.calculateLocalInertia(mass, it) }
}
val body = RigidBody(RigidBody.RigidBodyConstructionInfo(
mass,
GameMotionState(gameObject),
btShape,
inertia
))
return body
}
// World creation and object handling:
class PhysicsSystem {
val world: DiscreteDynamicsWorld
init {
val config = DefaultCollisionConfiguration()
val dispatcher = CollisionDispatcher(config)
val pairCache = DbvtBroadphase()
val solver = SequentialImpulseConstraintSolver()
world = DiscreteDynamicsWorld(dispatcher, pairCache, solver, config)
world.gravity = Vec3(0f, -1f, 0f) // Slow enough to get clear video; see link at the bottom
}
fun update(delta: Float) {
world.stepSimulation(delta, 10)
}
private val map = mutableMapOf<PhysicsObject, RigidBody>()
fun addObject(physicsObject: PhysicsObject) {
val body = map.getOrPut(physicsObject) { physicsObject.makeRigidBody() }
world.addRigidBody(body)
}
}
val floor = addObject("floor") {
transform.scale = Vector3(3f, 1f, 3f) // make floor big
addComponent<PhysicsObject> {
mass = 0f // no mass, it's static
physics.addObject(this)
}
}
val cube = addObject("cube") {
transform.rotation = Quaternion.IDENTITY.rotate(Vector3(PI / 4)) // apply some rotation; seems to be lost after physics tick?
transform.translation = Vector3(0f, 2f, 0f) // place 2 units above floor
addComponent<PhysicsObject> {
mass = 1f
physics.addObject(this)
}
}
Clip: https://github.com/user-attachments/assets/62a68cbd-c69e-446e-97ba-3bc95b067638
Update: After switching to worldTransform.set/getRotation, it seems to actually collide, but now collisions behave a bit strange:
A cube without rotation will go into space, and a cube with rotation sort of seems to slide/bounce off (depending on number of substeps), instead of simply rotating to be flat on the surface.
While not in the video, it seems lowering the gravity makes the cube bounce off the floor before even making contact. Also, if I instead extend the floor to 30x1x30, it seems the angled cube simply phases through it.