Skip to content

Trail: 3D points, so a ribbon can recede under a Camera3d #1621

Description

@obiot

Summary

Trail cannot produce a trail behind an object moving into the scene. Points are stored as {x, y, age} and drawn as connected screen-space quads, so under a Camera3d the ribbon stays flat — it does not narrow with distance or sit on the terrain.

This is the effect a "leave a trail behind you" prompt asks for in any 3D or 2.5D game: ski tracks, exhaust, a speed streak, a spell arc. It is also the first thing anyone reaches for, because Trail's own JSDoc carries a rainbow-gradient example.

What exists today

Two workarounds, both viable, neither the obvious one:

  • ParticleEmitter with referenceSpace: "world" — particles stay where they were dropped while the emitter moves on, and the emitter propagates its depth to each particle so Camera3d projects them correctly. Good for discrete puffs; visibly not a continuous ribbon.
  • A procedural Mesh built from the object's recent path, with mesh.vertexColors for the gradient. Correct result, ~60–80 lines of strip generation the user writes themselves.

Proposal

Let a trail's points carry z, and generate a camera-facing strip when the stage has a perspective camera.

  • addPoint(x, y, z?), points stored with z (0 keeps every existing 2D trail identical)
  • accept a Vector3d / Renderable target and sample pos.z alongside pos.x/y
  • build each segment's quad from the path tangent × the vector to the camera, rather than a screen-space perpendicular — the standard billboarded-ribbon construction
  • minDistance becomes a world-space distance rather than px

The 2D path must stay bit-for-bit unchanged: with all-zero z and no perspective camera, the existing screen-space construction is already correct and cheaper.

Relationship to #1383

#1383 adds a texture to the ribbon; this issue changes its geometry. They are independent in value but overlap heavily in implementation — both are strip generation with per-vertex attributes, and the UV work #1383 needs is most of what a 3D strip needs anyway.

Worth deciding the point representation before either lands: if #1383 is built on {x, y} first, the texture path has to be redone when z arrives. Adding z to the point record up front costs almost nothing.

Notes

Found while checking whether melonJS could build a sledding game from a screenshot — a chase-camera 3D scene whose headline feature was a rainbow trail behind the sled. Everything else in the scene mapped onto existing features (Camera3d + followOffset, InstancedMesh, castGroundShadow, Sprite3d billboards, world-space particles, BitmapText); the trail was one of two gaps.

The skill documenting Trail now states it is 2D-only and names the two workarounds, so agents stop walking into it (da041b259).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions