Last active
November 3, 2024 04:25
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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