Physics and walkability
The region's physics engine is BulletSim. A place is judged by what happens when someone stands in it: whether they can get through the door, walk under the tree, climb the stair, and stand on the stone without being shoved.
A place must be walkable
1. Clear doorways for an avatar
At least 1 m wide and 2.2 m tall.
- Learned: a cottage door hung ajar across its doorway, and the first visitor tried the door and could not get in.
- Fix in place with
move_object,rotate_object(Euler degrees) andscale_objectrather than rebuilding and resetting every script.
2. Test walkability with a walker, not by eye
Walking a test through the world found faults no render showed: every mesh standing as its own bounding box, a knee-high fern bed that stopped a walker dead, 1959 solid ground-cover prims on one line.
Physics shapes for meshes
3. A mesh's physics defaults to its bounding box
spawn_mesh gives every mesh its bounding BOX as physics unless told otherwise.
- Learned: a tree was an invisible block you could not walk under, and an arched bridge a flat platform.
- Pass
physics="mesh"(the high mesh's own triangles) orphysics=<a simpler meshdata file>.
4. Give a complex model a SIMPLE custom physics shape
The engine does not hull a static mesh's custom physics block (proven with two thin fins as one physics block: rays fall between them to the ground). So a simple custom shape behaves as drawn:
- a bridge's rails carry two arched fins (no falling through);
- a flight of door steps has ONE WEDGE, walked like a slope, so no one catches a riser (
tools/build_doorstep.py); - a hazel has a 0.22 m stool pillar, so the outer branches are passable (
tools/shrub_pillars.py); - trees keep physics of the TRUNK only; leaves, water, smoke and ground cover stay phantom.
- CONFLICTS.md records an earlier note that claimed the engine hulls a mesh's shape.
5. Things you walk through are phantom
Ground cover, leaves, water, mist, smoke. tools/phantomize.py sets phantom live on named families without
rebuilding (a rebuild would reset state such as planting ages).
6. Decorative meshes get a tiny physics box
A mesh with no custom physics collides as its whole bounding box. Give decorative parts (a lantern's horn panes, a moss colony) a tiny physics box (buried, for things on the ground) so nothing collides with them, and make them phantom where they should be walked through (after the mesh has settled; see the next section).
Ghost bodies (the phantom race)
7. Setting a mesh phantom as it spawns can leave a solid, invisible body
A mesh set phantom in the same breath as spawning it (a skin script's llSetStatus(STATUS_PHANTOM, TRUE) in
state_entry) races the asynchronous mesh-asset fetch: the fetch callback rebuilds a body after the prim left
physics. It stays SOLID (a dropped block rests on it), raycasts still name the "phantom" object, and after a delete
it lingers nameless ('?', same local id).
- Learned: it shoved a visitor off a flagstone that was phantom, and made the "phantom" shrubs solid boxes.
- Fixed in
opensim-patches/bulletsim-ghost(a destroyed prim never rebuilds). A restart also clears every existing ghost. - On an unpatched OpenSim: set phantom a few seconds AFTER spawning a mesh, never in the same breath.
- Find ghosts with a raycast sweep for hits named
?.
Seeing physics
8. Use raycasts, not a walking NPC, to see what is solid
A walking NPC is a noisy judge: it stalls on slopes, and one stopped 4 m short of a tree with the whole tree lifted
away. WorldBridge raycast casts through the physics engine and names the object that owns each hit.
- The land filter does NOT hold in BulletSim; fly each ray above the highest ground along its own path.
- Measure a collision shape's WIDTH with a fan of parallel rays (a six-sided physics prism reads at its inscribed radius, r cos 30).
- Aim at a trunk's axis AT THAT HEIGHT (trunks lean), not at the root's.
- See:
tools/physics_audit.py(rays from 7 m out toward every tree's axis at knee and head height). - Learned: a lightning strike was first aimed at the lookout's weathervane (44 m); a raycast of every tall point showed the tower's iron fire basket (its rim at 59.4 m) was the tallest thing.
9. Prove a crossing with an NPC where an NPC can prove it
npc_create, npc_move to a target, poll avatars for its position.
- On a bridge, compare its z with the deck curve: a steady +1.1-1.3 m is feet on the deck; +1.8 was riding a lid across the two rails (the default bounding-box physics).
- Under a tree, read its closest approach to the trunk.
- A walker that does not move at all is BLOCKED near its start: list what stands on its line.
10. Test climbing with the real avatar and held keys
Move-to-target can fly, so an NPC "climbing" a stair proves nothing. Drive the real avatar with held movement keys (forward plus a turn held, sliding round the wall) and time it: step 3 to the roof walk in 10 s was the proof. Raycast the passage and the ramp heights too.
11. A walkable sheet that comes and goes
Give it its own mesh as the physics shape and toggle llSetStatus(STATUS_PHANTOM, ...) with its state (a frozen
pond: an avatar stood on the ice at 20.99 m over a bed at 17.3 m).
Resizing solid prims leaks memory
12. Any script that animates size makes the prim phantom first
Every PRIM_SIZE / llSetScale change on a SOLID prim makes BulletSim build a new collision shape that is never
freed (about 75 KB each). Eight chimney-smoke puffs resizing four times a second leaked 2.4 MB/s; the region reached
8.3 GB, the host swapped, and the region froze for 22 s and dropped the visitor. Moving does not leak; only resizing.
- Rule:
llSetStatus(STATUS_PHANTOM, TRUE)first instate_entryof any size-animating script. - See: operations.md for how it was found and how to find the next one.