Chapter 12: Physics
Updated: Sep 4, 2026
IWSDK integrates the Havok physics engine. Physics entities use PhysicsBody and PhysicsShape. PhysicsManipulation applies a one-time impulse or velocity change.
Configure physics in iwsdk.config.json:
{
"world": {
"features": {
"physics": {
"useWorker": true,
"updateFrequency": 60,
"interpolation": true
}
}
}
}
The default settings use a worker, run the simulation at 60 Hz, and interpolate render poses. The highest supported update frequency is 240 Hz. Set useWorker to false to run the same physics runtime on the main thread.
When physics is enabled, IWSDK registers PhysicsSystem, PhysicsBody, PhysicsShape, and PhysicsManipulation.
Create a transform entity, then add a shape and body:
import {
Mesh,
MeshStandardMaterial,
PhysicsBody,
PhysicsShape,
PhysicsShapeType,
PhysicsState,
SphereGeometry,
} from '@iwsdk/core';
const sphere = new Mesh(
new SphereGeometry(0.2),
new MeshStandardMaterial({ color: 0xa78bfa }),
);
sphere.position.set(0, 2, -2);
const entity = world.createTransformEntity(sphere);
entity.addComponent(PhysicsShape, {
shape: PhysicsShapeType.Sphere,
dimensions: [0.2, 0.2, 0.2],
});
entity.addComponent(PhysicsBody, {
state: PhysicsState.Dynamic,
});
PhysicsState has three values:
Static: An immovable body, such as a floor or wall.Dynamic: A body affected by forces, collisions, and gravity.Kinematic: A body moved by application code that can push dynamic bodies.
The serialized values are STATIC, DYNAMIC, and KINEMATIC.
PhysicsShapeType has seven values:
Sphere: Uses the radius in dimensions[0].Box: Uses width, height, and depth.Cylinder: Uses radius and height.Capsules: Uses radius and total height.ConvexHull: Builds a convex hull around the mesh.TriMesh: Uses the mesh geometry. Use it mainly for static bodies.Auto: Selects a shape from known Three.js geometry and otherwise uses a convex hull.
PhysicsShape also stores density, friction, and restitution. The defaults are 1, 0.5, and 0.
Apply an impulse or velocity
Add PhysicsManipulation to a body:
import { PhysicsManipulation } from '@iwsdk/core';
entity.addComponent(PhysicsManipulation, {
force: [0, 10, 0],
linearVelocity: [0, 0, 0],
angularVelocity: [0, 0, 0],
});
The system applies the values in one frame and then removes the component.
Combine physics with grabbing
A physics object can also use IWSDK interaction components:
import {
DistanceGrabbable,
RayInteractable,
} from '@iwsdk/core';
entity.addComponent(RayInteractable);
entity.addComponent(DistanceGrabbable);
Enable both physics and grabbing in the project manifest.
Author physics in a native scene
The physics example declares physics-dynamic-sphere in src/assets.ts. Its scene refers to that asset ID:
{
"version": "iwsdk.scene.v1",
"units": "meters",
"resources": {},
"nodes": [
{
"id": "dynamic-sphere",
"name": "Dynamic Sphere",
"content": {
"type": "asset",
"asset": "physics-dynamic-sphere"
},
"transform": {
"position": [-1, 0.95, -1.75]
},
"components": {
"PhysicsBody": {
"state": "DYNAMIC"
},
"PhysicsShape": {
"shape": "Sphere",
"dimensions": [0.2, 0.2, 0.2]
}
}
}
]
}
Use the native scene editor to check the object’s scale and contact with nearby surfaces.
Use setValue() to update reactive body fields:
entity.setValue(PhysicsBody, 'gravityFactor', 0);
entity.setValue(PhysicsBody, 'linearDamping', 0.5);
entity.setValue(PhysicsBody, 'angularDamping', 0.5);
The physics system sends those updates to the running simulation on the next frame.
An object falls through the floor
Symptom: A dynamic body does not collide with the environment.
Solution: Add PhysicsShape and PhysicsBody to both objects. Use PhysicsState.Static for a fixed floor. Check that the shape dimensions match the rendered objects.
Symptom: An impulse has no visible effect.
Solution: Use PhysicsState.Dynamic. Confirm that physics is enabled and that the entity has both required physics components.
A complex model is unstable
Symptom: Collisions are slow or produce unexpected motion.
Solution: Prefer ConvexHull or a basic shape for moving bodies. Reserve TriMesh for static geometry.