Software & Sims · 2026
Inside the Walker: Legs, Weight and a Cockpit Made of Camera Feeds
A four-legged transport for the surface of the generated world: an 11 m machine with a procedural gait, a hull on a spring and three-segment legs. You board it through the belly and drive it from a cabin whose screens show what cameras on the hull see, so looking left means turning your head to the port screen, not turning the world.
- Godot 4.7
- GDScript
- GLSL shaders
- Python
- NumPy
- Procedural animation
- Inverse kinematics
- from the ground to the top of the hull when standing; it kneels 3.4 m lower to let the pilot in
- 11 m
- camera feeds rendered for the cockpit: forward, port, starboard and belly
- 4
- mean frame time on foot vs. in the cockpit (RTX 3060 Laptop, 1600×900, vsync off, 6 s each)
- 3.3 → 10.3 ms
- animation clips: every step, sway and jolt is computed each frame
- 0

Result
The generated world from Seeing Through Stone has a surface that is far bigger than anyone wants to cross on foot. The walker is the overworld’s fast travel: a slow, heavy four-legged transport that carries the player from ruin to ruin. Inside a ruin the game switches back to the lantern camera; the two never run at the same time. You walk up to it in third person, it kneels, the belly hatch opens, and you climb into a cabin where the outside reaches you only through camera feeds. The design takes its cue from the titan cockpit in Titanfall 2: screens instead of windows, thin seams between them, a feed that boots and glitches.
What works now:
- A gait with weight. One leg moves at a time and three stay planted. Each step lifts fast, hangs, and lands hard. The hull sits on a spring, so every landing sinks it a little, and it leans over the planted feet.
- Legs that look grown, not mirrored. Arm-like front legs, digitigrade hind legs, three segments each, and every leg with its own lengths, knee direction, toes and armour.
- A cockpit you sit in. Five screens around the pilot’s head, each fed by a camera mounted where a small lens pod sits on the hull. Turning the head looks into a side screen; the outside view never turns with the mouse.
- Motion you feel through the seat. The pilot’s head is a mass on a spring, pushed by the hull’s measured acceleration. A front-left footfall rolls you left and pitches you forward; walking into a ruin throws you forward and tears the feeds.
Weight without animation clips
The walker has no animation data. Every frame, the code decides where each foot should be, solves the legs to reach it, and moves the hull over the result.
The gait is a phase that advances with distance travelled: each leg owns a quarter of the cycle in the air (left hind, left fore, right hind, right fore), so three feet always carry the hull. When the walker stops, the phase keeps running at a slow shuffle until every foot is within 0.7 m of its rest position, then halts. Turning in place falls out of the same rule.
Where a foot lands is predicted, not reacted to: when a leg lifts, its target is the rest
position the hull will have by the middle of that foot’s next stance, from the current speed
and yaw rate. The shape of the step carries most of the sense of mass (walker.gd):
var t := p / DUTY
var w := maxf(omega, 1e-3)
var ahead := (1.0 - t) * DUTY / w + (1.0 - DUTY) * 0.5 / w
leg.target = _ground(_rest(leg.i, minf(ahead, 3.0)))
var s := smoothstep(0.08, 0.82, t)
var pos: Vector3 = leg.from.lerp(leg.target, s)
# heavy step: lifts quickly, hangs, slams down at the end
var lift := sin(PI * pow(t, 0.72))
pos.y += STEP_HEIGHT * lift * clampf(0.35 + dist / 3.0, 0.35, 1.0)
The horizontal move finishes before the drop does, and the exponent on t skews the arc so the
foot comes down faster than it went up. Short corrective steps get a lower lift, so shuffling in
place doesn’t look like marching.
Each landing kicks the hull’s vertical spring (k = 26, slightly underdamped), raises a ring of
dust, sometimes vents steam from the hock, and emits a footfall signal that the cameras use.
Body pitch and roll follow the front/back and left/right foot heights, with a small shift of
weight away from whichever foot is in the air.
Three segments, one solved joint
The legs have three segments (thigh, shin, metatarsus), which a two-bone solver can’t handle on its own. Rather than writing a full three-joint solver, I set the metatarsus by hand: each leg has a lean direction for standing and another for kneeling, and it folds back while the foot is in the air. That fixes the hock, and the thigh and shin solve onto it with the usual two-bone construction:
var m_local: Vector3 = spec.meta.lerp(spec.meta_kneel, k)
m_local += Vector3(0, -0.1, 0.55) * leg.lift
var hock: Vector3 = ankle + (yb * m_local).normalized() * float(L[2])
var d := hock - hip
var dist := clampf(d.length(), absf(l1 - l2) + 0.1, l1 + l2 - 0.02)
var along := (l1 * l1 - l2 * l2 + dist * dist) / (2.0 * dist)
var h := sqrt(maxf(l1 * l1 - along * along, 0.0))
var knee := hip + dir * along + perp * h
The knee direction (pole) is per leg too. The front legs push their elbows up and out, the hind
legs push their knees forward, and the folding metatarsus gives the hind legs a backward hock.
Pistons between hull and thigh, and between thigh and shin on three of the legs, are re-aimed
every frame, which shows the joints working under load.





