@twobitedd/zen-sand-rake
v0.2.0
Published
React Three Fiber zen-garden sand disk with mask-based rake painting, nav grid, and optional demos (pattern / car sim).
Maintainers
Readme
@twobitedd/zen-sand-rake
Interactive zen garden sand disk for React Three Fiber: GPU-mixed raked / smooth sand layers driven by a CPU mask texture, with obstacle-aware stamping, optional nav/debug overlays, auto pattern playback, and a car-style UV demo (rakeCar URL flag).
Peer dependencies
react/react-dom^18.2 or ^19three^0.180–^0.183 (aligned with R3F stacks using 0.183.x)@react-three/fiber^9@react-three/drei^10 (usesHtmlfor debug overlay)
Install
npm install @twobitedd/zen-sand-rakeUsage
import { Canvas } from "@react-three/fiber";
import {
ClassicInteractiveSand,
getClassicZenGardenLayout,
type ClassicRakePatternKey,
} from "@twobitedd/zen-sand-rake";
function Sand({ seed = 1 }: { seed?: number }) {
const { rakeObstacles } = getClassicZenGardenLayout(seed);
return (
<ClassicInteractiveSand
rakePattern={"rings" satisfies ClassicRakePatternKey}
rakeRefreshToken={0}
rakeDebugContrast={false}
rakeIntensity={1}
rakePaintingEnabled={false}
autoRakeEnabled={false}
rakeBrushSize={48}
zenRakeObstacles={rakeObstacles}
/>
);
}
export function Demo() {
return (
<Canvas camera={{ position: [0, 14, 18] }}>
<ambientLight intensity={0.6} />
<Sand />
</Canvas>
);
}URL flags (read from urlSearchParams when passed from React Router, or once from window.location):
rake=1— rake without holding ShiftrakePattern/rakeFoolproof— one-shot scripted orbitrakeCar=1— car/bicycle UV demo (optional tuning:rakeCarSpeed,rakeCarHeadingWeight,rakeCarHeadingConvergence)sandDebug=1— mask-only debug (see alsoDEFAULT_SAND_DEBUG_LOCAL_STORAGE_KEYS)rakeOverwriteDecayOnHit(orrakeOverwrite) — per-hit overwrite decay0..0.95(higher fades old grooves faster)rakePathDebug=1— QA HUD (bottom-right 256 px canvas, same UV as rake stamping): amber pedestal outline + magenta prop discs (fromzenRakeObstacles), cyan scripted foolproof path (buildZenFoolproofAutoPathUv), and withrakeCar=1a golden forward lookahead segment matching the car sampler. Stamp-centroid rake trail (lime/coral dashes) when painting with debug on. Mirrors mask debug viaDEFAULT_RAKE_PATH_DEBUG_LOCAL_STORAGE_KEYS(xo3.rakePathDebug,zenSandRake.rakePathDebug). Pair withrakeNavDebug=1for the128²rigid/soft nav tint mosaic underneath, andrakeMap=1/rakePhysicalPath=1for the white A* orbit stroke on top.
| Query | HUD (Html 256²) | World disk (ZenRakePathDebugWorldQuad) |
|--------|-------------------|------------------------------------------|
| (none) | off | off |
| rakePathDebug=1 | on (when overlay suite active) | off |
| rakePathDebugWorld=1 | off unless rakePathDebug / rakeNavDebug / map flags enable the suite | on only with the same suite (rakeNavDebug and/or rakePathDebug and/or rakeMap/rakePhysicalPath) |
| rakePathDebug=1 + rakePathDebugWorld=1 | on | on (world raster throttled every 2 frames) |
rakePathDebugWorld is URL-only (no localStorage mirror). The world quad shares the sand stack’s CircleGeometry + tray CLASSIC_SAND_DISK_PATH_DEBUG_WORLD_TRAY_LOCAL_Z (coplanar with the visible shader sand in zenGardenObstacles.ts, not the separate hit shell — avoids parallax drift) and the same {@link drawZenRakePathDebugOverlay2d} raster as the HUD.
rakePathDebugAlign=1— URL-only: draws a thin center crosshair and disk rim (unit circle in canonical UV) on the debug canvas for both the HUD and the world disk when overlays are active.
You can reuse the overlay outside ClassicInteractiveSand by importing ZenRakePathDebugOverlay (@twobitedd/zen-sand-rake).
Build
npm run buildWhen consuming this package via file: / a local checkout, npm install inside the package can leave node_modules/react next to dist; Vite apps should use resolve.dedupe for react / three / R3F (see ergo-games-xo3/vite.config.ts), and may alias @twobitedd/zen-sand-rake → ../packages/zen-sand-rake/src/index.ts in dev only so hooks resolve against the app’s React.
License
MIT — see LICENSE.
