three-base 2.0.169 → 2.0.175
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FPScontrol.d.ts +55 -30
- package/FPScontrol.js +278 -225
- package/FPScontrol.ts +177 -127
- package/Ground1/Ground1.d.ts +4 -2
- package/Ground1/Ground1.js +77 -57
- package/Ground1/Ground1.ts +77 -57
- package/Mirror.js +0 -4
- package/Mirror.ts +0 -4
- package/MktMesh/MktMesh.d.ts +8 -3
- package/MktMesh/MktMesh.js +43 -14
- package/MktMesh/MktMesh.ts +40 -14
- package/MktMesh/mktMappingShader.d.ts +6 -5
- package/MktMesh/mktMappingShader.js +26 -19
- package/MktMesh/mktMappingShader.ts +28 -19
- package/MktMesh/mktShader.d.ts +127 -58
- package/MktMesh/mktShader.js +192 -117
- package/MktMesh/mktShader.ts +251 -127
- package/MktMesh/panoSlotRoster.d.ts +2 -2
- package/MktMesh/panoSlotRoster.js +9 -7
- package/MktMesh/panoSlotRoster.ts +9 -7
- package/MktMesh/panoTileStitcher.d.ts +20 -13
- package/MktMesh/panoTileStitcher.js +97 -76
- package/MktMesh/panoTileStitcher.ts +119 -90
- package/MktMesh/types.d.ts +5 -1
- package/MktMesh/types.ts +5 -1
- package/PipeMesh/PipeJoint.d.ts +22 -0
- package/PipeMesh/PipeJoint.js +33 -0
- package/PipeMesh/PipeJoint.ts +38 -0
- package/PipeMesh/PipeMesh.d.ts +94 -22
- package/PipeMesh/PipeMesh.js +192 -53
- package/PipeMesh/PipeMesh.ts +223 -76
- package/PipeMesh/PipeStraight.d.ts +19 -0
- package/PipeMesh/PipeStraight.js +34 -0
- package/PipeMesh/PipeStraight.ts +45 -0
- package/PipeMesh/axisSnap.d.ts +52 -0
- package/PipeMesh/axisSnap.js +52 -0
- package/PipeMesh/axisSnap.ts +93 -0
- package/PipeMesh/directRoute.d.ts +85 -0
- package/PipeMesh/directRoute.js +126 -0
- package/PipeMesh/directRoute.ts +190 -0
- package/PipeMesh/index.d.ts +6 -0
- package/PipeMesh/index.js +6 -0
- package/PipeMesh/index.ts +7 -1
- package/PipeMesh/pipeMaterial.d.ts +16 -0
- package/PipeMesh/pipeMaterial.js +23 -0
- package/PipeMesh/pipeMaterial.ts +26 -0
- package/ThreeBase.d.ts +2 -49
- package/ThreeBase.js +43 -164
- package/ThreeBase.ts +1176 -1314
- package/instanced/InstancedBatch.d.ts +14 -1
- package/instanced/InstancedBatch.js +53 -3
- package/instanced/InstancedBatch.ts +62 -3
- package/instanced/InstancedChild.d.ts +24 -0
- package/instanced/InstancedChild.js +40 -0
- package/instanced/InstancedChild.ts +41 -0
- package/instanced/InstancedGroup.d.ts +48 -0
- package/instanced/InstancedGroup.js +45 -1
- package/instanced/InstancedGroup.ts +85 -0
- package/package.json +2 -7
- package/pass/bloom_pass.js +7 -14
- package/pass/bloom_pass.ts +7 -16
- package/pass/cover_pass.js +7 -15
- package/pass/cover_pass.ts +7 -17
- package/pass/debugDepthState.d.ts +16 -8
- package/pass/debugDepthState.js +4 -0
- package/pass/debugDepthState.ts +27 -9
- package/pass/glow_pass.js +19 -110
- package/pass/glow_pass.ts +19 -115
- package/pass/ssao_pass.d.ts +14 -59
- package/pass/ssao_pass.js +66 -171
- package/pass/ssao_pass.ts +63 -207
- package/pass/stroke_pass.js +13 -16
- package/pass/stroke_pass.ts +14 -18
- package/shaders/baseDepthVisShader.d.ts +1 -1
- package/shaders/baseDepthVisShader.js +1 -1
- package/shaders/baseDepthVisShader.ts +1 -1
- package/shaders/debugDepthCompareShader.d.ts +2 -2
- package/shaders/debugDepthCompareShader.js +2 -2
- package/shaders/debugDepthCompareShader.ts +2 -2
- package/shaders/debugDepthJudgeShader.d.ts +1 -1
- package/shaders/debugDepthJudgeShader.js +1 -1
- package/shaders/debugDepthJudgeShader.ts +1 -1
- package/PipeMesh/PathGeometry.d.ts +0 -44
- package/PipeMesh/PathGeometry.js +0 -307
- package/PipeMesh/PathGeometry.ts +0 -343
- package/PipeMesh/PathPoint.d.ts +0 -17
- package/PipeMesh/PathPoint.js +0 -31
- package/PipeMesh/PathPoint.ts +0 -36
- package/PipeMesh/PathPointList.d.ts +0 -31
- package/PipeMesh/PathPointList.js +0 -209
- package/PipeMesh/PathPointList.ts +0 -227
- package/PipeMesh/PathTubeGeometry.d.ts +0 -25
- package/PipeMesh/PathTubeGeometry.js +0 -130
- package/PipeMesh/PathTubeGeometry.ts +0 -146
- package/WaterFlow/FloatingDuck.d.ts +0 -88
- package/WaterFlow/FloatingDuck.js +0 -307
- package/WaterFlow/FloatingDuck.ts +0 -445
- package/WaterFlow/GPUFluidSimulation.d.ts +0 -56
- package/WaterFlow/GPUFluidSimulation.js +0 -785
- package/WaterFlow/GPUFluidSimulation.ts +0 -827
- package/WaterFlow/ReservoirSystem.d.ts +0 -106
- package/WaterFlow/ReservoirSystem.js +0 -621
- package/WaterFlow/ReservoirSystem.ts +0 -754
- package/WaterFlow/SPHField.d.ts +0 -35
- package/WaterFlow/SPHField.js +0 -204
- package/WaterFlow/SPHField.ts +0 -228
- package/WaterFlow/ScreenSpaceFluidPass.d.ts +0 -69
- package/WaterFlow/ScreenSpaceFluidPass.js +0 -736
- package/WaterFlow/ScreenSpaceFluidPass.ts +0 -789
- package/WaterFlow/ShallowWaterSurface.d.ts +0 -45
- package/WaterFlow/ShallowWaterSurface.js +0 -441
- package/WaterFlow/ShallowWaterSurface.ts +0 -510
- package/WaterFlow/WaterFlow.d.ts +0 -87
- package/WaterFlow/WaterFlow.js +0 -171
- package/WaterFlow/WaterFlow.ts +0 -219
- package/WaterFlow/types.d.ts +0 -161
- package/WaterFlow/types.js +0 -1
- package/WaterFlow/types.ts +0 -189
- package/WaterFlow/waterFlowPass.d.ts +0 -3
- package/WaterFlow/waterFlowPass.js +0 -20
- package/WaterFlow/waterFlowPass.ts +0 -40
- package/shaders/debugExcludedShader.d.ts +0 -13
- package/shaders/debugExcludedShader.js +0 -46
- package/shaders/debugExcludedShader.ts +0 -48
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 直连管道走线(纯数字,零依赖)。
|
|
3
|
+
*
|
|
4
|
+
* 皇上旨 2026-10-25「直接就是点与点直接连接,最简单的方案」:
|
|
5
|
+
* 相邻两个控制点之间就是一根直管(可以是斜的),不再按轴序拆正交段、不再有 90° 弯头。
|
|
6
|
+
* 每段只算三件事:长度 = 两点欧氏距离、方向 = 连线单位向量、中点 = 两点中点。
|
|
7
|
+
*
|
|
8
|
+
* ⭐ 为什么仍单独一个零 import 模块:管道几何要写进 InstancedChild 的实例矩阵(见 PipeMesh.ts),
|
|
9
|
+
* 而「几段、每段多长、朝哪、球放哪」是可独立核对的算术。留成零依赖 ⇒ `test/pipeRoute.test.js`
|
|
10
|
+
* 能直接 require 编译产物逐字段断言,不必起浏览器。
|
|
11
|
+
*
|
|
12
|
+
* ⚠️ 拐角为什么必须补一颗球:直管是**开口圆柱**(CylinderGeometry openEnded,见 PipeStraight.ts),
|
|
13
|
+
* 两段斜管在拐角处只有轴线相交、端面是斜的 ⇒ 夹角外侧必然露一个楔形缺口,能直接看穿管子。
|
|
14
|
+
* 补法取最省事的一种:控制点上放一颗「直径同管」的球(PipeJoint),球面把缺口盖满。
|
|
15
|
+
* 球与管同径 ⇒ 共线时完全看不出来,有夹角时是光滑过渡,不是一串珠子。
|
|
16
|
+
*
|
|
17
|
+
* ⚠️ 上一版(`orthogonalRoute.ts`,2026-10-21 ~ 10-25)是按 axisOrder 逐轴补齐的正交走线 + 90° 弯头,
|
|
18
|
+
* 已整份删除。要找回请从 git 取,别在半路上重新发明一遍。
|
|
19
|
+
*/
|
|
20
|
+
/** 世界坐标点,单位米 */
|
|
21
|
+
export type Vec3 = [number, number, number];
|
|
22
|
+
/** 直管段:几何中心 + 轴向单位向量 + 段长 */
|
|
23
|
+
export interface StraightPart {
|
|
24
|
+
/** 段序号(从 0 起,对应「控制点 i → 控制点 i+1」) */
|
|
25
|
+
index: number;
|
|
26
|
+
/** 直管几何体的中心(单位圆柱沿 +Y 生成,容器再旋转/缩放到此位姿) */
|
|
27
|
+
center: Vec3;
|
|
28
|
+
/** 走线方向,单位向量(任意朝向,不限六向) */
|
|
29
|
+
dir: Vec3;
|
|
30
|
+
/** 段长(米)= 两控制点欧氏距离 */
|
|
31
|
+
length: number;
|
|
32
|
+
}
|
|
33
|
+
/** 拐角补角球:球心压在控制点上,半径 = 直径/2 */
|
|
34
|
+
export interface JointPart {
|
|
35
|
+
/** 对应控制点下标(1 … n-2;两端没有拐角,不补球) */
|
|
36
|
+
index: number;
|
|
37
|
+
center: Vec3;
|
|
38
|
+
radius: number;
|
|
39
|
+
}
|
|
40
|
+
export interface PipePlan {
|
|
41
|
+
straights: StraightPart[];
|
|
42
|
+
joints: JointPart[];
|
|
43
|
+
/** 退化输入说明(点重合、走线全零、直径非法…);渲染不受影响,供面板提示 */
|
|
44
|
+
warnings: string[];
|
|
45
|
+
}
|
|
46
|
+
/** 段长可忽略的判据(与上一版正交方案同量级) */
|
|
47
|
+
export declare const PIPE_EPS = 0.000001;
|
|
48
|
+
/**
|
|
49
|
+
* 算出整条管道的直管 + 补角球清单。
|
|
50
|
+
*
|
|
51
|
+
* ⚠️ 重合的控制点对**不产生直管**(长度 0 的圆柱缩放会让法线退化),但两端点仍参与球的判定 ——
|
|
52
|
+
* 只要该点还连着别的有效直管,球照放,接缝才不会因为一个废段而开口。
|
|
53
|
+
*/
|
|
54
|
+
export declare function planDirectLayout(points: Vec3[], opts?: {
|
|
55
|
+
diameter?: number;
|
|
56
|
+
}): PipePlan;
|
|
57
|
+
/**
|
|
58
|
+
* JSON 是「管道对象」与「编辑页项目」共用的唯一数据形状。
|
|
59
|
+
* 单位米;points 是控制点(不是段),所以重新走线/改直径只改这几个字段即可。
|
|
60
|
+
*
|
|
61
|
+
* ⚠️ version 仍是 1:形状(points / diameter / color)与上一版一致,只是上一版的 `axisOrder`
|
|
62
|
+
* 从「必填参数」降级成「忽略的多余键」⇒ 皇上库里的旧项目照样打得开,只是形状按直连重算。
|
|
63
|
+
*/
|
|
64
|
+
export interface PipeJson {
|
|
65
|
+
format: "three-base.pipe";
|
|
66
|
+
version: 1;
|
|
67
|
+
diameter: number;
|
|
68
|
+
color?: string;
|
|
69
|
+
points: Vec3[];
|
|
70
|
+
}
|
|
71
|
+
export declare const PIPE_JSON_FORMAT = "three-base.pipe";
|
|
72
|
+
export declare const PIPE_JSON_VERSION = 1;
|
|
73
|
+
export declare function makePipeJson(points: Vec3[], diameter: number, color?: string): PipeJson;
|
|
74
|
+
/**
|
|
75
|
+
* 解析结果:`ok=false` 时 `reason` 是人话,可直接弹给编辑页显示;`ok=true` 时 `json` 已归一化。
|
|
76
|
+
* ⚠️ 刻意不用 `{ok:true;json} | {ok:false;reason}` 可辨识联合:库编译走的是 `strict:false`
|
|
77
|
+
* (three-base/tsconfig.json),实测那种写法在 `if (!r.ok)` 之后取 `r.reason` 会报 TS2339。
|
|
78
|
+
*/
|
|
79
|
+
export interface PipeJsonResult {
|
|
80
|
+
ok: boolean;
|
|
81
|
+
json?: PipeJson;
|
|
82
|
+
reason?: string;
|
|
83
|
+
}
|
|
84
|
+
/** 宽松校验:接受对象/字符串,字段缺失或类型错都返回 reason 而不抛异常(导入现场不许崩) */
|
|
85
|
+
export declare function parsePipeJson(input: unknown): PipeJsonResult;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 直连管道走线(纯数字,零依赖)。
|
|
3
|
+
*
|
|
4
|
+
* 皇上旨 2026-10-25「直接就是点与点直接连接,最简单的方案」:
|
|
5
|
+
* 相邻两个控制点之间就是一根直管(可以是斜的),不再按轴序拆正交段、不再有 90° 弯头。
|
|
6
|
+
* 每段只算三件事:长度 = 两点欧氏距离、方向 = 连线单位向量、中点 = 两点中点。
|
|
7
|
+
*
|
|
8
|
+
* ⭐ 为什么仍单独一个零 import 模块:管道几何要写进 InstancedChild 的实例矩阵(见 PipeMesh.ts),
|
|
9
|
+
* 而「几段、每段多长、朝哪、球放哪」是可独立核对的算术。留成零依赖 ⇒ `test/pipeRoute.test.js`
|
|
10
|
+
* 能直接 require 编译产物逐字段断言,不必起浏览器。
|
|
11
|
+
*
|
|
12
|
+
* ⚠️ 拐角为什么必须补一颗球:直管是**开口圆柱**(CylinderGeometry openEnded,见 PipeStraight.ts),
|
|
13
|
+
* 两段斜管在拐角处只有轴线相交、端面是斜的 ⇒ 夹角外侧必然露一个楔形缺口,能直接看穿管子。
|
|
14
|
+
* 补法取最省事的一种:控制点上放一颗「直径同管」的球(PipeJoint),球面把缺口盖满。
|
|
15
|
+
* 球与管同径 ⇒ 共线时完全看不出来,有夹角时是光滑过渡,不是一串珠子。
|
|
16
|
+
*
|
|
17
|
+
* ⚠️ 上一版(`orthogonalRoute.ts`,2026-10-21 ~ 10-25)是按 axisOrder 逐轴补齐的正交走线 + 90° 弯头,
|
|
18
|
+
* 已整份删除。要找回请从 git 取,别在半路上重新发明一遍。
|
|
19
|
+
*/
|
|
20
|
+
/** 段长可忽略的判据(与上一版正交方案同量级) */
|
|
21
|
+
export const PIPE_EPS = 1e-6;
|
|
22
|
+
/**
|
|
23
|
+
* 算出整条管道的直管 + 补角球清单。
|
|
24
|
+
*
|
|
25
|
+
* ⚠️ 重合的控制点对**不产生直管**(长度 0 的圆柱缩放会让法线退化),但两端点仍参与球的判定 ——
|
|
26
|
+
* 只要该点还连着别的有效直管,球照放,接缝才不会因为一个废段而开口。
|
|
27
|
+
*/
|
|
28
|
+
export function planDirectLayout(points, opts = {}) {
|
|
29
|
+
const diameter = opts.diameter ?? 1;
|
|
30
|
+
const warnings = [];
|
|
31
|
+
const radius = diameter / 2;
|
|
32
|
+
if (points.length < 2) {
|
|
33
|
+
warnings.push("控制点少于 2 个,无法走线");
|
|
34
|
+
return { straights: [], joints: [], warnings };
|
|
35
|
+
}
|
|
36
|
+
if (!(diameter > 0)) {
|
|
37
|
+
warnings.push(`直径 ${diameter} 非法(必须为正数,单位米)`);
|
|
38
|
+
return { straights: [], joints: [], warnings };
|
|
39
|
+
}
|
|
40
|
+
const straights = [];
|
|
41
|
+
/** 第 i 段(控制点 i → i+1)是否真的产生了一根直管 */
|
|
42
|
+
const segOk = [];
|
|
43
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
44
|
+
const a = points[i];
|
|
45
|
+
const b = points[i + 1];
|
|
46
|
+
const dx = b[0] - a[0];
|
|
47
|
+
const dy = b[1] - a[1];
|
|
48
|
+
const dz = b[2] - a[2];
|
|
49
|
+
const len = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
50
|
+
if (len < PIPE_EPS) {
|
|
51
|
+
segOk.push(false);
|
|
52
|
+
warnings.push(`第 ${i + 1} 与第 ${i + 2} 个控制点重合,跳过这一段`);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
segOk.push(true);
|
|
56
|
+
straights.push({
|
|
57
|
+
index: i,
|
|
58
|
+
center: [a[0] + dx / 2, a[1] + dy / 2, a[2] + dz / 2],
|
|
59
|
+
dir: [dx / len, dy / len, dz / len],
|
|
60
|
+
length: len,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const joints = [];
|
|
64
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
65
|
+
// 前后都没生出直管 ⇒ 这是个孤立点,补球只是凭空多一颗,没意义
|
|
66
|
+
if (!segOk[i - 1] && !segOk[i])
|
|
67
|
+
continue;
|
|
68
|
+
const p = points[i];
|
|
69
|
+
joints.push({ index: i, center: [p[0], p[1], p[2]], radius });
|
|
70
|
+
}
|
|
71
|
+
if (straights.length === 0 && warnings.length === 0) {
|
|
72
|
+
warnings.push("没有产生任何直管");
|
|
73
|
+
}
|
|
74
|
+
return { straights, joints, warnings };
|
|
75
|
+
}
|
|
76
|
+
export const PIPE_JSON_FORMAT = "three-base.pipe";
|
|
77
|
+
export const PIPE_JSON_VERSION = 1;
|
|
78
|
+
export function makePipeJson(points, diameter, color) {
|
|
79
|
+
const json = { format: PIPE_JSON_FORMAT, version: PIPE_JSON_VERSION, diameter, points };
|
|
80
|
+
if (color)
|
|
81
|
+
json.color = color;
|
|
82
|
+
return json;
|
|
83
|
+
}
|
|
84
|
+
/** 宽松校验:接受对象/字符串,字段缺失或类型错都返回 reason 而不抛异常(导入现场不许崩) */
|
|
85
|
+
export function parsePipeJson(input) {
|
|
86
|
+
let raw = input;
|
|
87
|
+
if (typeof raw === "string") {
|
|
88
|
+
try {
|
|
89
|
+
raw = JSON.parse(raw);
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
return { ok: false, reason: "不是合法 JSON 文本" };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
96
|
+
return { ok: false, reason: "顶层不是 JSON 对象" };
|
|
97
|
+
}
|
|
98
|
+
const obj = raw;
|
|
99
|
+
if (obj.format !== PIPE_JSON_FORMAT) {
|
|
100
|
+
return { ok: false, reason: `format 应为 "${PIPE_JSON_FORMAT}",实际 ${JSON.stringify(obj.format)}` };
|
|
101
|
+
}
|
|
102
|
+
if (obj.version !== PIPE_JSON_VERSION) {
|
|
103
|
+
return { ok: false, reason: `暂不支持 version ${String(obj.version)}(当前只认 ${PIPE_JSON_VERSION})` };
|
|
104
|
+
}
|
|
105
|
+
const points = obj.points;
|
|
106
|
+
if (!Array.isArray(points) || points.length < 2) {
|
|
107
|
+
return { ok: false, reason: "points 至少要有 2 个控制点" };
|
|
108
|
+
}
|
|
109
|
+
const vecs = [];
|
|
110
|
+
for (let i = 0; i < points.length; i++) {
|
|
111
|
+
const p = points[i];
|
|
112
|
+
const isTuple = Array.isArray(p) && p.length === 3 && p.every((n) => typeof n === "number" && Number.isFinite(n));
|
|
113
|
+
if (!isTuple) {
|
|
114
|
+
return { ok: false, reason: `第 ${i + 1} 个控制点不是 [x,y,z] 三个有限数字` };
|
|
115
|
+
}
|
|
116
|
+
vecs.push([p[0], p[1], p[2]]);
|
|
117
|
+
}
|
|
118
|
+
const diameter = typeof obj.diameter === "number" && Number.isFinite(obj.diameter) && obj.diameter > 0
|
|
119
|
+
? obj.diameter
|
|
120
|
+
: NaN;
|
|
121
|
+
if (!(diameter > 0)) {
|
|
122
|
+
return { ok: false, reason: "diameter 缺失或不是正数(单位米)" };
|
|
123
|
+
}
|
|
124
|
+
const color = typeof obj.color === "string" ? obj.color : undefined;
|
|
125
|
+
return { ok: true, json: makePipeJson(vecs, diameter, color) };
|
|
126
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 直连管道走线(纯数字,零依赖)。
|
|
3
|
+
*
|
|
4
|
+
* 皇上旨 2026-10-25「直接就是点与点直接连接,最简单的方案」:
|
|
5
|
+
* 相邻两个控制点之间就是一根直管(可以是斜的),不再按轴序拆正交段、不再有 90° 弯头。
|
|
6
|
+
* 每段只算三件事:长度 = 两点欧氏距离、方向 = 连线单位向量、中点 = 两点中点。
|
|
7
|
+
*
|
|
8
|
+
* ⭐ 为什么仍单独一个零 import 模块:管道几何要写进 InstancedChild 的实例矩阵(见 PipeMesh.ts),
|
|
9
|
+
* 而「几段、每段多长、朝哪、球放哪」是可独立核对的算术。留成零依赖 ⇒ `test/pipeRoute.test.js`
|
|
10
|
+
* 能直接 require 编译产物逐字段断言,不必起浏览器。
|
|
11
|
+
*
|
|
12
|
+
* ⚠️ 拐角为什么必须补一颗球:直管是**开口圆柱**(CylinderGeometry openEnded,见 PipeStraight.ts),
|
|
13
|
+
* 两段斜管在拐角处只有轴线相交、端面是斜的 ⇒ 夹角外侧必然露一个楔形缺口,能直接看穿管子。
|
|
14
|
+
* 补法取最省事的一种:控制点上放一颗「直径同管」的球(PipeJoint),球面把缺口盖满。
|
|
15
|
+
* 球与管同径 ⇒ 共线时完全看不出来,有夹角时是光滑过渡,不是一串珠子。
|
|
16
|
+
*
|
|
17
|
+
* ⚠️ 上一版(`orthogonalRoute.ts`,2026-10-21 ~ 10-25)是按 axisOrder 逐轴补齐的正交走线 + 90° 弯头,
|
|
18
|
+
* 已整份删除。要找回请从 git 取,别在半路上重新发明一遍。
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** 世界坐标点,单位米 */
|
|
22
|
+
export type Vec3 = [number, number, number];
|
|
23
|
+
|
|
24
|
+
/** 直管段:几何中心 + 轴向单位向量 + 段长 */
|
|
25
|
+
export interface StraightPart {
|
|
26
|
+
/** 段序号(从 0 起,对应「控制点 i → 控制点 i+1」) */
|
|
27
|
+
index: number;
|
|
28
|
+
/** 直管几何体的中心(单位圆柱沿 +Y 生成,容器再旋转/缩放到此位姿) */
|
|
29
|
+
center: Vec3;
|
|
30
|
+
/** 走线方向,单位向量(任意朝向,不限六向) */
|
|
31
|
+
dir: Vec3;
|
|
32
|
+
/** 段长(米)= 两控制点欧氏距离 */
|
|
33
|
+
length: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** 拐角补角球:球心压在控制点上,半径 = 直径/2 */
|
|
37
|
+
export interface JointPart {
|
|
38
|
+
/** 对应控制点下标(1 … n-2;两端没有拐角,不补球) */
|
|
39
|
+
index: number;
|
|
40
|
+
center: Vec3;
|
|
41
|
+
radius: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface PipePlan {
|
|
45
|
+
straights: StraightPart[];
|
|
46
|
+
joints: JointPart[];
|
|
47
|
+
/** 退化输入说明(点重合、走线全零、直径非法…);渲染不受影响,供面板提示 */
|
|
48
|
+
warnings: string[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** 段长可忽略的判据(与上一版正交方案同量级) */
|
|
52
|
+
export const PIPE_EPS = 1e-6;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 算出整条管道的直管 + 补角球清单。
|
|
56
|
+
*
|
|
57
|
+
* ⚠️ 重合的控制点对**不产生直管**(长度 0 的圆柱缩放会让法线退化),但两端点仍参与球的判定 ——
|
|
58
|
+
* 只要该点还连着别的有效直管,球照放,接缝才不会因为一个废段而开口。
|
|
59
|
+
*/
|
|
60
|
+
export function planDirectLayout(points: Vec3[], opts: { diameter?: number } = {}): PipePlan {
|
|
61
|
+
const diameter = opts.diameter ?? 1;
|
|
62
|
+
const warnings: string[] = [];
|
|
63
|
+
const radius = diameter / 2;
|
|
64
|
+
|
|
65
|
+
if (points.length < 2) {
|
|
66
|
+
warnings.push("控制点少于 2 个,无法走线");
|
|
67
|
+
return { straights: [], joints: [], warnings };
|
|
68
|
+
}
|
|
69
|
+
if (!(diameter > 0)) {
|
|
70
|
+
warnings.push(`直径 ${diameter} 非法(必须为正数,单位米)`);
|
|
71
|
+
return { straights: [], joints: [], warnings };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const straights: StraightPart[] = [];
|
|
75
|
+
/** 第 i 段(控制点 i → i+1)是否真的产生了一根直管 */
|
|
76
|
+
const segOk: boolean[] = [];
|
|
77
|
+
|
|
78
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
79
|
+
const a = points[i];
|
|
80
|
+
const b = points[i + 1];
|
|
81
|
+
const dx = b[0] - a[0];
|
|
82
|
+
const dy = b[1] - a[1];
|
|
83
|
+
const dz = b[2] - a[2];
|
|
84
|
+
const len = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
85
|
+
if (len < PIPE_EPS) {
|
|
86
|
+
segOk.push(false);
|
|
87
|
+
warnings.push(`第 ${i + 1} 与第 ${i + 2} 个控制点重合,跳过这一段`);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
segOk.push(true);
|
|
91
|
+
straights.push({
|
|
92
|
+
index: i,
|
|
93
|
+
center: [a[0] + dx / 2, a[1] + dy / 2, a[2] + dz / 2],
|
|
94
|
+
dir: [dx / len, dy / len, dz / len],
|
|
95
|
+
length: len,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const joints: JointPart[] = [];
|
|
100
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
101
|
+
// 前后都没生出直管 ⇒ 这是个孤立点,补球只是凭空多一颗,没意义
|
|
102
|
+
if (!segOk[i - 1] && !segOk[i]) continue;
|
|
103
|
+
const p = points[i];
|
|
104
|
+
joints.push({ index: i, center: [p[0], p[1], p[2]], radius });
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (straights.length === 0 && warnings.length === 0) {
|
|
108
|
+
warnings.push("没有产生任何直管");
|
|
109
|
+
}
|
|
110
|
+
return { straights, joints, warnings };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* JSON 是「管道对象」与「编辑页项目」共用的唯一数据形状。
|
|
115
|
+
* 单位米;points 是控制点(不是段),所以重新走线/改直径只改这几个字段即可。
|
|
116
|
+
*
|
|
117
|
+
* ⚠️ version 仍是 1:形状(points / diameter / color)与上一版一致,只是上一版的 `axisOrder`
|
|
118
|
+
* 从「必填参数」降级成「忽略的多余键」⇒ 皇上库里的旧项目照样打得开,只是形状按直连重算。
|
|
119
|
+
*/
|
|
120
|
+
export interface PipeJson {
|
|
121
|
+
format: "three-base.pipe";
|
|
122
|
+
version: 1;
|
|
123
|
+
diameter: number;
|
|
124
|
+
color?: string;
|
|
125
|
+
points: Vec3[];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const PIPE_JSON_FORMAT = "three-base.pipe";
|
|
129
|
+
export const PIPE_JSON_VERSION = 1;
|
|
130
|
+
|
|
131
|
+
export function makePipeJson(points: Vec3[], diameter: number, color?: string): PipeJson {
|
|
132
|
+
const json: PipeJson = { format: PIPE_JSON_FORMAT, version: PIPE_JSON_VERSION, diameter, points };
|
|
133
|
+
if (color) json.color = color;
|
|
134
|
+
return json;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 解析结果:`ok=false` 时 `reason` 是人话,可直接弹给编辑页显示;`ok=true` 时 `json` 已归一化。
|
|
139
|
+
* ⚠️ 刻意不用 `{ok:true;json} | {ok:false;reason}` 可辨识联合:库编译走的是 `strict:false`
|
|
140
|
+
* (three-base/tsconfig.json),实测那种写法在 `if (!r.ok)` 之后取 `r.reason` 会报 TS2339。
|
|
141
|
+
*/
|
|
142
|
+
export interface PipeJsonResult {
|
|
143
|
+
ok: boolean;
|
|
144
|
+
json?: PipeJson;
|
|
145
|
+
reason?: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** 宽松校验:接受对象/字符串,字段缺失或类型错都返回 reason 而不抛异常(导入现场不许崩) */
|
|
149
|
+
export function parsePipeJson(input: unknown): PipeJsonResult {
|
|
150
|
+
let raw: unknown = input;
|
|
151
|
+
if (typeof raw === "string") {
|
|
152
|
+
try {
|
|
153
|
+
raw = JSON.parse(raw);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
return { ok: false, reason: "不是合法 JSON 文本" };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
159
|
+
return { ok: false, reason: "顶层不是 JSON 对象" };
|
|
160
|
+
}
|
|
161
|
+
const obj = raw as Record<string, unknown>;
|
|
162
|
+
if (obj.format !== PIPE_JSON_FORMAT) {
|
|
163
|
+
return { ok: false, reason: `format 应为 "${PIPE_JSON_FORMAT}",实际 ${JSON.stringify(obj.format)}` };
|
|
164
|
+
}
|
|
165
|
+
if (obj.version !== PIPE_JSON_VERSION) {
|
|
166
|
+
return { ok: false, reason: `暂不支持 version ${String(obj.version)}(当前只认 ${PIPE_JSON_VERSION})` };
|
|
167
|
+
}
|
|
168
|
+
const points = obj.points;
|
|
169
|
+
if (!Array.isArray(points) || points.length < 2) {
|
|
170
|
+
return { ok: false, reason: "points 至少要有 2 个控制点" };
|
|
171
|
+
}
|
|
172
|
+
const vecs: Vec3[] = [];
|
|
173
|
+
for (let i = 0; i < points.length; i++) {
|
|
174
|
+
const p = points[i];
|
|
175
|
+
const isTuple =
|
|
176
|
+
Array.isArray(p) && p.length === 3 && p.every((n) => typeof n === "number" && Number.isFinite(n));
|
|
177
|
+
if (!isTuple) {
|
|
178
|
+
return { ok: false, reason: `第 ${i + 1} 个控制点不是 [x,y,z] 三个有限数字` };
|
|
179
|
+
}
|
|
180
|
+
vecs.push([p[0] as number, p[1] as number, p[2] as number]);
|
|
181
|
+
}
|
|
182
|
+
const diameter = typeof obj.diameter === "number" && Number.isFinite(obj.diameter) && obj.diameter > 0
|
|
183
|
+
? obj.diameter
|
|
184
|
+
: NaN;
|
|
185
|
+
if (!(diameter > 0)) {
|
|
186
|
+
return { ok: false, reason: "diameter 缺失或不是正数(单位米)" };
|
|
187
|
+
}
|
|
188
|
+
const color = typeof obj.color === "string" ? obj.color : undefined;
|
|
189
|
+
return { ok: true, json: makePipeJson(vecs, diameter, color) };
|
|
190
|
+
}
|
package/PipeMesh/index.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
1
|
export { default } from "./PipeMesh";
|
|
2
|
+
export { default as PipeMesh } from "./PipeMesh";
|
|
3
|
+
export { default as PipeStraight } from "./PipeStraight";
|
|
4
|
+
export { default as PipeJoint } from "./PipeJoint";
|
|
5
|
+
export { createPipeMaterial, pipeMaterial, PIPE_DEFAULT_COLOR } from "./pipeMaterial";
|
|
6
|
+
export * from "./directRoute";
|
|
7
|
+
export * from "./axisSnap";
|
package/PipeMesh/index.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
1
|
export { default } from "./PipeMesh";
|
|
2
|
+
export { default as PipeMesh } from "./PipeMesh";
|
|
3
|
+
export { default as PipeStraight } from "./PipeStraight";
|
|
4
|
+
export { default as PipeJoint } from "./PipeJoint";
|
|
5
|
+
export { createPipeMaterial, pipeMaterial, PIPE_DEFAULT_COLOR } from "./pipeMaterial";
|
|
6
|
+
export * from "./directRoute";
|
|
7
|
+
export * from "./axisSnap";
|
package/PipeMesh/index.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
export { default } from "./PipeMesh";
|
|
1
|
+
export { default } from "./PipeMesh";
|
|
2
|
+
export { default as PipeMesh } from "./PipeMesh";
|
|
3
|
+
export { default as PipeStraight } from "./PipeStraight";
|
|
4
|
+
export { default as PipeJoint } from "./PipeJoint";
|
|
5
|
+
export { createPipeMaterial, pipeMaterial, PIPE_DEFAULT_COLOR } from "./pipeMaterial";
|
|
6
|
+
export * from "./directRoute";
|
|
7
|
+
export * from "./axisSnap";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MeshStandardMaterial } from "three";
|
|
2
|
+
/**
|
|
3
|
+
* 直管与弯头共用一份材质。
|
|
4
|
+
*
|
|
5
|
+
* ⭐ 为什么底色是白:实例化那条路,逐实例颜色走 `InstancedMesh.instanceColor`(InstancedBatch 预填 1.0,
|
|
6
|
+
* setColor 覆盖),three 里最终 diffuse = material.color × instanceColor。材质底色若非白,setColor 的值
|
|
7
|
+
* 就会被整体压暗,面板上「这根管子涂什么色」就对不上画面了。
|
|
8
|
+
* ⭐ 为什么两边共享同一份:材质只有一份 ⇒ 粗糙度/金属度改一次,两个 batch(直管、弯头)同时跟上;
|
|
9
|
+
* 合批是按 geometry+material 分桶的,共享材质不会把它们并成一个 batch(几何不同),draw call 仍是 2。
|
|
10
|
+
* ⚠️ DoubleSide 是必需的:直管是开口圆柱(无端面),从管口往里看要能看到内壁,否则管子里是黑的空洞。
|
|
11
|
+
*/
|
|
12
|
+
export declare function createPipeMaterial(): MeshStandardMaterial;
|
|
13
|
+
/** 全库共享的那一份材质实例(InstancedChild 的 static material 必须是同一个对象才会同桶/同改) */
|
|
14
|
+
export declare const pipeMaterial: MeshStandardMaterial;
|
|
15
|
+
/** 管道默认颜色,取自参考稿 */
|
|
16
|
+
export declare const PIPE_DEFAULT_COLOR = 5227511;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DoubleSide, MeshStandardMaterial } from "three";
|
|
2
|
+
/**
|
|
3
|
+
* 直管与弯头共用一份材质。
|
|
4
|
+
*
|
|
5
|
+
* ⭐ 为什么底色是白:实例化那条路,逐实例颜色走 `InstancedMesh.instanceColor`(InstancedBatch 预填 1.0,
|
|
6
|
+
* setColor 覆盖),three 里最终 diffuse = material.color × instanceColor。材质底色若非白,setColor 的值
|
|
7
|
+
* 就会被整体压暗,面板上「这根管子涂什么色」就对不上画面了。
|
|
8
|
+
* ⭐ 为什么两边共享同一份:材质只有一份 ⇒ 粗糙度/金属度改一次,两个 batch(直管、弯头)同时跟上;
|
|
9
|
+
* 合批是按 geometry+material 分桶的,共享材质不会把它们并成一个 batch(几何不同),draw call 仍是 2。
|
|
10
|
+
* ⚠️ DoubleSide 是必需的:直管是开口圆柱(无端面),从管口往里看要能看到内壁,否则管子里是黑的空洞。
|
|
11
|
+
*/
|
|
12
|
+
export function createPipeMaterial() {
|
|
13
|
+
return new MeshStandardMaterial({
|
|
14
|
+
color: 0xffffff,
|
|
15
|
+
roughness: 0.35,
|
|
16
|
+
metalness: 0.5,
|
|
17
|
+
side: DoubleSide,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** 全库共享的那一份材质实例(InstancedChild 的 static material 必须是同一个对象才会同桶/同改) */
|
|
21
|
+
export const pipeMaterial = createPipeMaterial();
|
|
22
|
+
/** 管道默认颜色,取自参考稿 */
|
|
23
|
+
export const PIPE_DEFAULT_COLOR = 0x4fc3f7;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DoubleSide, MeshStandardMaterial } from "three";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 直管与弯头共用一份材质。
|
|
5
|
+
*
|
|
6
|
+
* ⭐ 为什么底色是白:实例化那条路,逐实例颜色走 `InstancedMesh.instanceColor`(InstancedBatch 预填 1.0,
|
|
7
|
+
* setColor 覆盖),three 里最终 diffuse = material.color × instanceColor。材质底色若非白,setColor 的值
|
|
8
|
+
* 就会被整体压暗,面板上「这根管子涂什么色」就对不上画面了。
|
|
9
|
+
* ⭐ 为什么两边共享同一份:材质只有一份 ⇒ 粗糙度/金属度改一次,两个 batch(直管、弯头)同时跟上;
|
|
10
|
+
* 合批是按 geometry+material 分桶的,共享材质不会把它们并成一个 batch(几何不同),draw call 仍是 2。
|
|
11
|
+
* ⚠️ DoubleSide 是必需的:直管是开口圆柱(无端面),从管口往里看要能看到内壁,否则管子里是黑的空洞。
|
|
12
|
+
*/
|
|
13
|
+
export function createPipeMaterial(): MeshStandardMaterial {
|
|
14
|
+
return new MeshStandardMaterial({
|
|
15
|
+
color: 0xffffff,
|
|
16
|
+
roughness: 0.35,
|
|
17
|
+
metalness: 0.5,
|
|
18
|
+
side: DoubleSide,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** 全库共享的那一份材质实例(InstancedChild 的 static material 必须是同一个对象才会同桶/同改) */
|
|
23
|
+
export const pipeMaterial = createPipeMaterial();
|
|
24
|
+
|
|
25
|
+
/** 管道默认颜色,取自参考稿 */
|
|
26
|
+
export const PIPE_DEFAULT_COLOR = 0x4fc3f7;
|
package/ThreeBase.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ import ThreeMouse from "./ThreeMouse";
|
|
|
4
4
|
import InstancedGroup from "./instanced/InstancedGroup";
|
|
5
5
|
import Transition from "./Transition";
|
|
6
6
|
import { type DebugDepthMode } from "./pass/debugDepthState";
|
|
7
|
-
import { WaterFlow } from "./WaterFlow/WaterFlow";
|
|
8
7
|
import type { ThreeBaseEventTypeMap } from "./EventMap";
|
|
9
8
|
type CameraType = "perspectiveCamera" | "orthographicCamera";
|
|
10
9
|
type ControlType = "OrbitControls" | "MapControls";
|
|
@@ -79,35 +78,18 @@ export default class ThreeBase extends EventDispatcher<ThreeBaseEventTypeMap> {
|
|
|
79
78
|
get effectiveRatio(): number;
|
|
80
79
|
baseDepthTexture: DepthTexture;
|
|
81
80
|
baseRenderTarget: WebGLRenderTarget<Texture>;
|
|
82
|
-
/** 可选的屏幕空间水流对象(WaterFlow)。默认 null;调用 enableWaterFlow() 后创建。启用时
|
|
83
|
-
* 每帧消费 baseRenderTarget/baseDepthTexture,把水面合成进后处理链(不额外渲染主场景)。 */
|
|
84
|
-
waterFlow: WaterFlow | null;
|
|
85
|
-
private _waterFlowLastTime;
|
|
86
|
-
waterFlowElapsed: number;
|
|
87
|
-
excludedMaskRenderTarget: WebGLRenderTarget<Texture>;
|
|
88
81
|
depthRenderTarget: WebGLRenderTarget<Texture>;
|
|
89
82
|
aoDepthTexture: DepthTexture;
|
|
90
83
|
/**
|
|
91
84
|
* 调试用:深度预览模式。由面板「深度调试」切换,便于逐一看各深度图排查"深度测试全部失效"根因。
|
|
92
85
|
* - "none" :正常渲染(默认)
|
|
93
|
-
* - "global"
|
|
94
|
-
* - "ao" :仅预览 AO 深度图(aoDepthTexture = 法线 pass
|
|
86
|
+
* - "global" :仅预览可见深度图(baseDepthTexture;2026-10-18 起收全场景对象,含地板)。全白=深度为空→renderVisibleDepthPass 没写进深度。
|
|
87
|
+
* - "ao" :仅预览 AO 深度图(aoDepthTexture = 法线 pass 顺带写入)。用于确认深度管线本身是否工作。
|
|
95
88
|
* - "compare" :R=全局 base 深度,G=最近一次 glow/stroke 选区 select 深度。两路任一全白即该侧写入失败。
|
|
96
|
-
* - "excluded":深度图灰度 + 「被排除出深度图的面」叠红(红=该面写不进深度,永远挡不住后处理)。
|
|
97
|
-
* 物体区域(G 暗)若 B 全黑 → 判定从不触发;再看该区 R/G 谁大即可定位是谁缺深度。
|
|
98
89
|
* 兼容旧控制台入口:设置 `window.__BASE_DEPTH_VIS = true` 等价于切到 "global"。
|
|
99
90
|
* 通用控制台入口:任意页面都可 `window.__TB_DEBUG_DEPTH = "judge"`(优先级高于面板属性)。
|
|
100
91
|
*/
|
|
101
92
|
debugDepthPreview: DebugDepthMode;
|
|
102
|
-
/**
|
|
103
|
-
* 可见深度图是否包含「标了 userData.aoFloor 的地板」(如 Ground1)。
|
|
104
|
-
*
|
|
105
|
-
* 默认 false —— 原设计:地板可透视,透过地板看到的物体照常显示(不被地板挡住)。
|
|
106
|
-
* 置 true 后地板会写进 baseDepthTexture,**被地板挡住的描边/辉光/毛玻璃/覆盖色会被正确遮挡**。
|
|
107
|
-
* 排查"怎么都挡不住"时先开这个试一下:若开了就正常,说明挡你的正是可透视地板。
|
|
108
|
-
*/
|
|
109
|
-
get baseDepthIncludeFloor(): boolean;
|
|
110
|
-
set baseDepthIncludeFloor(v: boolean);
|
|
111
93
|
normalRenderTarget: WebGLRenderTarget<Texture>;
|
|
112
94
|
screenRenderTarget: WebGLRenderTarget<Texture>;
|
|
113
95
|
screenCopyShader: import("three").ShaderMaterial;
|
|
@@ -174,35 +156,6 @@ export default class ThreeBase extends EventDispatcher<ThreeBaseEventTypeMap> {
|
|
|
174
156
|
gridHelper: GridHelper;
|
|
175
157
|
axesHelper: AxesHelper;
|
|
176
158
|
init(): void;
|
|
177
|
-
/**
|
|
178
|
-
* 启用屏幕空间水流(GPGPU 粒子流体)。默认关闭,需显式调用或携带 ?waterflow=1。
|
|
179
|
-
* 创建后每帧自动消费 base 深度 + 当前合成画面,把水面合成进后处理链,不自渲染主场景。
|
|
180
|
-
* @param options.size 粒子网格边长(size×size 粒子),越大越细腻、越费
|
|
181
|
-
* @param options.speed 射流初速
|
|
182
|
-
* @param options.aperture 喷嘴开度
|
|
183
|
-
* @param options.nozzle 喷流起点坐标 [x,y,z],默认 [0.58,1.55,0]
|
|
184
|
-
* @param options.jetDirection 喷流方向(轴向,会被归一化),默认 [1,0,0](沿 +X)
|
|
185
|
-
* @param options.collision 是否开启粒子与 basin/地面碰撞回弹,默认 true
|
|
186
|
-
*/
|
|
187
|
-
enableWaterFlow(options?: {
|
|
188
|
-
size?: number;
|
|
189
|
-
speed?: number;
|
|
190
|
-
aperture?: number;
|
|
191
|
-
nozzle?: [number, number, number];
|
|
192
|
-
jetDirection?: [number, number, number];
|
|
193
|
-
collision?: boolean;
|
|
194
|
-
}): void;
|
|
195
|
-
/** 运行时改喷流起点(喷嘴)坐标(WaterFlow 已启用时有效) */
|
|
196
|
-
setWaterFlowNozzle(x: number, y: number, z: number): void;
|
|
197
|
-
/** 运行时改喷流方向(轴向,会被归一化) */
|
|
198
|
-
setWaterFlowJetDirection(x: number, y: number, z: number): void;
|
|
199
|
-
/** 运行时开关粒子与 basin/地面碰撞回弹 */
|
|
200
|
-
setWaterFlowCollision(enabled: boolean): void;
|
|
201
|
-
/**
|
|
202
|
-
* 关闭屏幕空间水流并释放其 GPU 资源(enableWaterFlow 的反操作)。
|
|
203
|
-
* 切走页面时必须调用,否则其它页面 render 仍会合成水面(this.waterFlow 非空)。
|
|
204
|
-
*/
|
|
205
|
-
disableWaterFlow(): void;
|
|
206
159
|
resetLookAt({ position, center, }: {
|
|
207
160
|
position: Vector3;
|
|
208
161
|
center: Vector3;
|