The first map's crates, barrels and cannon balls are rigid bodies the server steps and the app draws #18
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "task/3901-the-first-map-s-crates-barrels-and-canno"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Tracker: #3901
Step 2 of plan #3865 (Physics). Blender rigid bodies bake into the first map, the server steps them every tick, each snapshot carries their poses, and the client draws them between snapshots. The first map gains crates, barrels and cannon balls in front of its first spawn marker, which settle as the map loads. The player still walks through them until step 3.
What it delivers
Prefabs.
assets/prefabs/kenney.pytakes--centre, which puts a prefab's origin at its mesh's bounds' centre, where Blender centres a Box or Sphere body. It imported Kenney's Pirate Kit 2.1crate.glb,barrel.glbandcannon-ball.glb(CC0,kenney_pirate-kit.zip, 3154665 bytes, SHA-256 667ed2ca…c943, downloaded again on 2026-10-30) intoassets/prefabs/crate.blend,barrel.blendandcannon-ball.blend, each with its.md. The kit'scolormap.pngholds the texels ofassets/textures/ship-wreck_colormap.png, so kenney.py now finds a texture already underassets/textures/and the three draw that file. It also names the joined mesh for the model, which a scene links by name.The map.
assets/scenes/first_map_bodies.py, run once overfirst_map.blend:Spawn 1, along the way it faces. The ground there rose about 5° away from the marker, where a ball rolls off for good. Every vertex within 7.5 m of the clearing's centre takes the lowest of their heights, those out to 10.5 m blend back, and every prop stands a grid cell's diagonal inside the level ground. The marker's own ground is untouched;Propscollection, each mesh linked by relative path from its prefab: 10 crates as Box bodies of 20 kg (a tower of 3, a pyramid of 6, one 3 m up), 5 barrels as Convex Hull bodies of 60 kg (2 upright, 2 lying, one 2.5 m up) and 5 cannon balls as Sphere bodies of 30 kg (4 on the ground, one 2 m up).first_map.blend.mdrecords them.first_map_prefabs.py's clear now removes only its own prefabs' libraries, so rerunning it keeps the props: a rerun in an arm kept all 20 and placed the same 900 trees.The extract (
tools/bake/extract.py, intermediate version 6) takes a mesh object with an Active rigid body in the world's collection as a body. It records the body's shape sized as Blender sizes it, its mass, friction, restitution and both dampings, its evaluated pose, and its evaluated triangles in its own space with its scale applied. It reads the scene's gravity anduse_gravity. It takes a Passive Mesh body as map. It compares each rigid body with one made new in a reference scene byrigidbody.object_addof its type, its shape then set to the body's. It refuses, naming the datablock and the setting, every case D9 lists, a rigid body, Active or Passive, marked as water or as a collision proxy, a body its scale, its delta scale and its constraints together mirror, read by its world matrix's determinant, which the refusal names, and a Sphere or Capsule scaled unevenly in the world, by its scale, its delta scale or a constraint: Blender's simulation scales a Sphere's radius by the X scale alone and a Capsule's radius by its Y scale and its length by its Z scale, all read from the world matrix, so such a body would collide otherwise in hulken. A scale counts as even while its parts differ by at most 1e-5 of the largest, since a turned, evenly scaled object decomposes from its world matrix uneven by rounding (up to 5.3e-7 of its scale over 4000 random turns).rigid_body,rigid_body_constraint,rigidbody_world,gravityanduse_gravityhave left the lists it passes unread.The stage builds each hull with
hullOf. It writes each body's shape, mass, material, damping and start in hulken's axes (Blender's local Z becomes local +Y) and the scene's gravity into the world file (version 5), and each body's meshes in its own space into the render file (version 5). A body's triangles go into neither the collision world nor the static meshes.The server builds a
PhysicsWorldover its world's collision from the world file's bodies and gravity, and each tick steps its players, then the bodies, then posts the snapshot. The snapshot carries each body's index, position and unit quaternion (src/net/messages.sxdocuments the bytes). The client gives each body between its two kept snapshots, the position lerped and the orientation nlerped along the shorter arc.The renderer draws each body's meshes in the opaque pass, its vertex stage placing them by a rigid transform set per draw with
setVertexConstantsand turning their normals by its rotation. It shares the scene's fragment stage. The app loads the body meshes and draws them at the client's poses.README. The Scenes section says what a rigid body is in a scene.
Tests
tests/bake_extract.py: a case for each shape as Blender sizes it, a Capsule shorter than it is wide sized as a sphere, a Sphere scaled 1000 and turned, whose world scale decomposes as (1000, 1000, 999.99994), uneven by 6e-5 though only by 6e-8 of its scale, taken, a Capsule scaled evenly, a scaled and turned Box, a Convex Hull wedge scaled (1, 1, 2) whose normals are those of its scaled faces, what is read, the scene's gravity changed and off, a body whose mesh is linked fromcrate.blend, a Passive Mesh ground, the Passive Box, Passive Convex Hull, friction and restitution refusals, a baked cache, a Sphere scaled (1, 1, 1.00002), uneven by twice the tolerance, a Sphere of delta scale (1, 1, 2) and a Capsule a Limit Scale constraint holds at 2 along z refused, a body marked as water and the Passive Mesh ground marked as a collision proxy refused, a body scaled -1 along x and one of delta scale (-1, 1, 1) refused, the latter naming its world matrix's determinant, and each other refusal.tests/bake_stage.sx: bodies through the stage and both files, a Capsule turned in Blender lying along hulken's +Z by its local +Y, a hull built, the bodies' triangles kept out of the collision world and the static meshes, the gravity, both files read back, and a flat hull refused.tests/net_messages.sx: a snapshot with bodies round-trips, and one cut short in its last body is refused.tests/sim_bodies.sx: a crate dropped 3 m on flat ground falls, lands and sleeps in the server's snapshots; two servers fed the same commands send the same bytes for 600 ticks; the client's pose is lerped and nlerped along the shorter arc.tests/body_draws.sx: bodies turned about each axis, and a turned card drawing a cut-out checker, draw the same pixels as the same boxes and card placed statically, every pixel opaque, the card holding both texels and holes.tests/first_map_bodies.sx: the baked first map's props and shapes, each asleep within 10 s above the terrain under it, the tower and the pyramid within 5 cm of their starts, and each crate settled on the terrain drawing within 1 cm of it.Mutants
Each rule's code was changed in a
git archivearm of the head, one change at a time, and the tests that cover it were rerun. 85 mutants:hulken_collidefalse material, a water or proxy marker on a rigid body, an unevenly scaled Sphere or Capsule, the Sphere or the Capsule alone left out of it), only the water or only the proxy marker refused, the markers refused on Active bodies alone, the mirror read from the object's own scale, the evenness read from the object's own scale, from its scale times its delta scale, or on x and y alone, compared exactly, absolutely rather than relative to the scale, or within 1e-8, 1e-4, 1e-3, 1e-2, 1e-1 or half the scale, every scaled Sphere or Capsule refused, each size rule changed (box by whole dimensions, sphere by the least, capsule length without its caps, a capsule's half segment without its floor at 0), the scale left off the corners and the points, normals left unnormalised, normals only normalised and not divided by the scale, the rotation's components reordered,rigid_body,rigid_body_constraintorrigidbody_worldpassed unread again, gravity or mass compared rather than read,use_gravityignored, the preview settings compared, and the reference body's shape, type or world wrong. All killed bytests/bake_extract.py. The markers' ran at689103d; the mirror's and the evenness's, and 689103d's extract, which fails the new cases on their names, ran against the tests at6f5b54a.tests/bake_stage.sx,tests/first_map_bodies.sxortests/first_map_views.sx.tests/sim_bodies.sxortests/net_messages.sx. One survives as equivalent: the bodies stepped before the players, which nothing distinguishes until step 3 lets players touch bodies.tests/body_draws.sxortests/first_map_views.sx; the three cut-out ones bytests/body_draws.sxalone.tests/first_map_bodies.sx.Gates
fastat1c96f32: passed (gate run 888).fullat3d2ac98: passed, 34 of 34 (gate run 889).fullat22f4af3: passed, 34 of 34 (gate run 893).fullat689103d: passed, 34 of 34 (gate run 895).fullat6f5b54a: passed, 34 of 34 (gate run 898).For Agra's check
In the app, the props stand in the clearing in front of the first spawn marker; the crate, barrel and ball in the air fall and land; nothing should jitter at rest. A run of the built app with a print after its frame loop showed the server stepping 20 bodies, all asleep after about 5 s, and 20 drawn.