
Exposes Jolt Physics' rigid-body, character, vehicle, soft-body and ragdoll simulation as a near-complete, header-generated API with idiomatic bindings, ownership rules, samples and docs.
kolt is Jolt Physics for Kotlin Multiplatform: the same rigid body, character,
vehicle, soft body and ragdoll simulation on Android, iOS, the JVM and the Web (JS & Wasm), from one
API in commonMain.
[!NOTE] Unofficial project. A community-maintained Kotlin wrapper around Jolt Physics, not affiliated with or endorsed by its authors.
Jolt.init()
val temp = TempAllocatorImpl(10 * 1024 * 1024)
val jobs = JobSystemThreadPool(2048, 8, 1)
// One object layer in one broad phase layer, colliding with itself.
val broadPhaseLayers = BroadPhaseLayerInterfaceTable(1, 1).also { it.mapObjectToBroadPhaseLayer(0, BroadPhaseLayer(0)) }
val layerPairs = ObjectLayerPairFilterTable(1).also { it.enableCollision(0, 0) }
val objectVsBroadPhase = ObjectVsBroadPhaseLayerFilterTable(broadPhaseLayers, 1, layerPairs, 1)
val system = PhysicsSystem().also { it.init(1024, 0, 1024, 1024, broadPhaseLayers, objectVsBroadPhase, layerPairs) }
val bodies = system.bodyInterface
val sphere = SphereShape(0.5f, null)
val ball = BodyCreationSettings(sphere, Vec3(0f, 10f, 0f), Quat.IDENTITY, EMotionType.Dynamic, 0).use { settings ->
bodies.createAndAddBody(settings, EActivation.Activate)
}
repeat(60) { system.update(1f / 60, 1, temp, jobs) }
println(bodies.getPosition(ball)) // about 5 m lower, a second laterIf you know Jolt, you know kolt: the classes, methods and enums are Jolt's, in the package of their header's directory
(physics.body.BodyInterface). Getting Started continues this example, down to closing
what it created.
Every platform runs on one C API generated from Jolt's C++ headers, and the Kotlin API is generated once, in
commonMain, on top of it. The API and its behavior are the same everywhere:
| Platform | Targets | How Kotlin reaches Jolt |
|---|---|---|
| Android |
arm64-v8a, x86_64, minSdk 24 |
JNI, libkolt.so in the library's jniLibs |
| iOS |
iosArm64, iosSimulatorArm64, iOS 15 |
Kotlin/Native, linked statically |
| JVM | macOS arm64; Linux and Windows, x64 and arm64 | JNI, libkolt out of a runtime jar per platform |
| Web |
js, wasmJs, in a browser |
Jolt compiled to wasm with Emscripten, kolt.js + kolt.wasm
|
What differs per platform (loading the native library, threads on the web) is in Platform Notes.
kolt is on Maven Central: one dependency, native code included on every target.
commonMain.dependencies { implementation("io.github.erkko68.kolt:kolt:0.1.0") }On the web, serve kolt.js and kolt.wasm (each release's assets) next to your bundle; see
Platform Notes.
To build it from source, clone with the Jolt submodule and run the tests:
git clone --recurse-submodules https://github.com/Erkko68/kolt.git
./gradlew :kotlin:kolt:jvmTest :kotlin:kolt:iosSimulatorArm64TestThe toolchain each target needs is listed in Getting Started.
samples/ is a wall of cubes to push over, simulated by kolt and rendered by
filament-kmp in Compose Multiplatform, on every target. Its web build is live
at erkko68.github.io/kolt; samples/README.md has the
commands for the others.
The public API follows Jolt's C++ API, the one Jolt's documentation and headers describe, adapted only where Kotlin has its own shape:
GetX/SetX pairs and fields (system.gravity, settings.motionType); statics lose their
s (ConstraintSettings::sRestoreFromBinaryState is ConstraintSettings.restoreFromBinaryState).close() gives back what Kotlin created; what Jolt keeps is borrowed, and closing it does nothing.object : ContactListener() { override fun onContactAdded(…) }. A std::function is a Kotlin
lambda.getPositionAndRotation(id) returns a Pair<Vec3, Quat>; an error result throws
NativeException.c/api-coverage.txt names the rest.The full set of rules is in API Conventions.
kolt is Jolt Physics for Kotlin Multiplatform: the same rigid body, character,
vehicle, soft body and ragdoll simulation on Android, iOS, the JVM and the Web (JS & Wasm), from one
API in commonMain.
[!NOTE] Unofficial project. A community-maintained Kotlin wrapper around Jolt Physics, not affiliated with or endorsed by its authors.
Jolt.init()
val temp = TempAllocatorImpl(10 * 1024 * 1024)
val jobs = JobSystemThreadPool(2048, 8, 1)
// One object layer in one broad phase layer, colliding with itself.
val broadPhaseLayers = BroadPhaseLayerInterfaceTable(1, 1).also { it.mapObjectToBroadPhaseLayer(0, BroadPhaseLayer(0)) }
val layerPairs = ObjectLayerPairFilterTable(1).also { it.enableCollision(0, 0) }
val objectVsBroadPhase = ObjectVsBroadPhaseLayerFilterTable(broadPhaseLayers, 1, layerPairs, 1)
val system = PhysicsSystem().also { it.init(1024, 0, 1024, 1024, broadPhaseLayers, objectVsBroadPhase, layerPairs) }
val bodies = system.bodyInterface
val sphere = SphereShape(0.5f, null)
val ball = BodyCreationSettings(sphere, Vec3(0f, 10f, 0f), Quat.IDENTITY, EMotionType.Dynamic, 0).use { settings ->
bodies.createAndAddBody(settings, EActivation.Activate)
}
repeat(60) { system.update(1f / 60, 1, temp, jobs) }
println(bodies.getPosition(ball)) // about 5 m lower, a second laterIf you know Jolt, you know kolt: the classes, methods and enums are Jolt's, in the package of their header's directory
(physics.body.BodyInterface). Getting Started continues this example, down to closing
what it created.
Every platform runs on one C API generated from Jolt's C++ headers, and the Kotlin API is generated once, in
commonMain, on top of it. The API and its behavior are the same everywhere:
| Platform | Targets | How Kotlin reaches Jolt |
|---|---|---|
| Android |
arm64-v8a, x86_64, minSdk 24 |
JNI, libkolt.so in the library's jniLibs |
| iOS |
iosArm64, iosSimulatorArm64, iOS 15 |
Kotlin/Native, linked statically |
| JVM | macOS arm64; Linux and Windows, x64 and arm64 | JNI, libkolt out of a runtime jar per platform |
| Web |
js, wasmJs, in a browser |
Jolt compiled to wasm with Emscripten, kolt.js + kolt.wasm
|
What differs per platform (loading the native library, threads on the web) is in Platform Notes.
kolt is on Maven Central: one dependency, native code included on every target.
commonMain.dependencies { implementation("io.github.erkko68.kolt:kolt:0.1.0") }On the web, serve kolt.js and kolt.wasm (each release's assets) next to your bundle; see
Platform Notes.
To build it from source, clone with the Jolt submodule and run the tests:
git clone --recurse-submodules https://github.com/Erkko68/kolt.git
./gradlew :kotlin:kolt:jvmTest :kotlin:kolt:iosSimulatorArm64TestThe toolchain each target needs is listed in Getting Started.
samples/ is a wall of cubes to push over, simulated by kolt and rendered by
filament-kmp in Compose Multiplatform, on every target. Its web build is live
at erkko68.github.io/kolt; samples/README.md has the
commands for the others.
The public API follows Jolt's C++ API, the one Jolt's documentation and headers describe, adapted only where Kotlin has its own shape:
GetX/SetX pairs and fields (system.gravity, settings.motionType); statics lose their
s (ConstraintSettings::sRestoreFromBinaryState is ConstraintSettings.restoreFromBinaryState).close() gives back what Kotlin created; what Jolt keeps is borrowed, and closing it does nothing.object : ContactListener() { override fun onContactAdded(…) }. A std::function is a Kotlin
lambda.getPositionAndRotation(id) returns a Pair<Vec3, Quat>; an error result throws
NativeException.c/api-coverage.txt names the rest.The full set of rules is in API Conventions.