Skip to content

Instantly share code, notes, and snippets.

@PhoenixIllusion
Created September 12, 2025 15:49
Show Gist options
  • Save PhoenixIllusion/93cac435addfaed6f75bff2d6e7dc760 to your computer and use it in GitHub Desktop.
Save PhoenixIllusion/93cac435addfaed6f75bff2d6e7dc760 to your computer and use it in GitHub Desktop.
Tool that takes the raw Jolt Pointers of Bodies and the ContactConstraintManager and maps them out to F32/TypedArray raw access
class Reader {
constructor(ptr, buffer) {
this.ptr = ptr;
this.buffer = buffer;
this.offset = 0;
}
Float3() {
this.offset += 4 * 3;
return new Float32Array(this.buffer, this.ptr + this.offset - 12, 3);
}
Float4() {
this.offset += 4 * 4;
return new Float32Array(this.buffer, this.ptr + this.offset - 16, 4);
}
U32() {
this.offset += 4;
return new Uint32Array(this.buffer, this.ptr + this.offset - 4, 1)[0]
}
Skip(i) {
this.offset += i;
}
}
class RawBodyAccess {
constructor(joltBodyPtr, buffer) {
const reader = new Reader(joltBodyPtr, buffer);
this.position = reader.Float4();
this.rotation = reader.Float4();
this.aabox = {
min: reader.Float4(),
max: reader.Float4()
}
this.shape = reader.U32();
const motionProps = new Reader(reader.U32(), buffer);
this.motionProps = {
linearVelocity: motionProps.Float4(),
angularVelocity: motionProps.Float4(),
}
motionProps.Skip(4 * 4 * 2);
this.motionProps.force = motionProps.Float3()
this.motionProps.torque = motionProps.Float3()
}
}
class LockFreeHashMap {
constructor(ptr, buffer, isAssertBuild) {
const len = this.len = isAssertBuild ? 5 : 4;
this.buffer = buffer;
this.data = new Uint32Array(buffer, ptr, len)
this.mObjectStore = new Uint32Array(buffer, this.data[0], 1)[0]
}
get mBuckets() {
return new Uint32Array(this.buffer, this.data[this.len-3], this.data[this.len-2])
}
get mNumBuckets() {
return this.data[this.len-2]
}
GetKeyValues(startAddr, nextOffsetIndex, sliceSize) {
let address = startAddr;
const baseAddr = this.mObjectStore;
const result = []
let count = 0;
while(address != 0xffffffff && address !== undefined && count < 1e5) {
count++;
const buffer = new Uint32Array(this.buffer, baseAddr + address, sliceSize);
result.push(buffer);
address = buffer[nextOffsetIndex]
}
return result;
}
}
class ManifoldMap extends LockFreeHashMap {
constructor(ptr, buffer, isAssertBuild) {
super(ptr + 12, buffer, isAssertBuild)
}
GetAllKeyValues() {
const result = [];
this.mBuckets.filter( x => x !== 0xFFFFFFFF).forEach(addr => {
result.push(... this.GetKeyValues(addr, 4, 4 + 1 + 14))
})
}
}
class BodyPairMap extends LockFreeHashMap {
constructor(ptr, buffer, isAssertBuild) {
super(ptr + (isAssertBuild ? 32 : 28), buffer, isAssertBuild)
}
GetAllKeyValues() {
const results = [];
this.mBuckets.filter( x => x !== 0xFFFFFFFF).forEach(addr => {
results.push(... this.GetKeyValues(addr, 2, 2 + 1 + 6 + 1).map(buff => {
if(buff[9] !== 0xFFFFFFFF)
return {
body1: buff[0],
body2: buff[1],
mDeltaPosition: new Float32Array(this.buffer, buff.byteOffset + 12, 3),
mDeltaRotation: new Float32Array(this.buffer, buff.byteOffset + 24, 3),
mFirstCachedManifold: buff[9]
}
return null;
}).filter( x => x!== null))
})
return results;
}
}
class ManifoldCache {
constructor(ptr, buffer) {
const manifestCache = new Uint32Array(buffer, ptr, 12);
const isAssert = (manifestCache[3] == ptr && manifestCache[8] == ptr)
this.mCachedManifolds = new ManifoldMap(ptr, buffer, isAssert);
this.mCachedBodyPairs = new BodyPairMap(ptr, buffer, isAssert);
this.mIsFinalized = new Uint32Array(buffer, ptr + (isAssert ? 52 : 44), 1);
this.size = (isAssert ? 56 : 48)
}
}
class ContactConstraintManager {
constructor(ptr, buffer) {
const mCache_0 = new ManifoldCache(ptr + 4, buffer)
const mCache_1 = new ManifoldCache(ptr + 4 + mCache_0.size, buffer)
this.mCache = [mCache_0, mCache_1]
this.mCacheWriteIdx = new Uint32Array(buffer, ptr + 4 + mCache_0.size + mCache_1.size, 1);
this.mPhysicsSettings = new Uint32Array(buffer, ptr + 8 + mCache_0.size + mCache_1.size, 1)[0];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment