Physics simulation is where the magic happens. Crate slides? Cloth drapes? Particles scatter? It's all in the code. If it lags, your game chokes.
omni_physics_simulation is a C++ engine wrapped in Python via pybind11. It handles rigid bodies, joints, collisions, and GPU-accelerated particles — all integrated with NEPA AI Game Scene Workspace for accurate level generation.
What It Does
import omni_physics_simulation as phys
world = phys.PhysicsWorld(
gravity=(0, -9.81, 0),
substeps=4,
time_step=1/60,
solver="TGS"
)
# Four main systems
rigid_body_sim = world.rigid_body_system
constraint_system = world.constraint_system
particle_system = world.particle_system
collision_system = world.collision_system
C++ does the heavy lifting on CPU or GPU, Python just calls the API.
Rigid Body Dynamics
Common use case: objects that move and collide.
import omni_physics_simulation as phys
import numpy as np
world = phys.PhysicsWorld(gravity=(0, -9.81, 0), substeps=4)
rb = world.rigid_body_system
# Box (1m × 1m × 1m, 10kg) on a floor
box_id = rb.create_box(
half_extents=(0.5, 0.5, 0.5),
mass=10,
position=(0, 5, 0),
rotation=(0, 0, 0, 1),
restitution=0.3,
friction=0.6
)
floor_id = rb.create_box(
half_extents=(10, 0.1, 10),
mass=0,
position=(0, 0, 0)
)
# Push the box
rb.apply_impulse(box_id, (5, 0, 2), (0, 0, 0))
for frame in range(300):
world.step()
pos = rb.get_position(box_id)
rot = rb.get_rotation(box_id)
if frame % 30 == 0:
print(f"Frame {frame}: pos={pos}, rot={rot}")
Constraint System
Joints for complex interactions like hinges and springs.
door_body = rb.create_box(
half_extents=(0.05, 1, 0.5),
mass=5,
position=(1, 1, 0)
)
wall_anchor = rb.create_box(
half_extents=(0.05, 1, 0.05),
mass=0,
position=(1, 1, 0)
)
hinge = world.constraint_system.create_hinge(
body_a=wall_anchor,
body_b=door_body,
pivot_point=(1, 1, 0.5),
axis=(0, 1, 0),
lower_angle=-np.pi / 2,
upper_angle=np.pi / 2
)
rb.apply_torque(door_body, (0, 15, 0))
spring = world.constraint_system.create_spring(
body_a=box_id,
body_b=door_body,
stiffness=100,
damping=5,
rest_length=2
)
GPU Particle Systems
For effects like fire, smoke, and water.
fire_system = world.particle_system.create_emitter(
position=(0, 0.5, 0),
emission_rate=500,
particle_lifetime=(0.5, 2),
initial_velocity_min=(-0.5, 2, -0.5),
initial_velocity_max=(0.5, 5, 0.5),
gravity_scale=-0.5,
size_over_life=[(0, 0.05), (0.5, 0.08), (1, 0.0)],
color_over_life=[
(0, (1, 0.8, 0, 1)),
(0.5, (1, 0.3, 0, 0.8)),
(1, (0.2, 0.2, 0.2, 0))
],
backend="cuda"
)
for frame in range(600):
world.step()
positions = world.particle_system.get_positions(fire_system)
colors = world.particle_system.get_colors(fire_system)
sizes = world.particle_system.get_sizes(fire_system)
# Pass to your renderer
Collision Detection
Raycasting and overlap queries.
collision = world.collision_system
hit = collision.raycast(
origin=(0, 10, 0),
direction=(0, -1, 0),
max_distance=100
)
if hit:
print(f"Hit body: {hit.body_id}")
print(f"Point: {hit.point}")
print(f"Normal: {hit.normal}")
print(f"Distance: {hit.distance}")
nearby = collision.overlap_sphere(
center=(0, 0, 0),
radius=5
)
print(f"Bodies within 5m: {nearby}")
rb.set_ccd_enabled(box_id, True) # prevents tunneling
Procedural Level Validation
Simulate levels to catch physics issues before they hit players.
def validate_level_physics(level_data):
world = phys.PhysicsWorld(gravity=(0, -9.81, 0), substeps=8)
rb = world.rigid_body_system
body_ids = {}
for obj in level_data["objects"]:
if obj["type"] == "static":
body_ids[obj["id"]] = rb.create_box(
half_extents=obj["half_extents"],
mass=0,
position=obj["position"],
rotation=obj["rotation"]
)
else:
body_ids[obj["id"]] = rb.create_box(
half_extents=obj["half_extents"],
mass=obj.get("mass", 1),
position=obj["position"],
rotation=obj["rotation"]
)
for _ in range(180):
world.step()
issues = []
for obj in level_data["objects"]:
if obj["type"] == "static":
continue
final_pos = rb.get_position(body_ids[obj["id"]])
placed_pos = obj["position"]
drift = np.linalg.norm(np.array(final_pos) - np.array(placed_pos))
if drift > 0.5:
issues.append({
"object_id": obj["id"],
"issue": "unstable_placement",
"drift_meters": drift,
"final_position": final_pos
})
return {
"valid": len(issues) == 0,
"issues": issues,
"issue_count": len(issues)
}
Performance
On a Ryzen 9 3950X + RTX 3090:
| Scenario | Bodies | Particles | Step Time | |---|---|---|---| | Simple falling objects | 100 | 0 | 0.8ms | | Complex stacking | 500 | 0 | 3.2ms | | Fire effect | 0 | 10,000 | 0.4ms (GPU) | | Full game scene | 200 | 5,000 | 2.1ms |
All within real-time for 60fps.
NEPA AI Game Scene Workspace integrates omni_physics_simulation directly into its procedural level generation pipeline, ensuring no floating or clipping issues before export.
→ Get the Game Scene Workspace at axon.nepa-ai.com/shop/game-scene-workspace



