Files
agame/addons/csg_blockout/ARCHITECTURE_CN.md
T
2026-10-01 05:36:12 +08:00

176 lines
9.1 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.
# CSG_Blockout 架构设计与技术内幕
*其他语言版本: [English](ARCHITECTURE.md) | [返回主文档](README_CN.md)*
本文档面向对插件底层实现、算法细节以及二次开发感兴趣的开发者,详细阐述 `CSG_Blockout` 的核心算法设计、架构分层与完整 API 规范。
---
## 目录
- [一、 核心算法:3D 空间哈希网格 (Spatial Hash Grid)](#一-核心算法3d-空间哈希网格-spatial-hash-grid)
- [二、 系统架构与设计模式](#二-系统架构与设计模式)
- [三、 程序化世界对齐材质 Shader 设计](#三-程序化世界对齐材质-shader-设计)
- [四、 GDScript 2.0 规范与防御性设计](#四-gdscript-20-规范与防御性设计)
- [五、 节点与组件规格参考 (API Reference)](#五-节点与组件规格参考-api-reference)
- [六、 ProjectSettings 配置规范](#六-projectsettings-配置规范)
---
## 一、 核心算法:3D 空间哈希网格 (Spatial Hash Grid)
### 1. 传统暴力检测的性能瓶颈
在散布计算(`CSGSpreader3D`)中,为防止实例在 3D 体积内互相重叠穿模,朴素方案是对每一个候选位置与已有全部实例进行欧氏距离双重循环检测:
$$\text{复杂度} = \mathcal{O}(N^2)$$
当生成数百个高精度 CSG 几何体时,每秒数十万次的三维距离向量平方运算会导致 Godot 主线程严重卡顿,甚至触发编辑态未响应。
### 2. 空间哈希网格实现原理
`CSG_Blockout` 将 3D 空间哈希网格直接内建于 `CSGSpreader3D` 中,使用以 `Vector3i` 为键的 `Dictionary` 存储:
1. **单元格尺度计算**:
给定用户设定的最小防重叠间距 $d_{\min}$(`min_distance`),网格单元尺寸定义为:
$$\text{Cell Size} = d_{\min}$$
任意两个间距小于 $d_{\min}$ 的点,其在单一坐标轴上的差值不可能超过 $d_{\min}$,因此二者所在单元格在每个维度上至多相差 1。这保证了下述 27 邻域检索必定覆盖全部潜在碰撞候选。
2. **空间坐标量化与哈希映射**:
将任意浮点空间坐标 $\mathbf{P}(x, y, z)$ 离散化为整型网格坐标:
$$\mathbf{cell\_coords} = \left( \lfloor x / \text{CellSize} \rfloor, \lfloor y / \text{CellSize} \rfloor, \lfloor z / \text{CellSize} \rfloor \right)$$
使用基于 `Vector3i` 的字典键做常量时间寻址。
3. **27 邻域检索 (3x3x3 局部性查询)**:
每次验证候选位置时,算法无需遍历全量数据,仅需检索当前单元格以及紧邻的 26 个邻近单元格(共 27 块),将冲突检测的时间复杂度降为:
$$\text{候选冲突检测复杂度} = \mathcal{O}(1)$$
---
## 二、 系统架构与设计模式
```mermaid
graph TD
subgraph Editor Core
Plugin["csg_blockout.gd (EditorPlugin)"]
URM["EditorUndoRedoManager"]
I18N["CsgBlockoutI18n"]
ProjSet["ProjectSettings (addons/csg_blockout/*)"]
end
subgraph UI & Controls
Pie["CSGBlockoutPieMenu (Vector 2D/3D Viewport)"]
SideBar["CSGSideBlockoutBar (Left Viewport Bar)"]
TopBar["CSGTopBlockoutBar (Viewport Header Bar)"]
end
subgraph Node Domain
Combiner["CSGCombiner3D (Godot Built-in)"]
Repeater["CSGRepeater3D"] --> Combiner
Spreader["CSGSpreader3D"] --> Combiner
end
subgraph Strategy Pattern
Pattern["CSGPattern (Resource)"]
GridPat["CSGGridPattern"] --> Pattern
CircPat["CSGCircularPattern"] --> Pattern
SpiralPat["CSGSpiralPattern"] --> Pattern
NoisePat["CSGNoisePattern"] --> Pattern
Repeater -.-> Pattern
end
subgraph Collision & Placement
HashGrid["内建空间哈希网格 (O(1) 查询)"]
Spreader -.-> HashGrid
Spreader -.-> ShapeDomain["Shape3D (Box/Sphere/Mesh/...)"]
end
Plugin --> Pie
Plugin --> SideBar
Plugin --> TopBar
```
### 1. 策略模式:阵列分发器 (`CSGRepeater3D`)
`CSGRepeater3D` 摆脱了传统的硬编码循环,将生成逻辑完全抽象为独立的 `CSGPattern` 资源策略:
- **`CSGGridPattern`**:正交笛卡尔网格阵列,支持 AABB 边界自适应计算。
- **`CSGCircularPattern`**:多层同心极坐标环形阵列。
- **`CSGSpiralPattern`**:阿基米德/对数螺旋分布,支持自定义非线性半径曲线(`Curve`)。
- **`CSGNoisePattern`**:基于 `FastNoiseLite` 的体域噪声阈值采样分布。
### 2. 物理碰撞体边界域:散布系统 (`CSGSpreader3D`)
`CSGSpreader3D` 支持任意 Godot `Shape3D` 作为散布边界,其工作流包括:
- 提取碰撞体的世界空间 AABB 边界。
- 执行内部包含性与随机拒识采样。
- 联动内建空间哈希网格进行实时防重叠过滤。
- 支持最大容错尝试机制(`max_placement_attempts`)。
---
## 三、 程序化世界对齐材质 Shader 设计
`grid_triplanar.gdshader` 是专为白盒原型搭建定制的着色器,核心技术特征包括:
1. **世界坐标三平面投影(World-Space Triplanar Mapping)**:
- 弃用模型 UV 坐标,直接取顶点/片元的世界坐标 $\mathbf{P}_{\text{world}}$ 计算纹理采样。
- 物体在三维空间中随意平移、旋转、缩放或执行布尔切削,网格材质的物理尺寸(如 1m x 1m)永不拉伸扭曲。
2. **硬件级解析度自适应抗锯齿**:
- 利用导数函数 `fwidth()` 与 `smoothstep()` 计算网格边缘线,从根本上杜绝远处网格摩尔纹走样。
3. **性能开销最小化**:
- 无贴图依赖,纯数学公式生成网格与棋盘格,零显存带宽浪费。
---
## 四、 GDScript 2.0 规范与防御性设计
- **全线静态强类型化**:所有脚本启用强类型签名,消除动态查找开销。
- **ClassDB 安全校验**:所有动态实例化节点均经由 `ClassDB.instantiate()` 或类型断言,杜绝无效类抛错。
- **原子级 Undo/Redo**:全面对接 Godot 4.7 `EditorUndoRedoManager`,涵盖节点增删、属性变更、材质覆盖与实例烘焙(`CSGRepeater3D` / `CSGSpreader3D`)。
- **编辑器与运行时完全解耦**:所有工具类逻辑严格置于 `Engine.is_editor_hint()` 防护内,杜绝运行时产生幽灵节点或内存泄漏。
---
## 五、 节点与组件规格参考 (API Reference)
### 1. CSGRepeater3D 属性参考
| 属性名 | 类型 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `template_node` | `Node3D` | `null` | 引用场景树中作为阵列原型的节点。 |
| `template_node_scene` | `PackedScene` | `null` | 预制体模板资源(当未指定 `template_node` 时生效)。 |
| `hide_template` | `bool` | `true` | 生成阵列时自动隐藏原始模板节点。 |
| `pattern` | `CSGPattern` | `null` | 阵列分发策略资源。 |
| `position_jitter` | `float` | `0.0` | 位置微小随机抖动偏移量。 |
| `random_seed` | `int` | `0` | 伪随机数种子。 |
| `estimated_instances` | `int` | `0` | (只读) 预估生成的实例数量。 |
| `randomize_rotation` | `bool` | `false` | 启用旋转随机化。 |
| `randomize_rot_x/y/z` | `bool` | `false` | 各轴向旋转随机开关。 |
| `rotation_variance_x/y/z_deg` | `float` | `0.0` | 旋转随机浮动角度(设为 0 为 360 度全随机)。 |
| `randomize_scale` | `bool` | `false` | 启用缩放随机化。 |
| `scale_variance` | `float` | `0.0` | 等比缩放浮动量。 |
### 2. CSGSpreader3D 属性参考
| 属性名 | 类型 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `template_node` | `Node3D` | `null` | 需要散布的目标模板节点。 |
| `spread_area_3d` | `Shape3D` | `null` | 散布空间域形状(Box, Sphere, Capsule 等)。 |
| `max_count` | `int` | `10` | 散布最大实例上限(硬上限保护为 200)。 |
| `noise_threshold` | `float` | `0.5` | 噪声概率过滤阈值(0.0 至 1.0)。 |
| `seed` | `int` | `0` | 随机种子。 |
| `avoid_overlaps` | `bool` | `false` | 启用空间哈希碰撞避障检查。 |
| `min_distance` | `float` | `1.0` | 实例间最小安全间距。 |
| `max_placement_attempts` | `int` | `100` | 单个实例最大寻位采样尝试次数。 |
| `allow_rotation` | `bool` | `false` | 允许随机 Y 轴偏航旋转。 |
| `allow_scale` | `bool` | `false` | 允许随机缩放(0.5x 至 2.0x)。 |
---
## 六、 ProjectSettings 配置规范
插件所有全局配置项挂载于 Godot 项目设置 `addons/csg_blockout/*` 命名空间下:
| 配置键路径 | 类型 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `addons/csg_blockout/action_key` | `int` (Key) | `KEY_SHIFT` | 3D 轮盘菜单主触发修饰键。 |
| `addons/csg_blockout/auto_hide` | `bool` | `true` | 视口未选中 CSG 节点时自动隐藏左侧边栏。 |
| `addons/csg_blockout/language_override` | `String` | `"auto"` | 界面语言偏好覆盖 (`"auto"`、`"en"`、`"zh_CN"`、`"ja"`、`"ko"`、`"es"`、`"pt"`、`"ru"`)。 |
| `addons/csg_blockout/material_preset` | `int` (Enum) | `1` (GRID_LIGHT) | 默认激活的网格材质预设通道。 |
| `addons/csg_blockout/default_operation` | `int` (Enum) | `0` (并集) | 新建节点的默认 CSG 布尔运算(轮盘菜单与侧栏共享)。 |
| `addons/csg_blockout/custom_material_path` | `String` | `""` | CUSTOM 预设所引用的自定义材质资源路径(跨会话持久化)。 |