← Back to the collection
VISUAL COMPUTING / 2020—2026 / INTERACTIVE APPLICATION

Plan a route. Learn a way through.

3D Pathfinding

A 3D pathfinding and learning environment. Compare deterministic graph search with an agent learning from rewards, repeated journeys, and negative sink states.

MEDIUM
  • JavaScript
BUILT WITH
  • React
  • Three.js
  • React Three Fiber
  • Tween.js
ACCESS

Public source

Real 3D pathfinding learning run: seven clustered sink obstacles, an early failed episode and two later successful routes, with episode and move counts
EXPLORE THE APPLICATIONLaunch Project
12 seconds · actual app, selected episodes 1 → 503 → 998 · original learning rule, instrumented replay.Open film ↗
01

Two approaches, one world

Dijkstra and A* search the graph using costs; breadth-first and depth-first search explore it in different orders. The Q-Learning mode instead learns from repeated interactions with rewards. All five run in the same editable 3D world, but planning a route and learning how to navigate are different processes.

02

From world state to a visible result

World and Settings configure the grid. Weighted and unweighted search modules return visited nodes and predecessor chains. Grid also holds the learning state: cell values, visits, rewards, and episode snapshots. Three.js vertex colours and a shared Tween.Group turn those results into visible movement.

SYSTEM SKETCH / CONCEPTUAL OVERVIEW
WORLD / CELLS + WALLS + REWARDS
           │
     ┌─────┴───────────┐
     ▼                 ▼
 GRAPH SEARCH      LEARNING LOOP
 distances         choose → move → reward
 predecessors      update scalar cell value
     │                 │
     └─────┬───────────┘
           ▼
    THREE.JS / TWEEN REPLAY
A reading of the architecture, not an application screenshot.
SYSTEM MAP / COMPONENT & DATA FLOW

One world. Two ways to navigate.

World + Settings → Grid / terrainRef: configure. Grid / terrainRef → Graph search modules: graph nodes. Grid / terrainRef → qLearning(): states + rewards. qLearning() → qLearning(): repeat until terminal / 1,000 steps. Graph search modules → Records + route: visited nodes + predecessors. qLearning() → Records + route: one value snapshot per episode. Records + route → Three.js + Tween.Group: animate results.123456701 / INTERFACEWorld + SettingsAlgorithm, endpoints, epochsLearning rate + curiosity02 / SHARED MODELGrid / terrainRef30 × 30 cells · walls / rewardsDistances, predecessors, visits03 / SOLVERGraph search modulesWeighted: Dijkstra / A*Unweighted: BFS / DFS04 / LEARNING LOOPqLearning()chooseAction → next cellReward → scalar value update05 / STORED RESULTSRecords + routeEpisode value snapshotsPredecessors / policy trace06 / RENDERERThree.js + Tween.GroupVertex colours + wall meshesuseFrame advances tweens
  1. 01 / interface

    World + Settings

    Algorithm, endpoints, epochs

    Learning rate + curiosity

    • configure → 2. Grid / terrainRef
  2. 02 / shared model

    Grid / terrainRef

    30 × 30 cells · walls / rewards

    Distances, predecessors, visits

    • graph nodes → 3. Graph search modules
    • states + rewards → 4. qLearning()
  3. 03 / solver

    Graph search modules

    Weighted: Dijkstra / A*

    Unweighted: BFS / DFS

    • visited nodes + predecessors → 5. Records + route
  4. 04 / learning loop

    qLearning()

    chooseAction → next cell

    Reward → scalar value update

    • repeat until terminal / 1,000 steps → 4. qLearning()
    • one value snapshot per episode → 5. Records + route
  5. 05 / stored results

    Records + route

    Episode value snapshots

    Predecessors / policy trace

    • animate results → 6. Three.js + Tween.Group
  6. 06 / renderer

    Three.js + Tween.Group

    Vertex colours + wall meshes

    useFrame advances tweens

    1. 1World + Settings Grid / terrainRefconfigure
    2. 2Grid / terrainRef Graph search modulesgraph nodes
    3. 3Grid / terrainRef qLearning()states + rewards
    4. 4qLearning() qLearning()repeat until terminal / 1,000 steps
    5. 5Graph search modules Records + routevisited nodes + predecessors
    6. 6qLearning() Records + routeone value snapshot per episode
    7. 7Records + route Three.js + Tween.Groupanimate results
    The app calls its learning mode Q-Learning, but q_table stores one scalar per cell. It updates from the sampled next cell; it is not a standard state–action Q-table. Walls terminate learning episodes with −100; the goal rewards +100.
    Read from the implementation
    • World.js
    • Settings.js
    • Grid.js
    • algorithms/weightedSearchAlgorithm.js
    • algorithms/unweightedSearchAlgorithm.js
    • algorithms/helpers.js
    03

    Seven obstacles, a thousand episodes

    The new film reruns the actual app with seven buildings clustered between a start and goal. A sink ends an episode with −100; reaching the goal gives +100. Selected episodes 1, 503, and 998 replay in order: 137 moves ending in a sink, then 95 and 34 moves reaching the goal. Early episodes start at random cells; the final quarter starts at the configured green cell. These are different journeys, not a controlled shortest-path comparison.

    04

    What this learning rule actually learns

    The interface calls the mode Q-Learning, but the implementation stores a scalar value per cell rather than a state–action Q-table. It updates that value using the sampled next cell and its reward. Exploration remains active in later episodes. The final hundred episodes in this seeded run all reached the goal; the selected route shows useful avoidance, not proof of an optimal or fully stabilized policy.

    05

    Making the recorded history readable

    The original playback schedules all value snapshots at the same delay, hiding the progression. An isolated capture copy records the chosen states and replays selected episodes at readable speeds in the original 3D renderer. The readout reports actual episode and move counts; the heatmap shows values before each episode. The reward, action selection, learning update, and termination rules are unchanged.

    06

    The engineering boundary

    Dijkstra’s film remains at 2.5× speed. Its weighted search scans an array for the next closest node; the source suggests a priority queue as a future improvement. The learning experiment is likewise presented on its own terms: a way to observe changing behaviour, rather than a production routing engine or textbook Q-learning implementation.

    CONTINUE EXPLORING

    Waterflow Simulation →

    An early terrain simulation: click to add water and explore the difficult relationship between shared state, rendering, and time.

    2020
    • Java