Files
EVEngine/docs/usr/modules/spatial.md
T
Cursor Agentand西风逍遥游 410fa7895b Add spatial module with QuadTree, Octree, hash, and BSP indexes
Provide 2D/3D broad-phase structures for map/scene culling queries,
export them through eve.Spatial, and document the new module.

Co-authored-by: 西风逍遥游 <sunxfancy@gmail.com>
2026-08-09 16:49:59 +00:00

69 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 空间索引模块
**脚本入口:** `eve.Spatial()`
提供四叉树、八叉树、空间哈希与空间二分树(及其二维/三维版本),用于快速判断元素是否落在视口、拾取区或邻近范围内。
## 基本用法
```squirrel
local spatial = eve.Spatial();
local tree = spatial.newQuadTree(0, 0, 2048, 2048);
tree.insert(1, 100, 100, 132, 132); // id + AABB
tree.insert(2, 400, 200, 432, 232);
local n = tree.queryRect(90, 90, 200, 200);
for (local i = 0; i < tree.getResultCount(); i++) {
local id = tree.getResultId(i);
// 用 id 查自己的实体 / 地图对象
}
```
## 对象关系与调用时机
`Spatial` 只做工厂;真正持有数据的是 `QuadTree` / `Octree` / `SpatialHash2D` / `SpatialHash3D` / `BSPTree2D` / `BSPTree3D`。
索引里只存整数 `id` 与包围盒,不拥有实体。物体移动时调用 `update`;销毁时 `remove`。查询结果写在该索引对象内部,下一次 `query*` 会覆盖。
## 目标导向指南
### 地图视口裁剪
用地图世界范围创建 `QuadTree` 或 `SpatialHash2D`,把可交互对象 / 装饰物 id 与 AABB 插入;每帧用相机可见矩形 `queryRect`,只更新或绘制命中 id。
### 3D 场景邻近查询
用场景包围盒创建 `Octree` 或 `SpatialHash3D`;用 `querySphere` 找玩家附近可交互体,再做精确逻辑。
### 结构怎么选
- 物体大小接近、移动多:优先 `SpatialHash2D` / `SpatialHash3D`(调好 `cellSize`)
- 大地图静态或半静态:`QuadTree` / `Octree`
- 需要沿轴二分剪枝:`BSPTree2D` / `BSPTree3D`
## 常见问题
- 把 `procgen` 的 `dungeon.bsp` 当成空间查询树——那是地牢生成,不是本模块。
- 忘记在物体移动后 `update`,导致查询仍命中旧位置。
- `getResultId` 在新的 `query*` 之后仍使用旧循环变量——结果缓冲已被覆盖。
- 根包围盒过小:树/BSP 构造时给出的世界范围应覆盖所有可能插入的 AABB。
## API 快查
- 模块:`getName()`、`newQuadTree()`、`newOctree()`、`newSpatialHash2D()`、`newSpatialHash3D()`、`newBSPTree2D()`、`newBSPTree3D()`
- 共用:`clear()`、`insert()`、`remove()`、`update()`、`contains()`、`getCount()`、`getResultCount()`、`getResultId()`
- 2D 查询:`queryPoint()`、`queryRect()`、`queryCircle()`
- 3D 查询:`queryPoint()`、`queryAABB()`、`querySphere()`
- 树/BSP:`getMinX/Y[/Z]`、`getMaxX/Y[/Z]`、`getMaxDepth()`、`getMaxPerNode()`
- 哈希:`setCellSize()`、`getCellSize()`
## 使用要点
- 模块对象和索引对象应保存在全局或实体状态中,不要每帧重建整棵树(除非批量替换世界)。
- `id` 由脚本自定义,保持稳定即可;不要假设与 ECS 实体句柄自动同步。
- 参数约束与默认值以头文件及 `addFunc` 绑定为准。
**源码:** [`src/modules/spatial/`](../../../src/modules/spatial/)
**设计文档:** [`docs/dev/空间索引模块设计.md`](../../dev/空间索引模块设计.md)
**相关测试:** [`test/spatial.cpp`](../../../test/spatial.cpp)