A cockpit made of camera feeds
The walker has no windows. The pilot sees the outside through cameras, and the cockpit should make that obvious: screens, seams between them, a feed that boots with static and tears when a foot slams down.
# cockpit_room.gd: who sees what
cam.cull_mask = 0xFFFFF & ~CABIN_LAYER # feed cameras
views.center.cam.cull_mask = 0xFFFFF & ~CABIN_LAYER & ~walker.HULL_LAYER # it sits inside the prow
# walker_demo.gd, while piloting: the pilot sees only the cabin
cam.cull_mask = CockpitRoom.CABIN_LAYER
The feed look (a cool grade, scanlines, colour fringes, grain, tearing bands) is one full-screen quad on a layer that only feed cameras render, so each feed carries the effect and the cabin stays clean. The HUD is drawn per screen into transparent viewports and composited in the screen’s shader, so the compass, the leg-contact diagram and the waypoint stay in perspective on their screens when the head turns. The belly screen looks straight down from under the hatch and marks where the pilot will step off.


When the link comes up after boarding, every feed starts as static. It isn’t a fixed noise image: each frame picks new bands of random height, each with its own grain size, sideways tear and brightness, in navy, cyan and white, with a few bright bars rolling at random speeds. The picture fades in through it while the boot text runs.

Motion through the seat
Screen shake as a random offset tells the player that something happened, but not what. In the
cabin, the head is a damped spring pushed by what the hull actually does. The demo
differentiates the seat position twice, rotates the result into the cabin’s frame, and lets
inertia do the rest (walker_demo.gd):
# head: lags the cabin (inertia), leans out of turns, nods with surges
var ks := 55.0
head_vel += (-ks * head_off - 2.0 * 0.45 * sqrt(ks) * head_vel - a_local * 0.012 * k) * delta
head_off += head_vel * delta
var push := Vector3(a_local.z * 0.012, 0.0, -a_local.x * 0.012 + walker.yaw_rate * walker.speed * 0.05) * k
head_rot_vel += (-kr * head_rot - 2.0 * 0.4 * sqrt(kr) * head_rot_vel + push * kr * 0.1) * delta
On top of that, each footfall adds an impulse that depends on which corner landed: roll towards its side, pitch towards its end, a short drop. The hull’s own spring and the head’s spring then ring against each other, so a stride reads as a rhythm, not as noise. A collision with a ruin throws the head forward and tears every feed; kneeling and standing up add a servo rumble.
Several things are switchable in the demo for testing: shake strength (×0.6 is the default after playtesting), and three steering modes. In look-led the hull turns slowly towards where the pilot looks and the head settles back forward as it turns. In WASD turn the mouse only looks, and direct mouse turns the hull with the mouse. Middle mouse toggles a free look that doesn’t steer.
Measurements
Frame times from the demo’s --bench mode (the same scripted sequence each run), RTX 3060
Laptop GPU, 1600×900 window, vsync off, 6 s per situation after 1 s to settle:
| Situation | Frames | Mean | 95th percentile |
|---|---|---|---|
| On foot, walker idle | 1805 | 3.32 ms | 5.34 ms |
| Cockpit, standing | 583 | 10.30 ms | 12.92 ms |
| Cockpit, walking | 582 | 10.31 ms | 12.99 ms |
| Third person, walking | 1649 | 3.64 ms | 5.57 ms |
The cockpit costs about 7 ms because four cameras render the world (1600×940, two at 860×720 and 800×400), each with shadows and ambient occlusion. Walking itself (gait, IK, particles) adds about 0.3 ms over standing.
Where it goes next
The walker lives in its own scene next to the map viewer, so it could be developed while other work on the viewer went on. The next step is to bring it into the main project, and the plan is written down with the inventory of files:
- The switch between modes. The walker and the lantern camera never run together: boarding turns the lantern’s line-of-sight cube and cutaway off, arriving at a ruin parks the walker and hands back. That switch is the real integration point. The rest is bookkeeping: the walker’s physics bits move off the viewer’s per-material collision bits.
- Ground from the streamed world. The demo’s feet fall back to an analytic height function. In the real world they ray-cast streamed collision, which has to be kept ready around the walker, not only around the player.
- Shading. The main world is unshaded and lit by the lantern and a daylight term; the walker uses a real sun. On the surface the directions already match; one side has to adopt the other.
- The cockpit’s cost. Lower feed resolutions, no shadows or ambient occlusion on the flank and belly cameras, and side feeds every other frame should take most of the 7 ms back.
After that: real destinations from the overworld plan for the waypoint, sound for footfalls and servos, and the cargo pack as an inventory.