@d5techs/3dgs-lib 1.1.0 → 1.1.1
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/dist/3dgs-lib.cjs +2948 -349
- package/dist/3dgs-lib.cjs.map +1 -1
- package/dist/3dgs-lib.js +2948 -349
- package/dist/3dgs-lib.js.map +1 -1
- package/dist/App.d.ts +28 -7
- package/dist/core/BoundingBoxRenderer.d.ts +1 -3
- package/dist/core/OrbitControls.d.ts +21 -41
- package/dist/core/gizmo/{TransformGizmoV2.d.ts → TransformGizmo.d.ts} +2 -2
- package/dist/core/{ViewportGizmo.d.ts → gizmo/ViewportGizmo.d.ts} +2 -2
- package/dist/core/gizmo/index.d.ts +3 -2
- package/dist/core/index.d.ts +7 -0
- package/dist/gs/GSSplatRenderer.d.ts +48 -2
- package/dist/gs/GSSplatRendererMobile.d.ts +2 -1
- package/dist/gs/GSSplatSorter.d.ts +3 -0
- package/dist/gs/IGSSplatRenderer.d.ts +31 -2
- package/dist/gs/SOGLoader.d.ts +25 -0
- package/dist/index.d.ts +10 -9
- package/dist/interaction/GizmoManager.d.ts +6 -6
- package/dist/interaction/HotspotManager.d.ts +142 -0
- package/dist/mesh/Mesh.d.ts +4 -8
- package/dist/mesh/MeshRenderer.d.ts +30 -14
- package/dist/scene/SceneManager.d.ts +8 -2
- package/package.json +4 -1
package/dist/App.d.ts
CHANGED
|
@@ -17,11 +17,12 @@ import { MeshRenderer } from "./mesh/MeshRenderer";
|
|
|
17
17
|
import { Mesh } from "./mesh/Mesh";
|
|
18
18
|
import { GSSplatRenderer } from "./gs/GSSplatRenderer";
|
|
19
19
|
import { GSSplatRendererMobile } from "./gs/GSSplatRendererMobile";
|
|
20
|
-
import type { BoundingBox } from "./types";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
|
|
20
|
+
import type { BoundingBox, SimpleBoundingBox } from "./types";
|
|
21
|
+
import { HotspotManager } from "./interaction/HotspotManager";
|
|
22
|
+
import type { HotspotInfo } from "./interaction/HotspotManager";
|
|
23
|
+
import { SplatTransformProxy, MeshGroupProxy, SplatBoundingBoxProvider } from "./scene/proxies";
|
|
24
|
+
import { TransformableObject, GizmoMode } from "./core/gizmo/TransformGizmo";
|
|
25
|
+
import type { BoundingBoxProvider } from "./types";
|
|
25
26
|
/**
|
|
26
27
|
* 统一进度回调类型
|
|
27
28
|
* @param progress 进度值 0-100
|
|
@@ -41,6 +42,7 @@ export declare class App {
|
|
|
41
42
|
private objLoader;
|
|
42
43
|
private sceneManager;
|
|
43
44
|
private gizmoManager;
|
|
45
|
+
private hotspotManager;
|
|
44
46
|
private isRunning;
|
|
45
47
|
private animationId;
|
|
46
48
|
private useMobileRenderer;
|
|
@@ -66,6 +68,10 @@ export declare class App {
|
|
|
66
68
|
* 加载 Splat 文件
|
|
67
69
|
*/
|
|
68
70
|
addSplat(urlOrBuffer: string | ArrayBuffer, onProgress?: ProgressCallback, isLocalFile?: boolean): Promise<number>;
|
|
71
|
+
/**
|
|
72
|
+
* 加载 SOG 文件 (Spatially Ordered Gaussians)
|
|
73
|
+
*/
|
|
74
|
+
addSOG(urlOrBuffer: string | ArrayBuffer, onProgress?: ProgressCallback, isLocalFile?: boolean): Promise<number>;
|
|
69
75
|
/**
|
|
70
76
|
* 添加测试立方体
|
|
71
77
|
*/
|
|
@@ -105,13 +111,18 @@ export declare class App {
|
|
|
105
111
|
getMeshColor(index: number): [number, number, number, number] | null;
|
|
106
112
|
setMeshColor(index: number, r: number, g: number, b: number, a?: number): boolean;
|
|
107
113
|
setMeshRangeColor(startIndex: number, count: number, r: number, g: number, b: number, a?: number): number;
|
|
114
|
+
getOverlayMeshCount(): number;
|
|
115
|
+
removeOverlayMeshByIndex(index: number): boolean;
|
|
116
|
+
getOverlayMeshColor(index: number): [number, number, number, number] | null;
|
|
117
|
+
setOverlayMeshRangeColor(startIndex: number, count: number, r: number, g: number, b: number, a?: number): number;
|
|
118
|
+
createOverlayMeshGroupProxy(startIndex: number, count: number): MeshGroupProxy | null;
|
|
108
119
|
frameCurrentModel(animate?: boolean): boolean;
|
|
109
|
-
getTransformGizmo(): import(".").
|
|
120
|
+
getTransformGizmo(): import(".").TransformGizmo;
|
|
110
121
|
getViewportGizmo(): import(".").ViewportGizmo;
|
|
111
122
|
getBoundingBoxRenderer(): import(".").BoundingBoxRenderer;
|
|
112
123
|
setGizmoMode(mode: GizmoMode): void;
|
|
113
124
|
setGizmoTarget(object: TransformableObject | null): void;
|
|
114
|
-
setSelectionBoundingBox(box:
|
|
125
|
+
setSelectionBoundingBox(box: SimpleBoundingBox | null): void;
|
|
115
126
|
setSelectionBoundingBoxProvider(provider: BoundingBoxProvider | null): void;
|
|
116
127
|
clearSelectionBoundingBox(): void;
|
|
117
128
|
/**
|
|
@@ -133,6 +144,16 @@ export declare class App {
|
|
|
133
144
|
getGSRenderer(): GSSplatRenderer | undefined;
|
|
134
145
|
getGSRendererMobile(): GSSplatRendererMobile | undefined;
|
|
135
146
|
isUsingMobileRenderer(): boolean;
|
|
147
|
+
getHotspotManager(): HotspotManager;
|
|
148
|
+
enterHotspotMode(objUrl: string): void;
|
|
149
|
+
exitHotspotMode(): void;
|
|
150
|
+
isHotspotModeActive(): boolean;
|
|
151
|
+
getHotspots(): HotspotInfo[];
|
|
152
|
+
setHotspotBillboard(hotspotIndex: number, enabled: boolean): boolean;
|
|
153
|
+
getHotspotBillboard(hotspotIndex: number): boolean;
|
|
154
|
+
getHotspotCount(): number;
|
|
155
|
+
findHotspotIndexByMeshStart(overlayMeshStartIndex: number): number;
|
|
156
|
+
getOverlayMeshByIndex(index: number): import("./mesh/Mesh").Mesh | null;
|
|
136
157
|
private fetchWithProgress;
|
|
137
158
|
private parsePLYBuffer;
|
|
138
159
|
/**
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Renderer } from "./Renderer";
|
|
2
2
|
import { Camera } from "./Camera";
|
|
3
3
|
import type { SimpleBoundingBox, BoundingBoxProvider } from "../types";
|
|
4
|
-
export type { BoundingBoxProvider };
|
|
5
|
-
export type BoundingBox = SimpleBoundingBox;
|
|
6
4
|
/**
|
|
7
5
|
* BoundingBoxRenderer - 包围盒线框渲染器
|
|
8
6
|
* 用于显示选中对象的包围盒,支持动态跟随
|
|
@@ -35,7 +33,7 @@ export declare class BoundingBoxRenderer {
|
|
|
35
33
|
/**
|
|
36
34
|
* 设置静态包围盒(不会自动更新)
|
|
37
35
|
*/
|
|
38
|
-
setBoundingBox(box:
|
|
36
|
+
setBoundingBox(box: SimpleBoundingBox | null): void;
|
|
39
37
|
/**
|
|
40
38
|
* 清除包围盒
|
|
41
39
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Camera } from "./Camera";
|
|
2
2
|
/**
|
|
3
3
|
* OrbitControls - 轨道控制器
|
|
4
|
-
*
|
|
4
|
+
* 支持阻尼惯性、屏幕空间平移、中键拖拽、指数缩放
|
|
5
5
|
*/
|
|
6
6
|
export declare class OrbitControls {
|
|
7
7
|
private camera;
|
|
@@ -18,9 +18,17 @@ export declare class OrbitControls {
|
|
|
18
18
|
panSpeed: number;
|
|
19
19
|
touchZoomSpeed: number;
|
|
20
20
|
touchPanSpeed: number;
|
|
21
|
+
enableDamping: boolean;
|
|
22
|
+
dampingFactor: number;
|
|
21
23
|
private isDragging;
|
|
22
24
|
private lastX;
|
|
23
25
|
private lastY;
|
|
26
|
+
private velocityTheta;
|
|
27
|
+
private velocityPhi;
|
|
28
|
+
private velocityDistance;
|
|
29
|
+
private velocityPanX;
|
|
30
|
+
private velocityPanY;
|
|
31
|
+
private velocityPanZ;
|
|
24
32
|
private touchMode;
|
|
25
33
|
private lastTouchDistance;
|
|
26
34
|
private lastTouchCenter;
|
|
@@ -34,18 +42,17 @@ export declare class OrbitControls {
|
|
|
34
42
|
private boundOnTouchEnd;
|
|
35
43
|
private boundOnContextMenu;
|
|
36
44
|
constructor(camera: Camera, canvas: HTMLCanvasElement);
|
|
37
|
-
/**
|
|
38
|
-
* 设置事件监听
|
|
39
|
-
*/
|
|
40
45
|
private setupEventListeners;
|
|
46
|
+
private removeEventListeners;
|
|
47
|
+
destroy(): void;
|
|
41
48
|
/**
|
|
42
|
-
*
|
|
49
|
+
* 从视图矩阵提取相机的 right 和 up 向量,用于屏幕空间平移
|
|
43
50
|
*/
|
|
44
|
-
private
|
|
51
|
+
private getCameraAxes;
|
|
45
52
|
/**
|
|
46
|
-
*
|
|
53
|
+
* 屏幕空间平移:将屏幕 delta 映射到相机 right/up 方向
|
|
47
54
|
*/
|
|
48
|
-
|
|
55
|
+
private panByScreenDelta;
|
|
49
56
|
private onMouseDown;
|
|
50
57
|
private onMouseMove;
|
|
51
58
|
private onMouseUp;
|
|
@@ -53,49 +60,22 @@ export declare class OrbitControls {
|
|
|
53
60
|
private onTouchStart;
|
|
54
61
|
private onTouchMove;
|
|
55
62
|
private onTouchEnd;
|
|
56
|
-
/**
|
|
57
|
-
* 计算双指之间的距离
|
|
58
|
-
*/
|
|
59
63
|
private getTouchDistance;
|
|
60
|
-
/**
|
|
61
|
-
* 计算双指的中心点
|
|
62
|
-
*/
|
|
63
64
|
private getTouchCenter;
|
|
64
65
|
/**
|
|
65
|
-
*
|
|
66
|
+
* 将球坐标写入相机位置(内部方法,不处理阻尼)
|
|
66
67
|
*/
|
|
67
|
-
|
|
68
|
+
private applySpherical;
|
|
68
69
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* @param positive 是否正向
|
|
72
|
-
* @param animate 是否动画过渡
|
|
70
|
+
* 每帧调用:应用阻尼衰减并更新相机
|
|
71
|
+
* 在渲染循环中调用此方法以获得平滑惯性效果
|
|
73
72
|
*/
|
|
73
|
+
update(): void;
|
|
74
74
|
setViewAxis(axis: string, positive: boolean, animate?: boolean): void;
|
|
75
|
-
/**
|
|
76
|
-
* 动画过渡到目标视图
|
|
77
|
-
*/
|
|
78
75
|
private animateToView;
|
|
79
|
-
/**
|
|
80
|
-
* 设置相机目标点(控制器旋转中心)
|
|
81
|
-
* @param x X 坐标
|
|
82
|
-
* @param y Y 坐标
|
|
83
|
-
* @param z Z 坐标
|
|
84
|
-
*/
|
|
85
76
|
setTarget(x: number, y: number, z: number): void;
|
|
86
|
-
/**
|
|
87
|
-
* 获取当前目标点
|
|
88
|
-
*/
|
|
89
77
|
getTarget(): [number, number, number];
|
|
90
|
-
/**
|
|
91
|
-
* 根据模型参数自动调整相机位置和参数
|
|
92
|
-
* @param center 模型中心点
|
|
93
|
-
* @param radius 模型包围球半径
|
|
94
|
-
* @param animate 是否使用动画过渡
|
|
95
|
-
*/
|
|
96
78
|
frameModel(center: [number, number, number], radius: number, animate?: boolean): void;
|
|
97
|
-
/**
|
|
98
|
-
* 动画过渡到目标帧(包含目标点和距离)
|
|
99
|
-
*/
|
|
100
79
|
private animateToFrame;
|
|
80
|
+
clearVelocity(): void;
|
|
101
81
|
}
|
|
@@ -65,10 +65,10 @@ export interface TransformGizmoConfig {
|
|
|
65
65
|
snapIncrement?: number;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
68
|
+
* TransformGizmo - 变换 Gizmo
|
|
69
69
|
* 参考 PlayCanvas 引擎的 TransformGizmo 实现
|
|
70
70
|
*/
|
|
71
|
-
export declare class
|
|
71
|
+
export declare class TransformGizmo {
|
|
72
72
|
private renderer;
|
|
73
73
|
private camera;
|
|
74
74
|
private canvas;
|
|
@@ -10,5 +10,6 @@ export { ArcShape } from "./ArcShape";
|
|
|
10
10
|
export type { ArcShapeConfig, ArcDisplayMode } from "./ArcShape";
|
|
11
11
|
export { BoxLineShape } from "./BoxLineShape";
|
|
12
12
|
export type { BoxLineShapeConfig } from "./BoxLineShape";
|
|
13
|
-
export {
|
|
14
|
-
export
|
|
13
|
+
export { ViewportGizmo } from "./ViewportGizmo";
|
|
14
|
+
export { TransformGizmo, GizmoMode } from "./TransformGizmo";
|
|
15
|
+
export type { TransformGizmoConfig, TransformableObject, GizmoSpace, GizmoDragMode, GizmoTheme, } from "./TransformGizmo";
|
|
@@ -15,8 +15,6 @@ import { CompactSplatData } from "./PLYLoaderMobile";
|
|
|
15
15
|
import type { BoundingBox, Vec3Tuple } from "../types";
|
|
16
16
|
import { SHMode, RendererCapabilities } from "../types";
|
|
17
17
|
import type { IGSSplatRendererWithCapabilities } from "./IGSSplatRenderer";
|
|
18
|
-
export { SHMode };
|
|
19
|
-
export type { BoundingBox };
|
|
20
18
|
/**
|
|
21
19
|
* GSSplatRendererV2 - 优化的渲染器
|
|
22
20
|
*/
|
|
@@ -32,15 +30,37 @@ export declare class GSSplatRenderer implements IGSSplatRendererWithCapabilities
|
|
|
32
30
|
private sorter;
|
|
33
31
|
private shMode;
|
|
34
32
|
private boundingBox;
|
|
33
|
+
private cpuPositions;
|
|
35
34
|
private position;
|
|
36
35
|
private rotation;
|
|
37
36
|
private scale;
|
|
38
37
|
private pivot;
|
|
39
38
|
private modelMatrix;
|
|
40
39
|
private pixelCullThreshold;
|
|
40
|
+
private maxVisibleSplats;
|
|
41
|
+
private lastSortViewMatrix;
|
|
42
|
+
private lastSortProjMatrix;
|
|
43
|
+
private lastSortModelMatrix;
|
|
44
|
+
private lastSortWidth;
|
|
45
|
+
private lastSortHeight;
|
|
46
|
+
private lastSortPixelThreshold;
|
|
47
|
+
private lastSortMaxVisible;
|
|
48
|
+
private sortStateInitialized;
|
|
49
|
+
private sortFrequency;
|
|
50
|
+
private frameCounter;
|
|
51
|
+
private depthNormalPipeline;
|
|
52
|
+
private depthRT;
|
|
53
|
+
private depthRTView;
|
|
54
|
+
private normalRT;
|
|
55
|
+
private normalRTView;
|
|
56
|
+
private dnRTWidth;
|
|
57
|
+
private dnRTHeight;
|
|
58
|
+
private dnResult;
|
|
41
59
|
constructor(renderer: Renderer, camera: Camera);
|
|
42
60
|
private createPipeline;
|
|
43
61
|
private createUniformBuffer;
|
|
62
|
+
private createDepthNormalPipeline;
|
|
63
|
+
private ensureDepthNormalTextures;
|
|
44
64
|
setPosition(x: number, y: number, z: number): void;
|
|
45
65
|
getPosition(): Vec3Tuple;
|
|
46
66
|
setRotation(x: number, y: number, z: number): void;
|
|
@@ -54,13 +74,39 @@ export declare class GSSplatRenderer implements IGSSplatRendererWithCapabilities
|
|
|
54
74
|
setSHMode(mode: SHMode): void;
|
|
55
75
|
getSHMode(): SHMode;
|
|
56
76
|
setPixelCullThreshold(threshold: number): void;
|
|
77
|
+
/**
|
|
78
|
+
* 设置最大可见 splat 数量
|
|
79
|
+
* 排序后只保留距离最近的 N 个 splat,远处被遮挡的 splat 被丢弃
|
|
80
|
+
* 0 = 不限制
|
|
81
|
+
*/
|
|
82
|
+
setMaxVisibleSplats(count: number): void;
|
|
83
|
+
getMaxVisibleSplats(): number;
|
|
84
|
+
/**
|
|
85
|
+
* 设置排序频率
|
|
86
|
+
* 1 = 每帧排序(默认),2 = 每 2 帧排序一次,以此类推
|
|
87
|
+
* 相机静止时自动跳过排序,不受此参数影响
|
|
88
|
+
*/
|
|
89
|
+
setSortFrequency(frequency: number): void;
|
|
90
|
+
getSortFrequency(): number;
|
|
91
|
+
private needsSort;
|
|
92
|
+
private saveSortState;
|
|
57
93
|
setData(splats: SplatCPU[]): void;
|
|
58
94
|
setCompactData(compactData: CompactSplatData): void;
|
|
59
95
|
render(pass: GPURenderPassEncoder): void;
|
|
60
96
|
getSplatCount(): number;
|
|
61
97
|
getBoundingBox(): BoundingBox | null;
|
|
98
|
+
getCPUPositions(): Float32Array | null;
|
|
62
99
|
private computeBoundingBox;
|
|
63
100
|
private computeBoundingBoxFromCompact;
|
|
101
|
+
prepareDepthNormalPass(px?: number, py?: number): void;
|
|
102
|
+
private static half2Float;
|
|
103
|
+
private static _f32;
|
|
104
|
+
private static _u32;
|
|
105
|
+
getDepthNormal(): {
|
|
106
|
+
depth: number;
|
|
107
|
+
normal: Vec3Tuple;
|
|
108
|
+
worldPos: Vec3Tuple;
|
|
109
|
+
} | null;
|
|
64
110
|
supportsSHMode(mode: SHMode): boolean;
|
|
65
111
|
getCapabilities(): RendererCapabilities;
|
|
66
112
|
destroy(): void;
|
|
@@ -13,7 +13,6 @@ import { CompactSplatData } from "./PLYLoaderMobile";
|
|
|
13
13
|
import type { BoundingBox, Vec3Tuple } from "../types";
|
|
14
14
|
import { SHMode, RendererCapabilities } from "../types";
|
|
15
15
|
import type { IGSSplatRendererWithCapabilities } from "./IGSSplatRenderer";
|
|
16
|
-
export type { BoundingBox };
|
|
17
16
|
/**
|
|
18
17
|
* GSSplatRendererMobile - 移动端优化渲染器
|
|
19
18
|
* 实现 IGSSplatRenderer 接口
|
|
@@ -32,6 +31,7 @@ export declare class GSSplatRendererMobile implements IGSSplatRendererWithCapabi
|
|
|
32
31
|
private sorter;
|
|
33
32
|
private positionsBuffer;
|
|
34
33
|
private boundingBox;
|
|
34
|
+
private cpuPositions;
|
|
35
35
|
private frameCount;
|
|
36
36
|
private sortEveryNFrames;
|
|
37
37
|
private position;
|
|
@@ -117,6 +117,7 @@ export declare class GSSplatRendererMobile implements IGSSplatRendererWithCapabi
|
|
|
117
117
|
* 获取 bounding box
|
|
118
118
|
*/
|
|
119
119
|
getBoundingBox(): BoundingBox | null;
|
|
120
|
+
getCPUPositions(): Float32Array | null;
|
|
120
121
|
/**
|
|
121
122
|
* 设置排序频率
|
|
122
123
|
* @param n 每 n 帧排序一次
|
|
@@ -23,6 +23,8 @@ export interface CullingOptions {
|
|
|
23
23
|
farPlane: number;
|
|
24
24
|
pixelThreshold: number;
|
|
25
25
|
frustumDilation?: number;
|
|
26
|
+
/** 最大可见 splat 数量(排序后截断),0 = 不限制 */
|
|
27
|
+
maxVisibleCount?: number;
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
28
30
|
* 排序器配置选项
|
|
@@ -50,6 +52,7 @@ export declare class GSSplatSorter {
|
|
|
50
52
|
private sortedIndicesBuffer;
|
|
51
53
|
private initIndirectPipeline;
|
|
52
54
|
private projectCullPipeline;
|
|
55
|
+
private clampDrawCountPipeline;
|
|
53
56
|
private cullingBindGroupLayout;
|
|
54
57
|
private cullingBindGroup;
|
|
55
58
|
private upsweepPipeline;
|
|
@@ -7,8 +7,6 @@ import type { CompactSplatData } from "./PLYLoaderMobile";
|
|
|
7
7
|
import type { SplatCPU } from "./PLYLoader";
|
|
8
8
|
import type { BoundingBox, Vec3Tuple } from "../types";
|
|
9
9
|
import { SHMode, RendererCapabilities } from "../types";
|
|
10
|
-
export type { BoundingBox, Vec3Tuple, RendererCapabilities };
|
|
11
|
-
export { SHMode };
|
|
12
10
|
/**
|
|
13
11
|
* 3D Gaussian Splatting 渲染器接口
|
|
14
12
|
*/
|
|
@@ -70,6 +68,11 @@ export interface IGSSplatRenderer {
|
|
|
70
68
|
* 获取 bounding box
|
|
71
69
|
*/
|
|
72
70
|
getBoundingBox(): BoundingBox | null;
|
|
71
|
+
/**
|
|
72
|
+
* 获取 CPU 端 splat 位置数据(用于射线拾取等交互)
|
|
73
|
+
* 返回 Float32Array,每 3 个值为一个点的 x, y, z
|
|
74
|
+
*/
|
|
75
|
+
getCPUPositions(): Float32Array | null;
|
|
73
76
|
/**
|
|
74
77
|
* 设置 SH 模式
|
|
75
78
|
* 移动端可能只支持 L0
|
|
@@ -83,6 +86,32 @@ export interface IGSSplatRenderer {
|
|
|
83
86
|
* 是否支持指定的 SH 模式
|
|
84
87
|
*/
|
|
85
88
|
supportsSHMode?(mode: SHMode): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* 设置排序频率
|
|
91
|
+
* 1 = 每帧排序(默认),N = 每 N 帧排序一次
|
|
92
|
+
* 降低排序频率可显著提升中距离场景的帧率,代价是移动时短暂的排序瑕疵
|
|
93
|
+
*/
|
|
94
|
+
setSortFrequency?(frequency: number): void;
|
|
95
|
+
/**
|
|
96
|
+
* 获取排序频率
|
|
97
|
+
*/
|
|
98
|
+
getSortFrequency?(): number;
|
|
99
|
+
/**
|
|
100
|
+
* 渲染深度+法线到 offscreen RT,并将指定像素 copy 到 staging buffer 发起异步回读。
|
|
101
|
+
* 在主 render 之后每帧调用,复用排序结果。
|
|
102
|
+
* @param px 像素 x 坐标(-1 表示不回读)
|
|
103
|
+
* @param py 像素 y 坐标(-1 表示不回读)
|
|
104
|
+
*/
|
|
105
|
+
prepareDepthNormalPass?(px: number, py: number): void;
|
|
106
|
+
/**
|
|
107
|
+
* 同步读取上一帧 prepareDepthNormalPass 回读完成的结果。
|
|
108
|
+
* @returns null 表示上一帧无命中、回读未完成、或未请求过回读
|
|
109
|
+
*/
|
|
110
|
+
getDepthNormal?(): {
|
|
111
|
+
depth: number;
|
|
112
|
+
normal: Vec3Tuple;
|
|
113
|
+
worldPos: Vec3Tuple;
|
|
114
|
+
} | null;
|
|
86
115
|
/**
|
|
87
116
|
* 销毁资源
|
|
88
117
|
*/
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SOGLoader - 加载 SOG (Spatially Ordered Gaussians) 格式的 3DGS 文件
|
|
3
|
+
*
|
|
4
|
+
* SOG 是 PlayCanvas 开源的压缩容器格式,约 15-20x 压缩比 (vs PLY)
|
|
5
|
+
* .sog 文件本质是 ZIP 包,内含 meta.json + 多个无损 WebP 图像
|
|
6
|
+
*
|
|
7
|
+
* 支持:
|
|
8
|
+
* - 完整位置解码(16-bit 对称对数量化)
|
|
9
|
+
* - Codebook 缩放解码
|
|
10
|
+
* - Smallest-three 四元数解码 (26-bit)
|
|
11
|
+
* - DC 颜色 + 透明度 (SH L0)
|
|
12
|
+
* - 高阶球谐系数 L1-L3(palette + codebook)
|
|
13
|
+
*
|
|
14
|
+
* 规范 v2: https://developer.playcanvas.com/user-manual/gaussian-splatting/formats/sog/
|
|
15
|
+
*/
|
|
16
|
+
import type { CompactSplatData } from './PLYLoaderMobile';
|
|
17
|
+
export type SOGProgressCallback = (progress: number, stage: 'download' | 'parse' | 'upload') => void;
|
|
18
|
+
/**
|
|
19
|
+
* 从 URL 加载 .sog 文件
|
|
20
|
+
*/
|
|
21
|
+
export declare function loadSOG(url: string, onProgress?: SOGProgressCallback): Promise<CompactSplatData>;
|
|
22
|
+
/**
|
|
23
|
+
* 从 ArrayBuffer 解析 SOG 数据
|
|
24
|
+
*/
|
|
25
|
+
export declare function deserializeSOG(data: ArrayBuffer, onProgress?: SOGProgressCallback): Promise<CompactSplatData>;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,11 +8,9 @@ export { isMobileDevice, getRecommendedDPR, isWebGPUSupported, computeBoundingBo
|
|
|
8
8
|
export { Renderer } from './core/Renderer';
|
|
9
9
|
export { Camera } from './core/Camera';
|
|
10
10
|
export { OrbitControls } from './core/OrbitControls';
|
|
11
|
-
export { ViewportGizmo } from './core/ViewportGizmo';
|
|
11
|
+
export { ViewportGizmo } from './core/gizmo/ViewportGizmo';
|
|
12
12
|
export { BoundingBoxRenderer } from './core/BoundingBoxRenderer';
|
|
13
|
-
export type { BoundingBox as SelectionBoundingBox, BoundingBoxProvider } from './core/BoundingBoxRenderer';
|
|
14
13
|
export { Mesh } from './mesh/Mesh';
|
|
15
|
-
export type { MeshBoundingBox } from './mesh/Mesh';
|
|
16
14
|
export { MeshRenderer } from './mesh/MeshRenderer';
|
|
17
15
|
export { GLBLoader } from './loaders/GLBLoader';
|
|
18
16
|
export type { LoadedMesh } from './loaders/GLBLoader';
|
|
@@ -27,8 +25,9 @@ export type { SplatCPU } from './gs/PLYLoader';
|
|
|
27
25
|
export { loadPLYMobile, parsePLYBuffer, compactDataToGPUBuffer } from './gs/PLYLoaderMobile';
|
|
28
26
|
export type { MobileLoadOptions, CompactSplatData } from './gs/PLYLoaderMobile';
|
|
29
27
|
export { loadSplat, deserializeSplat } from './gs/SplatLoader';
|
|
30
|
-
export {
|
|
31
|
-
export type {
|
|
28
|
+
export { loadSOG, deserializeSOG } from './gs/SOGLoader';
|
|
29
|
+
export type { SOGProgressCallback } from './gs/SOGLoader';
|
|
30
|
+
export { GSSplatRenderer } from './gs/GSSplatRenderer';
|
|
32
31
|
export { GSSplatSorter } from './gs/GSSplatSorter';
|
|
33
32
|
export type { SorterOptions, CullingOptions, ScreenInfo } from './gs/GSSplatSorter';
|
|
34
33
|
export { GSSplatRendererMobile } from './gs/GSSplatRendererMobile';
|
|
@@ -39,9 +38,11 @@ export type { CompressedSplatTextures } from './gs/TextureCompressor';
|
|
|
39
38
|
export { SceneManager } from './scene/SceneManager';
|
|
40
39
|
export type { SceneObjectType, SceneObjectInfo } from './scene/SceneManager';
|
|
41
40
|
export { SplatTransformProxy, MeshGroupProxy, SplatBoundingBoxProvider, } from './scene/proxies';
|
|
42
|
-
export { GizmoManager
|
|
41
|
+
export { GizmoManager } from './interaction/GizmoManager';
|
|
42
|
+
export { HotspotManager } from './interaction/HotspotManager';
|
|
43
|
+
export type { HotspotInfo } from './interaction/HotspotManager';
|
|
44
|
+
export type { TransformableObject } from './core/gizmo/TransformGizmo';
|
|
45
|
+
export { TransformGizmo, GizmoMode } from './core/gizmo/TransformGizmo';
|
|
46
|
+
export type { GizmoTheme, TransformGizmoConfig, GizmoSpace } from './core/gizmo/TransformGizmo';
|
|
43
47
|
export { App } from './App';
|
|
44
48
|
export type { ProgressCallback } from './App';
|
|
45
|
-
export type { TransformableObject } from './core/gizmo/TransformGizmoV2';
|
|
46
|
-
export { TransformGizmoV2, GizmoMode } from './core/gizmo/TransformGizmoV2';
|
|
47
|
-
export type { GizmoTheme, TransformGizmoConfig, GizmoSpace } from './core/gizmo/TransformGizmoV2';
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
import { Renderer } from "../core/Renderer";
|
|
10
10
|
import { Camera } from "../core/Camera";
|
|
11
11
|
import { OrbitControls } from "../core/OrbitControls";
|
|
12
|
-
import { ViewportGizmo } from "../core/ViewportGizmo";
|
|
13
|
-
import {
|
|
14
|
-
import { BoundingBoxRenderer
|
|
12
|
+
import { ViewportGizmo } from "../core/gizmo/ViewportGizmo";
|
|
13
|
+
import { TransformGizmo, TransformableObject, GizmoMode } from "../core/gizmo/TransformGizmo";
|
|
14
|
+
import { BoundingBoxRenderer } from "../core/BoundingBoxRenderer";
|
|
15
|
+
import type { SimpleBoundingBox, BoundingBoxProvider } from "../types";
|
|
15
16
|
import type { IGSSplatRenderer } from "../gs/IGSSplatRenderer";
|
|
16
17
|
import type { Mesh } from "../mesh/Mesh";
|
|
17
18
|
import { SplatTransformProxy, MeshGroupProxy, SplatBoundingBoxProvider } from "../scene/proxies";
|
|
18
|
-
export { SplatTransformProxy, MeshGroupProxy, SplatBoundingBoxProvider };
|
|
19
19
|
/**
|
|
20
20
|
* GizmoManager - Gizmo 交互管理器
|
|
21
21
|
*/
|
|
@@ -47,7 +47,7 @@ export declare class GizmoManager {
|
|
|
47
47
|
/**
|
|
48
48
|
* 获取变换 Gizmo
|
|
49
49
|
*/
|
|
50
|
-
getTransformGizmo():
|
|
50
|
+
getTransformGizmo(): TransformGizmo;
|
|
51
51
|
/**
|
|
52
52
|
* 设置 Gizmo 模式
|
|
53
53
|
*/
|
|
@@ -67,7 +67,7 @@ export declare class GizmoManager {
|
|
|
67
67
|
/**
|
|
68
68
|
* 设置选中对象的包围盒(静态模式)
|
|
69
69
|
*/
|
|
70
|
-
setSelectionBoundingBox(box:
|
|
70
|
+
setSelectionBoundingBox(box: SimpleBoundingBox | null): void;
|
|
71
71
|
/**
|
|
72
72
|
* 设置选中对象的包围盒提供者(动态模式)
|
|
73
73
|
*/
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HotspotManager - 热点放置管理器
|
|
3
|
+
*
|
|
4
|
+
* 在 3DGS 场景中通过射线拾取表面点,计算法线,
|
|
5
|
+
* 显示吸附圆圈指示器,并放置 OBJ 模型热点。
|
|
6
|
+
*/
|
|
7
|
+
import { Camera } from "../core/Camera";
|
|
8
|
+
import { Renderer } from "../core/Renderer";
|
|
9
|
+
import { OrbitControls } from "../core/OrbitControls";
|
|
10
|
+
import { MeshRenderer } from "../mesh/MeshRenderer";
|
|
11
|
+
import type { IGSSplatRenderer } from "../gs/IGSSplatRenderer";
|
|
12
|
+
import type { Vec3Tuple } from "../types";
|
|
13
|
+
/** 热点信息 */
|
|
14
|
+
export interface HotspotInfo {
|
|
15
|
+
position: Vec3Tuple;
|
|
16
|
+
normal: Vec3Tuple;
|
|
17
|
+
meshStartIndex: number;
|
|
18
|
+
meshCount: number;
|
|
19
|
+
/** 是否始终面向屏幕(billboard 模式),默认 false */
|
|
20
|
+
billboard: boolean;
|
|
21
|
+
/** 放置时的缩放值(billboard 旋转时需要保持) */
|
|
22
|
+
placedScale: number;
|
|
23
|
+
/** 放置时的法线偏移量 */
|
|
24
|
+
placedNormalOffset: number;
|
|
25
|
+
/** 放置时的本地中心偏移 (本地空间) */
|
|
26
|
+
placedLocalCenter: Vec3Tuple;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* HotspotManager
|
|
30
|
+
*/
|
|
31
|
+
export declare class HotspotManager {
|
|
32
|
+
private camera;
|
|
33
|
+
private renderer;
|
|
34
|
+
private controls;
|
|
35
|
+
private meshRenderer;
|
|
36
|
+
private objLoader;
|
|
37
|
+
private canvas;
|
|
38
|
+
private active;
|
|
39
|
+
private gsRenderer;
|
|
40
|
+
private indicatorMesh;
|
|
41
|
+
private indicatorAdded;
|
|
42
|
+
private hotspots;
|
|
43
|
+
private currentHit;
|
|
44
|
+
private indicatorTransform;
|
|
45
|
+
private hotspotOBJUrl;
|
|
46
|
+
private boundOnMouseMove;
|
|
47
|
+
private boundOnMouseDown;
|
|
48
|
+
private boundOnMouseUp;
|
|
49
|
+
private boundOnKeyDown;
|
|
50
|
+
private mouseDownPos;
|
|
51
|
+
private isDragging;
|
|
52
|
+
private readonly DRAG_THRESHOLD;
|
|
53
|
+
private pendingMouseX;
|
|
54
|
+
private pendingMouseY;
|
|
55
|
+
private hasPendingMove;
|
|
56
|
+
private rafId;
|
|
57
|
+
private lastHitIdx;
|
|
58
|
+
private lastNormal;
|
|
59
|
+
private indicatorBaseRadius;
|
|
60
|
+
private pickRadiusPx;
|
|
61
|
+
private onHotspotPlaced;
|
|
62
|
+
private onModeChanged;
|
|
63
|
+
constructor(renderer: Renderer, camera: Camera, canvas: HTMLCanvasElement, controls: OrbitControls, meshRenderer: MeshRenderer);
|
|
64
|
+
setGSRenderer(gsRenderer: IGSSplatRenderer | null): void;
|
|
65
|
+
setHotspotOBJUrl(url: string): void;
|
|
66
|
+
enter(): void;
|
|
67
|
+
exit(): void;
|
|
68
|
+
isActive(): boolean;
|
|
69
|
+
getHotspots(): HotspotInfo[];
|
|
70
|
+
setOnHotspotPlaced(cb: ((info: HotspotInfo) => void) | null): void;
|
|
71
|
+
setOnModeChanged(cb: ((active: boolean) => void) | null): void;
|
|
72
|
+
private pickPixelX;
|
|
73
|
+
private pickPixelY;
|
|
74
|
+
private lastClientX;
|
|
75
|
+
private lastClientY;
|
|
76
|
+
private pickDirty;
|
|
77
|
+
/**
|
|
78
|
+
* Returns the current pick pixel coordinates in device pixels.
|
|
79
|
+
* Called by the render loop to pass to prepareDepthNormalPass.
|
|
80
|
+
* Returns [-1, -1] when no pick is needed.
|
|
81
|
+
*/
|
|
82
|
+
getPickPixel(): [number, number];
|
|
83
|
+
private onMouseMove;
|
|
84
|
+
private processMouseMove;
|
|
85
|
+
/**
|
|
86
|
+
* 读取上一帧的深度法线GPU回读结果,更新指示器
|
|
87
|
+
* 每帧在App.Render()中调用
|
|
88
|
+
* 如果GPU没有回读结果,则使用CPU拾取
|
|
89
|
+
*/
|
|
90
|
+
consumeGPUResult(): void;
|
|
91
|
+
private onMouseDown;
|
|
92
|
+
private onMouseUp;
|
|
93
|
+
private onKeyDown;
|
|
94
|
+
private raycastSplatsCPU;
|
|
95
|
+
private estimateNormal;
|
|
96
|
+
/**
|
|
97
|
+
* 距离加权 PCA:离中心越近的点权重越高
|
|
98
|
+
*/
|
|
99
|
+
private weightedPCA;
|
|
100
|
+
/**
|
|
101
|
+
* 求 3x3 对称矩阵最小特征值对应的特征向量(偏移幂迭代)
|
|
102
|
+
*/
|
|
103
|
+
private smallestEigenvector;
|
|
104
|
+
private createIndicatorMesh;
|
|
105
|
+
private showIndicator;
|
|
106
|
+
private hideIndicator;
|
|
107
|
+
private updateIndicator;
|
|
108
|
+
private placeHotspot;
|
|
109
|
+
/**
|
|
110
|
+
* 将 OBJ mesh 的变换设置为与指示器完全一致的大小、位置、朝向。
|
|
111
|
+
*
|
|
112
|
+
* 使用指示器缓存的基向量 (right, forward, normal) 和 visualDiameter,
|
|
113
|
+
* 将 OBJ 缩放到与指示器圆圈等大,居中放置在相同位置。
|
|
114
|
+
*/
|
|
115
|
+
private applyIndicatorTransform;
|
|
116
|
+
/**
|
|
117
|
+
* 从 modelMatrix 反向提取 position / rotation / scale,
|
|
118
|
+
* 使 Mesh 的分离属性与矩阵保持同步(Gizmo 需要)。
|
|
119
|
+
*/
|
|
120
|
+
private decomposeModelMatrix;
|
|
121
|
+
/**
|
|
122
|
+
* 设置指定热点的 billboard 模式
|
|
123
|
+
* @param hotspotIndex 热点索引(在 hotspots 数组中的位置)
|
|
124
|
+
* @param enabled 是否启用 billboard
|
|
125
|
+
*/
|
|
126
|
+
setHotspotBillboard(hotspotIndex: number, enabled: boolean): boolean;
|
|
127
|
+
getHotspotBillboard(hotspotIndex: number): boolean;
|
|
128
|
+
getHotspotCount(): number;
|
|
129
|
+
/**
|
|
130
|
+
* 通过 overlay mesh 起始索引找到对应的热点索引
|
|
131
|
+
*/
|
|
132
|
+
findHotspotIndexByMeshStart(overlayMeshStartIndex: number): number;
|
|
133
|
+
/**
|
|
134
|
+
* 每帧调用:更新所有 billboard 热点朝向相机
|
|
135
|
+
*/
|
|
136
|
+
updateBillboards(): void;
|
|
137
|
+
/**
|
|
138
|
+
* 关闭 billboard 时恢复到放置时的法线朝向
|
|
139
|
+
*/
|
|
140
|
+
private restoreHotspotOrientation;
|
|
141
|
+
destroy(): void;
|
|
142
|
+
}
|