Library / SDK
donmccurdy/three-pathfinding avatar
donmccurdy/three-pathfinding

three-pathfinding: Navigation Mesh Pathfinding for three.js

Navigation mesh utilities for three.js, based on PatrolJS.

1,376 stars139 forksJavaScriptMIT

At a glance

What is it?
three-pathfinding is a JavaScript toolkit for three.js that builds pathfinding zones from exported navigation mesh geometry and finds routes across multiple zones. It assumes that the mesh already exists, making it suitable for developers who already have a Recast, Blender, or other navmesh pipeline.
Who is it for?
Adopt three-pathfinding when the project already has a compatible navmesh exported as OBJ or glTF and needs runtime route calculation for three.js agents. Do not adopt it as a standalone navmesh generator, or for applications that cannot supply BufferGeometry using the +Y=Up convention.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why three-pathfinding handles movement on navigation meshes

three-pathfinding addresses a specific problem in three.js applications: calculating routes for agents that must move across walkable geometry rather than between manually placed waypoints. The README argues that waypoint systems can ignore the agent's physical size and fail to represent obstacles accurately. A navigation mesh gives pathfinding code a surface that describes where movement is permitted, so a large vehicle and a small character can follow paths appropriate to their available space.

The library is aimed at developers building browser-based three.js scenes, demos, games, and first-person controls. It is not a general-purpose level editor or mesh-generation package. The application must first produce a navigation mesh with Blender, Recast, or another tool, then export it as a 3D model format such as OBJ or glTF. three-pathfinding consumes the loaded geometry and turns it into pathfinding data.

That boundary is important. A project that starts with an ordinary visual model and expects automatic navmesh generation would need another tool. The library's central contribution begins after the navigation surface has been created.

From BufferGeometry to zones and node groups

The documented flow begins with a three.js `BufferGeometry`. The geometry must come from a supported model format loaded with a loader such as `THREE.OBJLoader` or `THREE.GLTFLoader`. three-pathfinding follows the three.js and glTF convention that +Y points upward. Once the mesh is available, `Pathfinding.createZone(navmesh.geometry)` constructs a `Zone` containing the data used for navigation.

The `Pathfinding` instance stores one or more named zones through `setZoneData`. Each call associates a string zone ID, such as `level1`, with a zone object. This design allows separate navigation datasets to coexist in one pathfinding instance. The API also exposes `getGroup`, which returns the closest node group ID for a position, and `getClosestNode`, which finds a node near a requested location.

For a route request, the application identifies the current group with `getGroup`, then calls `findPath`. The method accepts start and target `Vector3` values, a zone ID, and a group ID. It returns an array of `Vector3` points. The README does not describe a separate runtime representation for portals between zones, so multi-zone support should be understood as named zone management rather than a documented automatic cross-zone routing system.

Installing three-pathfinding and loading a glTF navmesh

The README gives one direct installation command for an npm project. The package is `three-pathfinding`, and the repository declares `three` as a peer dependency, so the host application must also provide a compatible three.js version. The package metadata specifies the main and module distributions under `dist/`, while the source entry point is `src/index.js`.

The following command installs the library and saves it to the project's npm dependencies:

bash
npm install --save three-pathfinding

The first documented loading example is a CommonJS glTF example. It assumes `three` is available through the application and that the navmesh file is named `navmesh.gltf`. The callback searches the loaded scene for a mesh and stores it in `navmesh`.

js
const THREE = window.THREE = require('three');
require('three/examples/js/loaders/GLTFLoader.js');

let navmesh;
const loader = new THREE.GLTFLoader();
loader.load('navmesh.gltf', ({scene}) => {
  scene.traverse((node) => {
    if (node.isMesh) navmesh = node;
  });
}, undefined, (e) => {
  console.error(e);
});

The callback should find the navmesh mesh before zone creation. If the file fails to load, the documented error handler receives the error and logs it with `console.error`.

Creating a Pathfinding zone and calculating the first route

After the mesh has loaded, the application creates a `Pathfinding` instance, registers the zone, and requests a route. The README provides both ES6 and CommonJS import styles. This matters because the package supports module consumers as well as environments that use `require`.

