Skip to content

Instantly share code, notes, and snippets.

@zvodd
Last active November 3, 2024 04:25
Show Gist options
  • Save zvodd/2d9ebfaa59e6747ce4a3f5bcd5cbad6b to your computer and use it in GitHub Desktop.
Save zvodd/2d9ebfaa59e6747ce4a3f5bcd5cbad6b to your computer and use it in GitHub Desktop.
Do physics sim asynchronously / not locked to renderer. Absolutely borked way to use havok_wasm.
import HavokPhysics, {
HavokPhysicsWithBindings,
Result, HP_ShapeId
} from "@babylonjs/havok";
// Global variable to store the initialized Havok physics engine
globalThis['HK'] = (await HavokPhysics()) as HavokPhysicsWithBindings;
const HK : HavokPhysicsWithBindings = globalThis.HK;
// Define helper functions for common physics types (Vector3, Quaternion, etc.)
// based on the HavokPhysics.d.ts definitions
type Vector3 = [number, number, number];
type Quaternion = [number, number, number, number];
// Function to create a box shape
function createBoxShape(halfExtents: Vector3): [Result, HP_ShapeId] {
const center = [0, 0, 0]; // Center of the box
const rotation = [1, 0, 0, 0]; // Identity quaternion (no rotation)
return HK.HP_Shape_CreateBox(center, rotation, halfExtents);
}
// Function to create a sphere shape
function createSphereShape(radius: number): [Result, HP_ShapeId] {
const center = [0, 0, 0]; // Center of the sphere
return HK.HP_Shape_CreateSphere(center, radius);
}
// Function to create a dynamic rigid body
async function createPhysBody(shapeId: HP_ShapeId, motionType:HK.MotionType): Promise<HP_BodyId> {
const [result, bodyId] = await HK.HP_Body_Create();
if (result != HK.Result.RESULT_OK){
throw result
}
await HK.HP_Body_SetShape(bodyId, shapeId);
await HK.HP_Body_SetMotionType(bodyId, motionType);
return bodyId;
}
async function main() {
// Create a box shape for the small cube
const smallCubeHalfExtents = [0.5, 0.5, 0.5]; // Half the size of the cube
const [result, smallCubeShapeId] = await createBoxShape(smallCubeHalfExtents);
if (result !== HK.Result.RESULT_OK) {
throw new Error(`Failed to create small cube shape: ${result}`);
}
// Create a dynamic rigid body for the small cube
const smallCubeBodyId = await createPhysBody(smallCubeShapeId, HK.MotionType.DYNAMIC);
// Create a box shape for the large cube used as ground.
const largeCubeHalfExtents = [10, 10, 10]; // Half the size of the cube
const [result2, largeCubeShapeId] = await createBoxShape(largeCubeHalfExtents);
if (result2 !== HK.Result.RESULT_OK) {
throw new Error(`Failed to create large cube shape: ${result}`);
}
// Create a static rigid body for the large cube (doesn't need physics simulation)
const largeCubeBodyId = await createPhysBody(largeCubeShapeId, HK.MotionType.STATIC)
// Set the initial position of the small cube (5 units above the large cube)
const smallCubePosition = [0, 5, 0];
await HK.HP_Body_SetPosition(smallCubeBodyId, smallCubePosition);
// Create a world
const [result3, worldId] = await HK.HP_World_Create();
if (result3 !== HK.Result.RESULT_OK) {
throw new Error(`Failed to create world: ${result}`);
}
await HK.HP_World_SetGravity(worldId, [0, -9.81, 0]); // Set gravity
// Add bodies to the world
await HK.HP_World_AddBody(worldId, smallCubeBodyId, false);
await HK.HP_World_AddBody(worldId, largeCubeBodyId, false);
// Record the initial position and rotation of the small cube
const positions: Vector3[] = [];
const rotations: Quaternion[] = [];
//@ts-ignore _-_
positions.push(smallCubePosition);
rotations.push([1,0,0,0]); // Identity quaternion (no rotation)
// Define the number of simulation steps and time step
const numSteps = 100;
const timeStep = 1 / 60; // Adjust time step as needed
// Perform physics simulation for the specified number of steps
for (let i = 0; i < numSteps; i++) {
// Step the physics world
await HK.HP_World_Step(worldId, timeStep);
// Get the updated position and rotation of the small cube
const newPosition = await HK.HP_Body_GetPosition(smallCubeBodyId);
const newRotation = await HK.HP_Body_GetOrientation(smallCubeBodyId);
// Record the updated position and rotation
positions.push(newPosition);
rotations.push(newRotation);
}
// Release the world and bodies
await HK.HP_Body_Release(smallCubeBodyId);
await HK.HP_Body_Release(largeCubeBodyId);
await HK.HP_World_Release(worldId);
// Now you have the positions and rotations in the `positions` and `rotations` arrays
console.log("Positions:", positions);
console.log("Rotations:", rotations);
}
main().catch(console.error);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment