Modules / Physics & movement

ragdoll3dplugin

A limp body on a Mixamo skeleton, stepped on the sim's clock, the same on every seat.

Putting it in a scene

ragdoll3d has no row and no prefab of its own: its numbers never change, so they are the scene's world.ragdoll3d. It has two modes. Without physics, a body is stepped in the page only, once per sim step and never per frame, so every seat shows the same body. List it after the plugin that gives it model and pose (see Mods), which makes and poses its models in its own tick. render3d may be listed anywhere. The scene's engine prefab gives dt, the seconds in a step. With physics: true, a body is a box3d ragdoll on the server instead (see The physics mode).

"plugins": ["loader", "scenemanager", "player", "terrain3d", "scatter3d", "anim", "ragdoll3d", "render3d"],
"world": {
  "ragdoll3d": {
    "mods": { "model": "anim", "pose": "anim", "land": "terrain3d", "solids": "scatter3d", "gravity": "walker" },
    "bones": {
      "hips": "Hips", "spine": "Spine2", "head": "Head",
      "armL": "LeftArm", "forearmL": "LeftForeArm", "handL": "LeftHand",
      "armR": "RightArm", "forearmR": "RightForeArm", "handR": "RightHand",
      "uplegL": "LeftUpLeg", "legL": "LeftLeg", "footL": "LeftFoot",
      "uplegR": "RightUpLeg", "legR": "RightLeg", "footR": "RightFoot"
    },
    "damp": 0.98, "iter": 6, "sweeps": 30, "radius": 0.08, "vmax": 0.5, "friction": 0.3, "spread": 0.35,
    "limits": { "elbow": [20, 175], "knee": [20, 175], "spine": [100, 175], "hip": [30, 180], "shoulder": [20, 180] },
    "still": 0.002, "calm": 20, "settle": 3
  }
}

A game's rule kills a body with die on the step its row dies, counts the steps it lies with lie, and stands it again with rise, the same calls in either mode. They write the fields under The dying row. The body is built from where the row died and lies until its limp clears or its row ends. anim stops drawing a row whose limp is true, and puts a row that gets up back at its rest.

Properties

Read from world.ragdoll3d. Without physics, the numbers are checked whenever their content changes. A body takes the numbers as they stand when it is built and keeps them while it lies, so an edit reaches the next body and never a body part way down.

.physics : boolean

True for the physics mode, where a body is a box3d ragdoll the server makes. The page then reads none of the numbers below and asks none of the page's mods.

.mods : { model, pose, land, solids, gravity, bodies? }

The plugins that provide what the body lies on and how it is posed, and the other bodies a shot meets (see Mods).

.bones : { [role]: string }

For each of the 15 roles, the suffix of the name of the bone that joint is: hips, spine (the upper spine), head, armL, forearmL, handL, armR, forearmR, handR, uplegL, legL, footL, uplegR, legR, footR. Every role needs a suffix. A repeated bone name that three.js's glTF loader makes unique with _1, _2, … is matched without that ending.

A joint is the first bone under a skeleton copy whose name ends with its role's suffix. A Mixamo model's meshes can each bind a skeleton copy of their own, so a copy is every bone under a bone with no bone above it, and every copy that holds all 15 joints is driven. The joints are read from the copy whose hips' name has no _N, the copy anim's clips name, wherever it stands in the model, or the first when every copy's has one. A model with no whole copy cannot be used.

.damp : number

The share of a step's velocity kept into the next. Above 0 and at most 1.

.iter : number

Passes a step, each reading the ground under every point once. A whole number from 1.

.sweeps : number

Rounds of the sticks, the limits, the ground and the solids in each pass. A whole number from 1. At iter 6 and sweeps 30, every limit holds within 0.1° after every step, landings included.

.radius : number

Metres: how far a joint's point stays off the ground and out of a solid. At least 0.

.vmax : number

Metres a step: the most a point moves by its velocity. Above 0. It is also the distance along x and along z over which the ground's slope is read.

.friction : number

The share of a ground-touching point's speed across the ground taken each step. From 0 to 1.

.spread : number

The share of the blow's speed that every point but the one struck is given. At least 0.

.limits : { elbow, knee, spine, hip, shoulder }

Each [least, most] in degrees, with 0 ≤ least ≤ most ≤ 180. A limit bounds the angle at the middle point of three joints, left and right alike: elbow is arm, forearm, hand; knee is up-leg, leg, foot; spine is hips, upper spine, head, so it is the bend of the spine and the neck, since the torso below the upper spine is a slab; hip is upper spine, up-leg, leg; shoulder is hips, arm, forearm. A most just short of 180 stops a hinge folding backwards, and a most of 180 is no bound.

.still : number

Metres a step. A body whose every point moves less than this for calm steps running sleeps. Above 0.

.calm : number

Steps, a whole number from 1.

.settle : number

Seconds: the most of its fall a body is stepped through. It is a hard stop: a body never steps past it and sleeps there, so a seat that arrives after it draws the settled body exactly. Above 0.

The dying row

die writes these on the step the row dies. The rule leaves pos and yaw alone until the row stands again, so a seat that first sees it late builds the body from where it died.

FieldMeaning
limpTrue while the body lies. A row whose limp is true is the ragdoll's.
limpForThe steps since it went limp: 0 as it dies, one more each step lie is called. A rule reads no step counter, so the row counts its own. A limpFor below the last one seen is a new death, and the body is built again.
blow{ dir: [x, z], speed, height }: the way it was struck across the ground (it is normalised), its speed in m/s, and its height in metres above the row's pos. Without physics, the point whose height is nearest pos[1] + height (the first in role order on a tie) gets speed, and the rest get speed · spread, since a kick on one joint of a braced body leaves it standing like a statue.
pose{ clip, clipT }: the clip and the playhead it died in, its clip and clipT. A row anim has not played yet dies in its stance's still clip at 0. The body is built from the model drawn in that pose.
ragdollThe physics mode only: bone name to the id of its bone row, and null once the body has stood again.

How a body falls

Without physics, a body is 15 points, one for each joint. Twenty sticks join them, and each keeps the length it had at death: the 14 bones between the points, and braces shoulder to shoulder, hip to hip, hips to each shoulder and the upper spine to each hip, so the torso stays a slab. The limits bend the joints. Once per sim step each point moves by its velocity times damp, cut to vmax, then falls by gravity. It is then lifted onto the ground, pushed out of every solid across the ground to the solid's radius plus radius, and held by the sticks and limits, in iter passes of sweeps rounds. A point that was lifted touches the ground, and loses friction of its speed across it. Gravity is read when the body is built, from the gravity mod for the row's kind, so a body falls at the gravity it walked under.

A row is owed the smaller of limpFor and settle / dt steps, and each frame takes the steps it is owed, so a seat that sees the row late catches up to the body every seat shows. A body is built again when the model mod hands back a model other than the one it was built on, as anim does when its rig changes.

After each step the hips take the pelvis's turn since death and stand on the hips point. The neck, the shoulders, the arms, the forearms, the up-legs and the legs are turned toward their children by the shortest arc, starting from their rotation at death, so their twist is the death pose's. Every other bone keeps its rotation at death. All driven skeleton copies are written alike.

The physics mode

With physics: true, a body that dies becomes a box3d ragdoll on the server: one box3d body for each bone, joined at its joints, so it falls, is thrown and lands as rigid bodies do, the same on every seat. The scene's sim lists the bone and bonejoint kinds from #plugins/ragdoll3d/ragdoll3d.sim.ts and gives each a prefab, whose values die writes over. box3d is handed both kinds by naming ragdoll3d in world.box3d.mods.kinds. A body's rig must carry the ends that anim's bake measures. The page takes the model from anim.

"plugins": ["loader", "scenemanager", "player", "terrain3d", "box3d", "anim", "ragdoll3d", "render3d"],
"world": {
  "box3d": { "subStepCount": 4, "static": [], "kinds": {}, "chunk": { "count": 33, "cell": 4 },
             "mods": { "ground": "terrain3d", "kinds": ["ragdoll3d"] } },
  "ragdoll3d": { "physics": true }
},
"prefabs": {
  "bone": {},
  "bonejoint": {}
}

A bone is a capsule from one end of the bone to the other as the body stood in its pose, of the bone's radius below. Every joint is the same ball joint where the child bone starts: the child swings at most 60° from the way it pointed at death and rolls about itself at most 30° either way. Each bone is a dynamic body with linear damping 0.05, angular damping 0.4 and a sleep threshold of 0.05, its capsule of density 1000, friction 0.8, restitution 0 and rolling resistance 0.05. No bone collides with another bone.

