Skip to content

Commit

Permalink
feat(TileCache): expose detour result when adding and removing obstacles
Browse files Browse the repository at this point in the history
  • Loading branch information
isaac-mason committed Apr 10, 2024
1 parent e570811 commit d490a5c
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 33 deletions.
7 changes: 7 additions & 0 deletions .changeset/eleven-waves-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@recast-navigation/core": minor
"@recast-navigation/wasm": minor
"recast-navigation": minor
---

feat(TileCache): expose detour result when adding and removing obstacles
63 changes: 55 additions & 8 deletions packages/recast-navigation-core/src/tile-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ export type CylinderObstacle = {
height: number;
};

export type AddObstacleResult<T> = {
success: true;
status: number;
obstacle: T;
} | {
success: false;
status: number;
obstacle?: T;
};

export type RemoveObstacleResult = {
success: boolean;
status: number;
};

export type Obstacle = BoxObstacle | CylinderObstacle;

export type TileCacheParamsType = {
Expand Down Expand Up @@ -128,13 +143,22 @@ export class TileCache {
position: Vector3,
radius: number,
height: number
): CylinderObstacle {
const ref = this.raw.addCylinderObstacle(
): AddObstacleResult<CylinderObstacle> {
const result = this.raw.addCylinderObstacle(
vec3.toRaw(position),
radius,
height
);

if (result.status !== Raw.Detour.SUCCESS) {
return {
success: false,
status: result.status,
};
}

const ref = result.ref;

const obstacle: CylinderObstacle = {
type: 'cylinder',
ref,
Expand All @@ -145,7 +169,11 @@ export class TileCache {

this.obstacles.set(ref, obstacle);

return obstacle;
return {
success: true,
status: result.status,
obstacle,
};
}

/**
Expand All @@ -155,13 +183,22 @@ export class TileCache {
position: Vector3,
extent: Vector3,
angle: number
): BoxObstacle {
const ref = this.raw.addBoxObstacle(
): AddObstacleResult<BoxObstacle> {
const result = this.raw.addBoxObstacle(
vec3.toRaw(position),
vec3.toRaw(extent),
angle
);

if (result.status !== Raw.Detour.SUCCESS) {
return {
success: false,
status: result.status,
};
}

const ref = result.ref;

const obstacle: BoxObstacle = {
type: 'box',
ref,
Expand All @@ -172,13 +209,17 @@ export class TileCache {

this.obstacles.set(ref, obstacle);

return obstacle;
return {
success: true,
status: result.status,
obstacle,
};
}

/**
* Removes an obstacle from the navigation mesh.
*/
removeObstacle(obstacle: Obstacle | ObstacleRef): void {
removeObstacle(obstacle: Obstacle | ObstacleRef): RemoveObstacleResult {
let ref: ObstacleRef;

if (typeof obstacle === 'object') {
Expand All @@ -188,7 +229,13 @@ export class TileCache {
}

this.obstacles.delete(ref);
this.raw.removeObstacle(ref);

const status = this.raw.removeObstacle(ref);

return {
success: Raw.Detour.statusSucceed(status),
status,
};
}

addTile(
Expand Down
11 changes: 8 additions & 3 deletions packages/recast-navigation-wasm/recast-navigation.idl
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,11 @@ interface TileCacheUpdateResult {
attribute boolean upToDate;
};

interface TileCacheAddObstacleResult {
attribute unsigned long status;
attribute dtObstacleRef ref;
};

interface dtTileCacheCompressor {
};

Expand Down Expand Up @@ -541,9 +546,9 @@ interface TileCache {
unsigned long buildNavMeshTile([Const] dtCompressedTileRef ref, NavMesh navMesh);
unsigned long buildNavMeshTilesAt([Const] long tx, [Const] long ty, NavMesh navMesh);
[Value] TileCacheUpdateResult update(NavMesh navMesh);
dtObstacleRef addCylinderObstacle([Const, Ref] Vec3 position, float radius, float height);
dtObstacleRef addBoxObstacle([Const, Ref] Vec3 position, [Const, Ref] Vec3 extent, float angle);
void removeObstacle(dtObstacleRef obstacle);
[Value] TileCacheAddObstacleResult addCylinderObstacle([Const, Ref] Vec3 position, float radius, float height);
[Value] TileCacheAddObstacleResult addBoxObstacle([Const, Ref] Vec3 position, [Const, Ref] Vec3 extent, float angle);
unsigned long removeObstacle(dtObstacleRef obstacle);
void destroy();
};

Expand Down
41 changes: 30 additions & 11 deletions packages/recast-navigation-wasm/src/TileCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,45 +50,64 @@ TileCacheUpdateResult TileCache::update(NavMesh *navMesh)
return *result;
};

dtObstacleRef *TileCache::addCylinderObstacle(const Vec3 &position, float radius, float height)
TileCacheAddObstacleResult TileCache::addCylinderObstacle(const Vec3 &position, float radius, float height)
{
dtObstacleRef ref(-1);

TileCacheAddObstacleResult *result = new TileCacheAddObstacleResult;

if (!m_tileCache)
{
return nullptr;
result->status = DT_FAILURE;
return *result;
}

m_tileCache->addObstacle(&position.x, radius, height, &ref);
result->status = m_tileCache->addObstacle(&position.x, radius, height, &ref);

m_obstacles.push_back(ref);
return &m_obstacles.back();

result->ref = &m_obstacles.back();

return *result;
}

dtObstacleRef *TileCache::addBoxObstacle(const Vec3 &position, const Vec3 &extent, float angle)
TileCacheAddObstacleResult TileCache::addBoxObstacle(const Vec3 &position, const Vec3 &extent, float angle)
{
dtObstacleRef ref(-1);

TileCacheAddObstacleResult *result = new TileCacheAddObstacleResult;

if (!m_tileCache)
{
return nullptr;
result->status = DT_FAILURE;
return *result;
}

m_tileCache->addBoxObstacle(&position.x, &extent.x, angle, &ref);
result->status = m_tileCache->addBoxObstacle(&position.x, &extent.x, angle, &ref);

m_obstacles.push_back(ref);
return &m_obstacles.back();

result->ref = &m_obstacles.back();

return *result;
}

void TileCache::removeObstacle(dtObstacleRef *obstacle)
dtStatus TileCache::removeObstacle(dtObstacleRef *obstacle)
{
if (!m_tileCache || !obstacle || *obstacle == -1)
{
return;
return DT_FAILURE;
}

m_tileCache->removeObstacle(*obstacle);
dtStatus status = m_tileCache->removeObstacle(*obstacle);

auto iter = std::find(m_obstacles.begin(), m_obstacles.end(), *obstacle);
if (iter != m_obstacles.end())
{
m_obstacles.erase(iter);
}

return status;
}

void TileCache::destroy()
Expand Down
12 changes: 9 additions & 3 deletions packages/recast-navigation-wasm/src/TileCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ struct TileCacheUpdateResult
bool upToDate;
};

struct TileCacheAddObstacleResult
{
unsigned int status;
dtObstacleRef *ref;
};

class TileCache
{
public:
Expand All @@ -162,11 +168,11 @@ class TileCache

TileCacheUpdateResult update(NavMesh *navMesh);

dtObstacleRef *addCylinderObstacle(const Vec3 &position, float radius, float height);
TileCacheAddObstacleResult addCylinderObstacle(const Vec3 &position, float radius, float height);

dtObstacleRef *addBoxObstacle(const Vec3 &position, const Vec3 &extent, float angle);
TileCacheAddObstacleResult addBoxObstacle(const Vec3 &position, const Vec3 &extent, float angle);

void removeObstacle(dtObstacleRef *obstacle);
dtStatus removeObstacle(dtObstacleRef *obstacle);

void destroy();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ export const CrowdExample = () => {

crowd.destroy();
navMesh.destroy();
tileCache.destroy();
navMeshQuery.destroy();
};
}, [group]);

Expand All @@ -139,24 +141,34 @@ export const CrowdExample = () => {

if (boxObstacle.current) {
tileCache.removeObstacle(boxObstacle.current);
boxObstacle.current = undefined;
}

if (cylinderObstacle.current) {
tileCache.removeObstacle(cylinderObstacle.current);
cylinderObstacle.current = undefined;
}

boxObstacle.current = tileCache.addBoxObstacle(
const boxObstacleResult = tileCache.addBoxObstacle(
boxObstacleTarget.current!.getWorldPosition(new Vector3()),
{ x: 1, y: 1, z: 1 },
0.2
);

cylinderObstacle.current = tileCache.addCylinderObstacle(
if (boxObstacleResult.success) {
boxObstacle.current = boxObstacleResult.obstacle;
}

const cylinderObstacleResult = tileCache.addCylinderObstacle(
cylinderObstacleTarget.current!.getWorldPosition(new Vector3()),
1,
0.5
);

if (cylinderObstacleResult.success) {
cylinderObstacle.current = cylinderObstacleResult.obstacle;
}

let upToDate = false;
while (!upToDate) {
const result = tileCache.update(navMesh);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,34 @@ export const PathExample = () => {
setTileCache(undefined);

navMesh.destroy();
tileCache.destroy();
navMeshQuery.destroy();
};
}, [group]);

const update = () => {
if (!navMesh || !tileCache || !navMeshQuery) return;

console.log('box', boxObstacle.current)
if (boxObstacle.current) {
tileCache.removeObstacle(boxObstacle.current);
console.log('removeObstacle')
const status = tileCache.removeObstacle(boxObstacle.current);

console.log(status);

boxObstacle.current = undefined;
}

boxObstacle.current = tileCache.addBoxObstacle(
const addObstacleResult = tileCache.addBoxObstacle(
boxObstacleTarget.current!.getWorldPosition(new Vector3()),
{ x: 1, y: 1, z: 1 },
0.2
);

if (addObstacleResult.success) {
boxObstacle.current = addObstacleResult.obstacle;
}

let upToDate = false;
while (!upToDate) {
const result = tileCache.update(navMesh);
Expand Down
Loading

0 comments on commit d490a5c

Please sign in to comment.