The first API call creates the zone data. The next call registers it under a zone ID. Finally, the application obtains a group ID from the agent's current position and passes that group to `findPath`. In the README's example, `a` and `b` represent the start and destination positions.

js
import { Pathfinding } from 'three-pathfinding';

const pathfinding = new Pathfinding();
const ZONE = 'level1';
pathfinding.setZoneData(ZONE, Pathfinding.createZone(navmesh.geometry));

const groupID = pathfinding.getGroup(ZONE, a);
const path = pathfinding.findPath(a, b, ZONE, groupID);

The route is an array of `Vector3` points, not a single calculated direction. The application must therefore decide how to follow, interpolate, animate, or render those points. The origin of an agent should initially sit on the navmesh surface. The README also allows a dummy object to be used for pathfinding when the rendered agent needs an offset from the logical position.

Controlling first-person movement with clampStep

three-pathfinding is not limited to agent routes. The `clampStep` method constrains a desired movement endpoint so that first-person or WASD controls remain on the navigation mesh. It takes the current start position, desired endpoint, current node, zone ID, and group ID. The documentation says that the method updates the endpoint through an `endTarget` value and returns the updated node.

This creates a second integration path. An application can calculate a full route with `findPath`, or it can accept the player's short proposed movement and reject movement that would leave the walkable surface. The distinction is useful when movement is continuous rather than destination-driven. A route planner may be suitable for enemies or patrol units, while `clampStep` is intended for direct player controls.

The API does not document collision against arbitrary scene meshes, animation state handling, or a movement budget for vehicle dimensions. Those concerns remain application responsibilities. The navmesh itself must reflect the restrictions the project needs.

Limitations, alternatives, and maintenance signals

The main limitation is explicit in the README: three-pathfinding does not build navigation meshes and does not accept custom navigation mesh formats produced by tools such as Recast. The mesh must be exported to a model format and loaded into three.js. Projects that need an integrated scene-to-navmesh pipeline should evaluate Recast tooling, Blender-based workflow, or another generation library before choosing this package.

PatrolJS is the stated basis for the implementation. It is also a different kind of tool: PatrolJS is the source project for Patrol-style navigation logic, whereas three-pathfinding adapts that approach to three.js `BufferGeometry`, named zones, and browser scene integration. A simpler waypoint solution may be more appropriate when the environment is small, obstacles are sparse, and exact surface clearance is not important. A game that needs authored patrol logic may also prefer explicit waypoints because those express mission behavior more directly than a surface graph.

The repository is not archived. The last push was on 2026-10-06. However, there are no GitHub releases, and the README does not document a release or migration policy. Upgrading therefore requires checking the package version, peer dependency expectations, and generated distributions rather than relying on a documented release stream. The MIT license permits use and modification under its terms, but an application should still review the complete license file and comply with its notice requirements.

Editorial conclusion

Adopt three-pathfinding when the project already has a compatible navmesh exported as OBJ or glTF and needs runtime route calculation for three.js agents. Do not adopt it as a standalone navmesh generator, or for applications that cannot supply BufferGeometry using the +Y=Up convention. Verify the mesh import, zone construction, and target placement before integrating gameplay logic, because the library returns the nearest available endpoint when a complete path cannot be found.

Frequently asked questions

Does three-pathfinding create navigation meshes automatically?

No. The README says the library does not build navigation meshes. Use Blender, Recast, or another tool to create one, then export it as OBJ or glTF and load the geometry with a three.js loader.

What geometry format does three-pathfinding accept?

It accepts a three.js `BufferGeometry`. The README documents OBJ and glTF as suitable export formats and says that the geometry follows the +Y=Up convention used by three.js and glTF.

How does three-pathfinding find a path?

Create a `Zone` with `Pathfinding.createZone`, register it with `setZoneData`, obtain the agent's group with `getGroup`, and call `findPath`. The result is an array of `Vector3` points, or the nearest available endpoint if a complete path cannot be found.

Official sources

  1. donmccurdy/three-pathfinding on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/donmccurdy-three-pathfinding.svg)](https://hysenlabs.com/projects/donmccurdy-three-pathfinding)

Was this useful?