BoneModel bone suffixRadius, metres
torsoHips0.13
headHead0.1
armL, armRLeftArm, RightArm0.05
forearmL, forearmRLeftForeArm, RightForeArm0.045
handL, handRLeftHand, RightHand0.04
uplegL, uplegRLeftUpLeg, RightUpLeg0.075
legL, legRLeftLeg, RightLeg0.06
footL, footRLeftFoot, RightFoot0.045

The joints join the torso to the head, each arm and each up-leg, each arm to its forearm and each forearm to its hand, each up-leg to its leg and each leg to its foot.

RowFields
bonebox3d's pos, rot, vel, spin and awake; of, the body's id; bone, its name; half, half its length between the capsule's two centres; radius.
bonejointbox3d's a and b, the parent bone's row and the child's; joint, its box3d joint entry.

The page turns each bone of the model to follow its body every frame, from the pose it stood in when the ragdoll was first drawn, and moves the hips with the torso's body. Every skeleton copy of a Mixamo model follows the first.

Methods

Rules

From #plugins/ragdoll3d/ragdoll3d.sim.ts.

die( w, me, blow, hits? )

Kills a body, on the step it dies: writes limp true, limpFor 0, blow and pose on its row. A body already limp is left as it lies. In the physics mode it also spawns the body's bone and joint rows and writes ragdoll. Every bone starts at the row's own vel. With hits, each { bone, point, impulse } is a push of impulse N·s at the world point on that bone's body, applied on the step its body is made. Without hits, the bone whose middle stands nearest pos[1] + blow.height is set moving at blow.speed along blow.dir on top of that.

lie( me )

Adds one to limpFor. A rule calls it each step its body lies.

rise( w, me )

Stands a body again, and is called before its row ends. Its bone and joint rows end and its ragdoll is null, and limp, limpFor, blow and pose go back to false, 0, null and null.

capsules( w, me ) : { bone, a, b, radius }[]

A standing body's bones as capsules in the world, this step of its clip: each bone of the table above from one end to the other, a and b in metres, of its radius.

On the page

Through plugins.ragdoll3d.

body( id ) : { points, steps, asleep } | undefined

Without physics, the body of the row with that id as it stands: each role's point, the steps taken, and whether it sleeps. Undefined when the row has no body.

Mods

Name them in world.ragdoll3d.mods. Only model and pose hand back what their plugin changes in the frame, which is why the plugin that provides them is listed before ragdoll3d. A mod named for a plugin the scene does not list also fails, except gravity, which reads the scene's world and so needs no plugin. The physics mode asks only bodies.

  • anim
    model and pose, both required without physics. model(plugins, id) is the row's model root, or undefined before it is built. pose(plugins, id, clip, t) is the row's model drawn in one clip alone, at t, from its rest.
  • terrain3d
    land: land(plugins) is the ground the body lies on, { height(x, z) }, or undefined until there is one. Until there is a ground no body steps, and a scene that names none has none, so its bodies lie as they died.
  • scatter3d
    solids: solids(plugins, x, z, r) is the circles { x, z, radius } the body is pushed out of, each a solid upright without end. A scene that names none has no solids.
  • walker
    gravity, required without physics: gravity(world, kind) is the m/s² a body of that kind falls at, walker's world.walker.kinds[kind].gravity, or undefined for a kind it has none for. A body of a kind it gives no gravity cannot fall.

bodies is a server function, (w) → { id, kind, pos, shapes }[]: the other bodies ragdoll3d's mod for hitscan3d hands on beside its own. It is read from the named plugin's mod for ragdoll3d, and no module ships one, so it is a game's own plugin's.

ragdoll3d gives two mods.

  • box3d
    kinds: name it in world.box3d.mods.kinds. Each bone row is a dynamic capsule of the row's own half and radius, with the settings above, and each bonejoint row is the joint its joint holds.
  • hitscan3d
    bodies: name it in world.hitscan3d.mods as { bodies: "ragdoll3d" }, so a shot meets a standing body's bones before it falls. Every row of a kind world.anim.kinds lists, whose rig carries the bake's ends for its model and that anim has played a clip on, is the body capsules makes of it, each part named as its bone. Every other body comes from the bodies mod world.ragdoll3d.mods names, none when it names none. A body that mod hands with the id of one of these is this one, never both.

In the guide