@threepipe/plugin-gaussian-splatting 0.1.0
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/assets/worker-dK7pvmNj.js +1569 -0
- package/dist/assets/worker-dK7pvmNj.js.map +1 -0
- package/dist/dependencies.txt +212 -0
- package/dist/gaussian-splats-3d/GaussianSplatsPlugin.d.ts +1 -0
- package/dist/gaussian-splats-3d/GaussianSplatsPlugin.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +879 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +876 -0
- package/dist/index.mjs.map +1 -0
- package/dist/three-gaussian-splat/ThreeGaussianSplatPlugin.d.ts +45 -0
- package/dist/three-gaussian-splat/ThreeGaussianSplatPlugin.d.ts.map +1 -0
- package/dist/three-gaussian-splat/cpp-sorter/BufferPool.d.ts +9 -0
- package/dist/three-gaussian-splat/cpp-sorter/BufferPool.d.ts.map +1 -0
- package/dist/three-gaussian-splat/cpp-sorter/SortWorkerManager.d.ts +13 -0
- package/dist/three-gaussian-splat/cpp-sorter/SortWorkerManager.d.ts.map +1 -0
- package/dist/three-gaussian-splat/cpp-sorter/worker.d.ts +18 -0
- package/dist/three-gaussian-splat/cpp-sorter/worker.d.ts.map +1 -0
- package/dist/three-gaussian-splat/geometry/GaussianSplatGeometry.d.ts +25 -0
- package/dist/three-gaussian-splat/geometry/GaussianSplatGeometry.d.ts.map +1 -0
- package/dist/three-gaussian-splat/index.d.ts +22 -0
- package/dist/three-gaussian-splat/index.d.ts.map +1 -0
- package/dist/three-gaussian-splat/loaders/SplatLoader.d.ts +13 -0
- package/dist/three-gaussian-splat/loaders/SplatLoader.d.ts.map +1 -0
- package/dist/three-gaussian-splat/materials/GaussianSplatMaterialExtension.d.ts +28 -0
- package/dist/three-gaussian-splat/materials/GaussianSplatMaterialExtension.d.ts.map +1 -0
- package/dist/three-gaussian-splat/materials/GaussianSplatMaterialPhysical.d.ts +9 -0
- package/dist/three-gaussian-splat/materials/GaussianSplatMaterialPhysical.d.ts.map +1 -0
- package/dist/three-gaussian-splat/materials/GaussianSplatMaterialRaw.d.ts +12 -0
- package/dist/three-gaussian-splat/materials/GaussianSplatMaterialRaw.d.ts.map +1 -0
- package/dist/three-gaussian-splat/materials/GaussianSplatMaterialUnlit.d.ts +9 -0
- package/dist/three-gaussian-splat/materials/GaussianSplatMaterialUnlit.d.ts.map +1 -0
- package/dist/three-gaussian-splat/materials/util.d.ts +3 -0
- package/dist/three-gaussian-splat/materials/util.d.ts.map +1 -0
- package/dist/three-gaussian-splat/mesh/GaussianSplatMesh.d.ts +10 -0
- package/dist/three-gaussian-splat/mesh/GaussianSplatMesh.d.ts.map +1 -0
- package/dist/three-gaussian-splat/shaders/index.d.ts +7 -0
- package/dist/three-gaussian-splat/shaders/index.d.ts.map +1 -0
- package/package.json +34 -0
- package/src/gaussian-splats-3d/GaussianSplatsPlugin.ts +50 -0
- package/src/global.d.ts +40 -0
- package/src/index.ts +5 -0
- package/src/three-gaussian-splat/ThreeGaussianSplatPlugin.css +3 -0
- package/src/three-gaussian-splat/ThreeGaussianSplatPlugin.ts +74 -0
- package/src/three-gaussian-splat/cpp-sorter/BufferPool.ts +30 -0
- package/src/three-gaussian-splat/cpp-sorter/ISort.d.ts +3 -0
- package/src/three-gaussian-splat/cpp-sorter/SortWorkerManager.ts +53 -0
- package/src/three-gaussian-splat/cpp-sorter/build-in-docker.sh +4 -0
- package/src/three-gaussian-splat/cpp-sorter/build.sh +7 -0
- package/src/three-gaussian-splat/cpp-sorter/sort.cpp +107 -0
- package/src/three-gaussian-splat/cpp-sorter/sort.js +16 -0
- package/src/three-gaussian-splat/cpp-sorter/sort.wasm +0 -0
- package/src/three-gaussian-splat/cpp-sorter/watch.sh +9 -0
- package/src/three-gaussian-splat/cpp-sorter/worker.ts +59 -0
- package/src/three-gaussian-splat/geometry/GaussianSplatGeometry.ts +182 -0
- package/src/three-gaussian-splat/index.ts +22 -0
- package/src/three-gaussian-splat/loaders/SplatLoader.ts +51 -0
- package/src/three-gaussian-splat/materials/GaussianSplatMaterialExtension.ts +105 -0
- package/src/three-gaussian-splat/materials/GaussianSplatMaterialPhysical.ts +25 -0
- package/src/three-gaussian-splat/materials/GaussianSplatMaterialRaw.ts +73 -0
- package/src/three-gaussian-splat/materials/GaussianSplatMaterialUnlit.ts +26 -0
- package/src/three-gaussian-splat/materials/util.ts +9 -0
- package/src/three-gaussian-splat/mesh/GaussianSplatMesh.ts +96 -0
- package/src/three-gaussian-splat/shaders/gsplat.main.frag.glsl +18 -0
- package/src/three-gaussian-splat/shaders/gsplat.main.vert.glsl +15 -0
- package/src/three-gaussian-splat/shaders/gsplat.pars.frag.glsl +10 -0
- package/src/three-gaussian-splat/shaders/gsplat.pars.vert.glsl +58 -0
- package/src/three-gaussian-splat/shaders/index.ts +11 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,879 @@
|
|
|
1
|
+
(function(global, factory) {
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("threepipe"), require("three")) : typeof define === "function" && define.amd ? define(["exports", "threepipe", "three"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global["@threepipe/plugin-gaussian-splatting"] = {}, global.threepipe, global.threepipe));
|
|
3
|
+
})(this, function(exports2, threepipe, three) {
|
|
4
|
+
"use strict";/**
|
|
5
|
+
* @license
|
|
6
|
+
* @threepipe/plugin-gaussian-splatting v0.1.0
|
|
7
|
+
* Copyright 2022-2024 repalash <palash@shaders.app>
|
|
8
|
+
* Apache-2.0 License
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
|
|
12
|
+
const computeFocalLengths = (width, height, fov, aspect, dpr) => {
|
|
13
|
+
const fovRad = threepipe.MathUtils.degToRad(fov);
|
|
14
|
+
const fovXRad = 2 * Math.atan(Math.tan(fovRad / 2) * aspect);
|
|
15
|
+
const fy = dpr * height / (2 * Math.tan(fovRad / 2));
|
|
16
|
+
const fx = dpr * width / (2 * Math.tan(fovXRad / 2));
|
|
17
|
+
return new threepipe.Vector2(fx, fy);
|
|
18
|
+
};
|
|
19
|
+
const fragmentParsShaderSource = "precision mediump float;varying vec4 vColor;varying vec3 vConic;varying vec2 vCenter;uniform vec2 viewport;uniform vec2 focal;uniform float minAlpha;";
|
|
20
|
+
const vertexParsShaderSource = "precision mediump float;\n#ifndef SHADER_NAME\nattribute vec3 position;uniform mat4 modelViewMatrix;uniform mat4 projectionMatrix;mat3 transpose(mat3 m){return mat3(m[0][0],m[1][0],m[2][0],m[0][1],m[1][1],m[2][1],m[0][2],m[1][2],m[2][2]);}\n#endif\nattribute vec4 color;attribute vec4 quat;attribute vec3 scale;attribute vec3 center;uniform vec2 focal;uniform vec2 viewport;varying vec4 vColor;varying vec3 vConic;varying vec2 vCenter;varying vec2 vPosition;mat3 compute_cov3d(vec3 scale,vec4 rot){mat3 S=mat3(scale.x,0.0,0.0,0.0,scale.y,0.0,0.0,0.0,scale.z);mat3 R=mat3(1.0-2.0*(rot.z*rot.z+rot.w*rot.w),2.0*(rot.y*rot.z-rot.x*rot.w),2.0*(rot.y*rot.w+rot.x*rot.z),2.0*(rot.y*rot.z+rot.x*rot.w),1.0-2.0*(rot.y*rot.y+rot.w*rot.w),2.0*(rot.z*rot.w-rot.x*rot.y),2.0*(rot.y*rot.w-rot.x*rot.z),2.0*(rot.z*rot.w+rot.x*rot.y),1.0-2.0*(rot.y*rot.y+rot.z*rot.z));mat3 M=S*R;return transpose(M)*M;}vec3 compute_cov2d(vec3 center,vec3 scale,vec4 rot){mat3 Vrk=compute_cov3d(scale,rot);vec4 t=modelViewMatrix*vec4(center,1.0);vec2 lims=1.3*0.5*viewport/focal;t.xy=min(lims,max(-lims,t.xy/t.z))*t.z;mat3 J=mat3(focal.x/t.z,0.,-(focal.x*t.x)/(t.z*t.z),0.,focal.y/t.z,-(focal.y*t.y)/(t.z*t.z),0.,0.,0.);mat3 W=transpose(mat3(modelViewMatrix));mat3 T=W*J;mat3 cov=transpose(T)*transpose(Vrk)*T;return vec3(cov[0][0]+0.3,cov[0][1],cov[1][1]+0.3);}";
|
|
21
|
+
const vertexShaderSource = "vec3 cov2d=compute_cov2d(center,scale,quat);float det=cov2d.x*cov2d.z-cov2d.y*cov2d.y;vec3 conic=vec3(cov2d.z,cov2d.y,cov2d.x)/det;float mid=0.5*(cov2d.x+cov2d.z);float lambda1=mid+sqrt(max(0.1,mid*mid-det));float lambda2=mid-sqrt(max(0.1,mid*mid-det));vec2 v1=7.0*sqrt(lambda1)*normalize(vec2(cov2d.y,lambda1-cov2d.x));vec2 v2=7.0*sqrt(lambda2)*normalize(vec2(-(lambda1-cov2d.x),cov2d.y));vColor=color;vConic=conic;vCenter=vec2(gl_Position)/gl_Position.w;vPosition=vec2(vCenter+position.x*(position.y<0.0 ? v1 : v2)/viewport);gl_Position=vec4(vPosition,gl_Position.z/gl_Position.w,1);";
|
|
22
|
+
const fragmentShaderSource = "vec2 d=(vCenter-2.0*(gl_FragCoord.xy/viewport-vec2(0.5,0.5)))*viewport*0.5;float power=-0.5*(vConic.x*d.x*d.x+vConic.z*d.y*d.y)+vConic.y*d.x*d.y;if(power>0.0)discard;float alpha=min(0.99,vColor.a*exp(power));if(alpha<minAlpha)discard;gl_FragColor=vec4(vColor.rgb,alpha);";
|
|
23
|
+
const gaussianSplatShaders = {
|
|
24
|
+
main_frag: "\n" + fragmentShaderSource + "\n",
|
|
25
|
+
main_vert: "\n" + vertexShaderSource + "\n",
|
|
26
|
+
pars_frag: fragmentParsShaderSource,
|
|
27
|
+
pars_vert: vertexParsShaderSource
|
|
28
|
+
};
|
|
29
|
+
class GaussianSplatMaterialExtension {
|
|
30
|
+
constructor() {
|
|
31
|
+
this.isGaussianSplatMaterialExtension = true;
|
|
32
|
+
this.extraUniforms = {
|
|
33
|
+
viewport: { value: new threepipe.Vector2() },
|
|
34
|
+
focal: { value: new threepipe.Vector2() },
|
|
35
|
+
minAlpha: { value: 0.02 }
|
|
36
|
+
};
|
|
37
|
+
this.parsFragmentSnippet = gaussianSplatShaders.pars_frag;
|
|
38
|
+
this.parsVertexSnippet = gaussianSplatShaders.pars_vert;
|
|
39
|
+
this.shaderExtender = (shader, material) => {
|
|
40
|
+
shader.vertexShader = threepipe.shaderReplaceString(
|
|
41
|
+
shader.vertexShader,
|
|
42
|
+
"#include <begin_vertex>",
|
|
43
|
+
"vec3 transformed = vec3( center );"
|
|
44
|
+
);
|
|
45
|
+
if (shader.vertexShader.includes("#include <beginnormal_vertex>")) {
|
|
46
|
+
shader.vertexShader = threepipe.shaderReplaceString(
|
|
47
|
+
shader.vertexShader,
|
|
48
|
+
"#include <beginnormal_vertex>",
|
|
49
|
+
"\nobjectNormal = vec3(1,0,0);\n",
|
|
50
|
+
{ append: true }
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
shader.vertexShader = threepipe.shaderReplaceString(
|
|
54
|
+
shader.vertexShader,
|
|
55
|
+
"#include <project_vertex>",
|
|
56
|
+
gaussianSplatShaders.main_vert,
|
|
57
|
+
{ append: true }
|
|
58
|
+
);
|
|
59
|
+
if (!material.isGBufferMaterial && !material.userData.isGBufferMaterial) {
|
|
60
|
+
shader.fragmentShader = threepipe.shaderReplaceString(
|
|
61
|
+
shader.fragmentShader,
|
|
62
|
+
"#include <map_fragment>",
|
|
63
|
+
threepipe.shaderReplaceString(
|
|
64
|
+
gaussianSplatShaders.main_frag,
|
|
65
|
+
/gl_FragColor\s*=/,
|
|
66
|
+
// because of minification
|
|
67
|
+
"diffuseColor*="
|
|
68
|
+
),
|
|
69
|
+
{ prepend: true }
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return shader;
|
|
73
|
+
};
|
|
74
|
+
this.isCompatible = (material) => !!material.isPhysicalMaterial || !!material.isUnlitMaterial || !!material.isGBufferMaterial || !!material.userData.isGBufferMaterial;
|
|
75
|
+
this._refresh = () => {
|
|
76
|
+
var _a, _b;
|
|
77
|
+
if (!this._currentCamera)
|
|
78
|
+
return;
|
|
79
|
+
const size = new threepipe.Vector2();
|
|
80
|
+
(_a = this._renderer) == null ? void 0 : _a.getSize(size);
|
|
81
|
+
const dpr = ((_b = this._renderer) == null ? void 0 : _b.getPixelRatio()) || 1;
|
|
82
|
+
let fov = 75;
|
|
83
|
+
let aspect = size.x / size.y;
|
|
84
|
+
if (this._currentCamera instanceof threepipe.PerspectiveCamera) {
|
|
85
|
+
fov = this._currentCamera.fov;
|
|
86
|
+
aspect = this._currentCamera.aspect;
|
|
87
|
+
}
|
|
88
|
+
this.extraUniforms.focal.value = computeFocalLengths(size.x, size.y, fov, aspect, dpr);
|
|
89
|
+
this.extraUniforms.viewport.value = new threepipe.Vector2(size.x * dpr, size.y * dpr);
|
|
90
|
+
};
|
|
91
|
+
window.addEventListener("resize", this._refresh);
|
|
92
|
+
}
|
|
93
|
+
set minAlpha(value) {
|
|
94
|
+
this.extraUniforms.minAlpha.value = value;
|
|
95
|
+
this.setDirty && this.setDirty();
|
|
96
|
+
}
|
|
97
|
+
dispose() {
|
|
98
|
+
window.removeEventListener("resize", this._refresh);
|
|
99
|
+
}
|
|
100
|
+
update(camera, renderer) {
|
|
101
|
+
if (this._currentCamera === camera && this._renderer === renderer)
|
|
102
|
+
return;
|
|
103
|
+
this._renderer = renderer;
|
|
104
|
+
this._currentCamera = camera;
|
|
105
|
+
this._refresh();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
class GaussianSplatMaterialPhysical extends threepipe.PhysicalMaterial {
|
|
109
|
+
constructor() {
|
|
110
|
+
super({
|
|
111
|
+
depthTest: true,
|
|
112
|
+
depthWrite: false,
|
|
113
|
+
transparent: true,
|
|
114
|
+
vertexColors: false
|
|
115
|
+
});
|
|
116
|
+
this.isGaussianSplatMaterialPhysical = true;
|
|
117
|
+
this.gsplatExtension = new GaussianSplatMaterialExtension();
|
|
118
|
+
this.registerMaterialExtensions([this.gsplatExtension]);
|
|
119
|
+
}
|
|
120
|
+
dispose() {
|
|
121
|
+
this.gsplatExtension.dispose();
|
|
122
|
+
return super.dispose();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
class GaussianSplatMaterialRaw extends threepipe.ShaderMaterial2 {
|
|
126
|
+
constructor() {
|
|
127
|
+
super({
|
|
128
|
+
uniforms: {
|
|
129
|
+
viewport: { value: new threepipe.Vector2() },
|
|
130
|
+
focal: { value: new threepipe.Vector2() },
|
|
131
|
+
minAlpha: { value: 0.02 }
|
|
132
|
+
},
|
|
133
|
+
fragmentShader: `${gaussianSplatShaders.pars_frag}
|
|
134
|
+
void main () {
|
|
135
|
+
${gaussianSplatShaders.main_frag}
|
|
136
|
+
}`,
|
|
137
|
+
vertexShader: `${gaussianSplatShaders.pars_vert}
|
|
138
|
+
void main () {
|
|
139
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(center, 1);
|
|
140
|
+
${gaussianSplatShaders.main_vert}
|
|
141
|
+
}`,
|
|
142
|
+
depthTest: true,
|
|
143
|
+
depthWrite: false,
|
|
144
|
+
transparent: true
|
|
145
|
+
}, true);
|
|
146
|
+
this.isGaussianSplatMaterialRaw = true;
|
|
147
|
+
this._refresh = () => {
|
|
148
|
+
var _a, _b;
|
|
149
|
+
if (!this._currentCamera)
|
|
150
|
+
return;
|
|
151
|
+
const size = new threepipe.Vector2();
|
|
152
|
+
(_a = this._renderer) == null ? void 0 : _a.getSize(size);
|
|
153
|
+
const width = size.x;
|
|
154
|
+
const height = size.y;
|
|
155
|
+
const dpr = ((_b = this._renderer) == null ? void 0 : _b.getPixelRatio()) || 1;
|
|
156
|
+
let fov = 75;
|
|
157
|
+
let aspect = width / height;
|
|
158
|
+
if (this._currentCamera instanceof threepipe.PerspectiveCamera) {
|
|
159
|
+
fov = this._currentCamera.fov;
|
|
160
|
+
aspect = this._currentCamera.aspect;
|
|
161
|
+
}
|
|
162
|
+
this.uniforms.focal.value = computeFocalLengths(width, height, fov, aspect, dpr);
|
|
163
|
+
this.uniforms.viewport.value = new threepipe.Vector2(width * dpr, height * dpr);
|
|
164
|
+
};
|
|
165
|
+
window.addEventListener("resize", this._refresh);
|
|
166
|
+
}
|
|
167
|
+
set minAlpha(value) {
|
|
168
|
+
this.uniforms.minAlpha.value = value;
|
|
169
|
+
this.needsUpdate = true;
|
|
170
|
+
}
|
|
171
|
+
dispose() {
|
|
172
|
+
window.removeEventListener("resize", this._refresh);
|
|
173
|
+
return super.dispose();
|
|
174
|
+
}
|
|
175
|
+
update(camera, renderer) {
|
|
176
|
+
this._renderer = renderer;
|
|
177
|
+
this._currentCamera = camera;
|
|
178
|
+
this._refresh();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
class GaussianSplatMaterialUnlit extends threepipe.UnlitMaterial {
|
|
182
|
+
constructor() {
|
|
183
|
+
super({
|
|
184
|
+
depthTest: true,
|
|
185
|
+
depthWrite: false,
|
|
186
|
+
transparent: true,
|
|
187
|
+
vertexColors: false
|
|
188
|
+
});
|
|
189
|
+
this.isGaussianSplatMaterialUnlit = true;
|
|
190
|
+
this.gsplatExtension = new GaussianSplatMaterialExtension();
|
|
191
|
+
this.registerMaterialExtensions([this.gsplatExtension]);
|
|
192
|
+
}
|
|
193
|
+
dispose() {
|
|
194
|
+
this.gsplatExtension.dispose();
|
|
195
|
+
return super.dispose();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* @license
|
|
200
|
+
* Copyright 2019 Google LLC
|
|
201
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
202
|
+
*/
|
|
203
|
+
const proxyMarker = Symbol("Comlink.proxy");
|
|
204
|
+
const createEndpoint = Symbol("Comlink.endpoint");
|
|
205
|
+
const releaseProxy = Symbol("Comlink.releaseProxy");
|
|
206
|
+
const finalizer = Symbol("Comlink.finalizer");
|
|
207
|
+
const throwMarker = Symbol("Comlink.thrown");
|
|
208
|
+
const isObject = (val) => typeof val === "object" && val !== null || typeof val === "function";
|
|
209
|
+
const proxyTransferHandler = {
|
|
210
|
+
canHandle: (val) => isObject(val) && val[proxyMarker],
|
|
211
|
+
serialize(obj) {
|
|
212
|
+
const { port1, port2 } = new MessageChannel();
|
|
213
|
+
expose(obj, port1);
|
|
214
|
+
return [port2, [port2]];
|
|
215
|
+
},
|
|
216
|
+
deserialize(port) {
|
|
217
|
+
port.start();
|
|
218
|
+
return wrap(port);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
const throwTransferHandler = {
|
|
222
|
+
canHandle: (value) => isObject(value) && throwMarker in value,
|
|
223
|
+
serialize({ value }) {
|
|
224
|
+
let serialized;
|
|
225
|
+
if (value instanceof Error) {
|
|
226
|
+
serialized = {
|
|
227
|
+
isError: true,
|
|
228
|
+
value: {
|
|
229
|
+
message: value.message,
|
|
230
|
+
name: value.name,
|
|
231
|
+
stack: value.stack
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
} else {
|
|
235
|
+
serialized = { isError: false, value };
|
|
236
|
+
}
|
|
237
|
+
return [serialized, []];
|
|
238
|
+
},
|
|
239
|
+
deserialize(serialized) {
|
|
240
|
+
if (serialized.isError) {
|
|
241
|
+
throw Object.assign(new Error(serialized.value.message), serialized.value);
|
|
242
|
+
}
|
|
243
|
+
throw serialized.value;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const transferHandlers = /* @__PURE__ */ new Map([
|
|
247
|
+
["proxy", proxyTransferHandler],
|
|
248
|
+
["throw", throwTransferHandler]
|
|
249
|
+
]);
|
|
250
|
+
function isAllowedOrigin(allowedOrigins, origin) {
|
|
251
|
+
for (const allowedOrigin of allowedOrigins) {
|
|
252
|
+
if (origin === allowedOrigin || allowedOrigin === "*") {
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
|
|
262
|
+
ep.addEventListener("message", function callback(ev) {
|
|
263
|
+
if (!ev || !ev.data) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
|
|
267
|
+
console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const { id, type, path } = Object.assign({ path: [] }, ev.data);
|
|
271
|
+
const argumentList = (ev.data.argumentList || []).map(fromWireValue);
|
|
272
|
+
let returnValue;
|
|
273
|
+
try {
|
|
274
|
+
const parent = path.slice(0, -1).reduce((obj2, prop) => obj2[prop], obj);
|
|
275
|
+
const rawValue = path.reduce((obj2, prop) => obj2[prop], obj);
|
|
276
|
+
switch (type) {
|
|
277
|
+
case "GET":
|
|
278
|
+
{
|
|
279
|
+
returnValue = rawValue;
|
|
280
|
+
}
|
|
281
|
+
break;
|
|
282
|
+
case "SET":
|
|
283
|
+
{
|
|
284
|
+
parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
|
|
285
|
+
returnValue = true;
|
|
286
|
+
}
|
|
287
|
+
break;
|
|
288
|
+
case "APPLY":
|
|
289
|
+
{
|
|
290
|
+
returnValue = rawValue.apply(parent, argumentList);
|
|
291
|
+
}
|
|
292
|
+
break;
|
|
293
|
+
case "CONSTRUCT":
|
|
294
|
+
{
|
|
295
|
+
const value = new rawValue(...argumentList);
|
|
296
|
+
returnValue = proxy(value);
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
case "ENDPOINT":
|
|
300
|
+
{
|
|
301
|
+
const { port1, port2 } = new MessageChannel();
|
|
302
|
+
expose(obj, port2);
|
|
303
|
+
returnValue = transfer(port1, [port1]);
|
|
304
|
+
}
|
|
305
|
+
break;
|
|
306
|
+
case "RELEASE":
|
|
307
|
+
{
|
|
308
|
+
returnValue = void 0;
|
|
309
|
+
}
|
|
310
|
+
break;
|
|
311
|
+
default:
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
} catch (value) {
|
|
315
|
+
returnValue = { value, [throwMarker]: 0 };
|
|
316
|
+
}
|
|
317
|
+
Promise.resolve(returnValue).catch((value) => {
|
|
318
|
+
return { value, [throwMarker]: 0 };
|
|
319
|
+
}).then((returnValue2) => {
|
|
320
|
+
const [wireValue, transferables] = toWireValue(returnValue2);
|
|
321
|
+
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
|
|
322
|
+
if (type === "RELEASE") {
|
|
323
|
+
ep.removeEventListener("message", callback);
|
|
324
|
+
closeEndPoint(ep);
|
|
325
|
+
if (finalizer in obj && typeof obj[finalizer] === "function") {
|
|
326
|
+
obj[finalizer]();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}).catch((error) => {
|
|
330
|
+
const [wireValue, transferables] = toWireValue({
|
|
331
|
+
value: new TypeError("Unserializable return value"),
|
|
332
|
+
[throwMarker]: 0
|
|
333
|
+
});
|
|
334
|
+
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
if (ep.start) {
|
|
338
|
+
ep.start();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function isMessagePort(endpoint) {
|
|
342
|
+
return endpoint.constructor.name === "MessagePort";
|
|
343
|
+
}
|
|
344
|
+
function closeEndPoint(endpoint) {
|
|
345
|
+
if (isMessagePort(endpoint))
|
|
346
|
+
endpoint.close();
|
|
347
|
+
}
|
|
348
|
+
function wrap(ep, target) {
|
|
349
|
+
return createProxy(ep, [], target);
|
|
350
|
+
}
|
|
351
|
+
function throwIfProxyReleased(isReleased) {
|
|
352
|
+
if (isReleased) {
|
|
353
|
+
throw new Error("Proxy has been released and is not useable");
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
function releaseEndpoint(ep) {
|
|
357
|
+
return requestResponseMessage(ep, {
|
|
358
|
+
type: "RELEASE"
|
|
359
|
+
}).then(() => {
|
|
360
|
+
closeEndPoint(ep);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
const proxyCounter = /* @__PURE__ */ new WeakMap();
|
|
364
|
+
const proxyFinalizers = "FinalizationRegistry" in globalThis && new FinalizationRegistry((ep) => {
|
|
365
|
+
const newCount = (proxyCounter.get(ep) || 0) - 1;
|
|
366
|
+
proxyCounter.set(ep, newCount);
|
|
367
|
+
if (newCount === 0) {
|
|
368
|
+
releaseEndpoint(ep);
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
function registerProxy(proxy2, ep) {
|
|
372
|
+
const newCount = (proxyCounter.get(ep) || 0) + 1;
|
|
373
|
+
proxyCounter.set(ep, newCount);
|
|
374
|
+
if (proxyFinalizers) {
|
|
375
|
+
proxyFinalizers.register(proxy2, ep, proxy2);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function unregisterProxy(proxy2) {
|
|
379
|
+
if (proxyFinalizers) {
|
|
380
|
+
proxyFinalizers.unregister(proxy2);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
function createProxy(ep, path = [], target = function() {
|
|
384
|
+
}) {
|
|
385
|
+
let isProxyReleased = false;
|
|
386
|
+
const proxy2 = new Proxy(target, {
|
|
387
|
+
get(_target, prop) {
|
|
388
|
+
throwIfProxyReleased(isProxyReleased);
|
|
389
|
+
if (prop === releaseProxy) {
|
|
390
|
+
return () => {
|
|
391
|
+
unregisterProxy(proxy2);
|
|
392
|
+
releaseEndpoint(ep);
|
|
393
|
+
isProxyReleased = true;
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
if (prop === "then") {
|
|
397
|
+
if (path.length === 0) {
|
|
398
|
+
return { then: () => proxy2 };
|
|
399
|
+
}
|
|
400
|
+
const r = requestResponseMessage(ep, {
|
|
401
|
+
type: "GET",
|
|
402
|
+
path: path.map((p) => p.toString())
|
|
403
|
+
}).then(fromWireValue);
|
|
404
|
+
return r.then.bind(r);
|
|
405
|
+
}
|
|
406
|
+
return createProxy(ep, [...path, prop]);
|
|
407
|
+
},
|
|
408
|
+
set(_target, prop, rawValue) {
|
|
409
|
+
throwIfProxyReleased(isProxyReleased);
|
|
410
|
+
const [value, transferables] = toWireValue(rawValue);
|
|
411
|
+
return requestResponseMessage(ep, {
|
|
412
|
+
type: "SET",
|
|
413
|
+
path: [...path, prop].map((p) => p.toString()),
|
|
414
|
+
value
|
|
415
|
+
}, transferables).then(fromWireValue);
|
|
416
|
+
},
|
|
417
|
+
apply(_target, _thisArg, rawArgumentList) {
|
|
418
|
+
throwIfProxyReleased(isProxyReleased);
|
|
419
|
+
const last = path[path.length - 1];
|
|
420
|
+
if (last === createEndpoint) {
|
|
421
|
+
return requestResponseMessage(ep, {
|
|
422
|
+
type: "ENDPOINT"
|
|
423
|
+
}).then(fromWireValue);
|
|
424
|
+
}
|
|
425
|
+
if (last === "bind") {
|
|
426
|
+
return createProxy(ep, path.slice(0, -1));
|
|
427
|
+
}
|
|
428
|
+
const [argumentList, transferables] = processArguments(rawArgumentList);
|
|
429
|
+
return requestResponseMessage(ep, {
|
|
430
|
+
type: "APPLY",
|
|
431
|
+
path: path.map((p) => p.toString()),
|
|
432
|
+
argumentList
|
|
433
|
+
}, transferables).then(fromWireValue);
|
|
434
|
+
},
|
|
435
|
+
construct(_target, rawArgumentList) {
|
|
436
|
+
throwIfProxyReleased(isProxyReleased);
|
|
437
|
+
const [argumentList, transferables] = processArguments(rawArgumentList);
|
|
438
|
+
return requestResponseMessage(ep, {
|
|
439
|
+
type: "CONSTRUCT",
|
|
440
|
+
path: path.map((p) => p.toString()),
|
|
441
|
+
argumentList
|
|
442
|
+
}, transferables).then(fromWireValue);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
registerProxy(proxy2, ep);
|
|
446
|
+
return proxy2;
|
|
447
|
+
}
|
|
448
|
+
function myFlat(arr) {
|
|
449
|
+
return Array.prototype.concat.apply([], arr);
|
|
450
|
+
}
|
|
451
|
+
function processArguments(argumentList) {
|
|
452
|
+
const processed = argumentList.map(toWireValue);
|
|
453
|
+
return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
|
|
454
|
+
}
|
|
455
|
+
const transferCache = /* @__PURE__ */ new WeakMap();
|
|
456
|
+
function transfer(obj, transfers) {
|
|
457
|
+
transferCache.set(obj, transfers);
|
|
458
|
+
return obj;
|
|
459
|
+
}
|
|
460
|
+
function proxy(obj) {
|
|
461
|
+
return Object.assign(obj, { [proxyMarker]: true });
|
|
462
|
+
}
|
|
463
|
+
function toWireValue(value) {
|
|
464
|
+
for (const [name, handler] of transferHandlers) {
|
|
465
|
+
if (handler.canHandle(value)) {
|
|
466
|
+
const [serializedValue, transferables] = handler.serialize(value);
|
|
467
|
+
return [
|
|
468
|
+
{
|
|
469
|
+
type: "HANDLER",
|
|
470
|
+
name,
|
|
471
|
+
value: serializedValue
|
|
472
|
+
},
|
|
473
|
+
transferables
|
|
474
|
+
];
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return [
|
|
478
|
+
{
|
|
479
|
+
type: "RAW",
|
|
480
|
+
value
|
|
481
|
+
},
|
|
482
|
+
transferCache.get(value) || []
|
|
483
|
+
];
|
|
484
|
+
}
|
|
485
|
+
function fromWireValue(value) {
|
|
486
|
+
switch (value.type) {
|
|
487
|
+
case "HANDLER":
|
|
488
|
+
return transferHandlers.get(value.name).deserialize(value.value);
|
|
489
|
+
case "RAW":
|
|
490
|
+
return value.value;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
function requestResponseMessage(ep, msg, transfers) {
|
|
494
|
+
return new Promise((resolve) => {
|
|
495
|
+
const id = generateUUID();
|
|
496
|
+
ep.addEventListener("message", function l(ev) {
|
|
497
|
+
if (!ev.data || !ev.data.id || ev.data.id !== id) {
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
ep.removeEventListener("message", l);
|
|
501
|
+
resolve(ev.data);
|
|
502
|
+
});
|
|
503
|
+
if (ep.start) {
|
|
504
|
+
ep.start();
|
|
505
|
+
}
|
|
506
|
+
ep.postMessage(Object.assign({ id }, msg), transfers);
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
function generateUUID() {
|
|
510
|
+
return new Array(4).fill(0).map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16)).join("-");
|
|
511
|
+
}
|
|
512
|
+
class GaussianSplatGeometry extends threepipe.InstancedBufferGeometry {
|
|
513
|
+
constructor(_worker, _vertexCount, _maxSplats, _onLoad) {
|
|
514
|
+
super();
|
|
515
|
+
this._worker = _worker;
|
|
516
|
+
this._vertexCount = _vertexCount;
|
|
517
|
+
this._maxSplats = _maxSplats;
|
|
518
|
+
this._onLoad = _onLoad;
|
|
519
|
+
this.isGaussianSplatGeometry = true;
|
|
520
|
+
this.setDirty = threepipe.iGeometryCommons.setDirty;
|
|
521
|
+
this.refreshUi = threepipe.iGeometryCommons.refreshUi;
|
|
522
|
+
this.appliedMeshes = /* @__PURE__ */ new Set();
|
|
523
|
+
this._viewProj = [];
|
|
524
|
+
this._sortRunning = false;
|
|
525
|
+
this._initialized = false;
|
|
526
|
+
this._centersBuffer = new Float32Array(0);
|
|
527
|
+
threepipe.iGeometryCommons.upgradeGeometry.call(this);
|
|
528
|
+
this.initAttributes();
|
|
529
|
+
}
|
|
530
|
+
async update(camera, meshMatrixWorld) {
|
|
531
|
+
if (this._sortRunning || !this._initialized || !this._worker) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
camera.updateMatrixWorld(true);
|
|
535
|
+
this._viewProj = new threepipe.Matrix4().multiply(camera.projectionMatrix).multiply(camera.matrixWorldInverse).multiply(meshMatrixWorld).elements;
|
|
536
|
+
this._sortRunning = true;
|
|
537
|
+
const viewProj = new Float32Array(this._viewProj);
|
|
538
|
+
const result = await this._worker.runSort(viewProj);
|
|
539
|
+
const { quat, scale, center, color } = this._extractViews(result);
|
|
540
|
+
if (this._centersBuffer.length !== center.length)
|
|
541
|
+
this._centersBuffer = new Float32Array(center);
|
|
542
|
+
else
|
|
543
|
+
this._centersBuffer.set(center);
|
|
544
|
+
this.attributes.color.array = color;
|
|
545
|
+
this.attributes.quat.array = quat;
|
|
546
|
+
this.attributes.scale.array = scale;
|
|
547
|
+
this.attributes.center.array = this._centersBuffer;
|
|
548
|
+
const pms = Promise.all([
|
|
549
|
+
new Promise((resolve) => this.attributes.color.onUpload(resolve)),
|
|
550
|
+
new Promise((resolve) => this.attributes.quat.onUpload(resolve)),
|
|
551
|
+
new Promise((resolve) => this.attributes.scale.onUpload(resolve))
|
|
552
|
+
// new Promise<void>(resolve => (this.attributes.center as InstancedBufferAttribute).onUpload(resolve)),
|
|
553
|
+
]);
|
|
554
|
+
this.attributes.color.needsUpdate = true;
|
|
555
|
+
this.attributes.quat.needsUpdate = true;
|
|
556
|
+
this.attributes.scale.needsUpdate = true;
|
|
557
|
+
this.attributes.center.needsUpdate = true;
|
|
558
|
+
this.setDirty();
|
|
559
|
+
await pms;
|
|
560
|
+
await this._worker.returnBuffer(transfer(result, [result]));
|
|
561
|
+
this._sortRunning = false;
|
|
562
|
+
}
|
|
563
|
+
async initAttributes() {
|
|
564
|
+
const viewProj = new Float32Array(this._viewProj);
|
|
565
|
+
const result = await this._worker.runSort(viewProj);
|
|
566
|
+
const { quat, scale, center, color } = this._extractViews(result);
|
|
567
|
+
this.setAttribute("color", new threepipe.InstancedBufferAttribute(color, 4, true));
|
|
568
|
+
this.setAttribute("quat", new threepipe.InstancedBufferAttribute(quat, 4, true));
|
|
569
|
+
this.setAttribute("scale", new threepipe.InstancedBufferAttribute(scale, 3, true));
|
|
570
|
+
this.setAttribute("center", new threepipe.InstancedBufferAttribute(center, 3, true));
|
|
571
|
+
this.setAttribute("position", new threepipe.BufferAttribute(new Float32Array([1, -1, 0, 1, 1, 0, -1, -1, 0, -1, 1, 0]), 3, true));
|
|
572
|
+
this.attributes.position.needsUpdate = true;
|
|
573
|
+
this.setIndex(new threepipe.BufferAttribute(new Uint16Array([0, 1, 2, 2, 3, 0]), 1, true));
|
|
574
|
+
this.instanceCount = Math.min(quat.length / 4, this._maxSplats);
|
|
575
|
+
this.computeBoundingBox();
|
|
576
|
+
this.computeBoundingSphere();
|
|
577
|
+
this._initialized = true;
|
|
578
|
+
this.setDirty();
|
|
579
|
+
this._onLoad && this._onLoad(this);
|
|
580
|
+
}
|
|
581
|
+
_extractViews(receivedBuffer) {
|
|
582
|
+
const combined = new Float32Array(receivedBuffer);
|
|
583
|
+
const quatLength = 4 * this._vertexCount;
|
|
584
|
+
const scaleLength = 3 * this._vertexCount;
|
|
585
|
+
const centerLength = 3 * this._vertexCount;
|
|
586
|
+
const colorLength = 4 * this._vertexCount;
|
|
587
|
+
const quatOffset = 0;
|
|
588
|
+
const scaleOffset = quatOffset + quatLength;
|
|
589
|
+
const centerOffset = scaleOffset + scaleLength;
|
|
590
|
+
const colorOffset = centerOffset + centerLength;
|
|
591
|
+
const quat = combined.subarray(quatOffset, quatOffset + quatLength);
|
|
592
|
+
const scale = combined.subarray(scaleOffset, scaleOffset + scaleLength);
|
|
593
|
+
const center = combined.subarray(centerOffset, centerOffset + centerLength);
|
|
594
|
+
const color = combined.subarray(colorOffset, colorOffset + colorLength);
|
|
595
|
+
return { quat, scale, center, color };
|
|
596
|
+
}
|
|
597
|
+
computeBoundingBox() {
|
|
598
|
+
if (!this.getAttribute("center"))
|
|
599
|
+
return super.computeBoundingBox();
|
|
600
|
+
const box = this.boundingBox ?? (this.boundingBox = new threepipe.Box3());
|
|
601
|
+
box.setFromBufferAttribute(this.getAttribute("center"));
|
|
602
|
+
if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) {
|
|
603
|
+
console.error('GaussianSplatGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
computeBoundingSphere() {
|
|
607
|
+
if (this.boundingSphere === null)
|
|
608
|
+
this.boundingSphere = new threepipe.Sphere();
|
|
609
|
+
const position = this.attributes.center;
|
|
610
|
+
if (position && position.isGLBufferAttribute) {
|
|
611
|
+
console.error('THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".', this);
|
|
612
|
+
this.boundingSphere.set(new threepipe.Vector3(), Infinity);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
if (position) {
|
|
616
|
+
const center = this.boundingSphere.center;
|
|
617
|
+
if (!this.boundingBox)
|
|
618
|
+
this.computeBoundingBox();
|
|
619
|
+
this.boundingBox.getCenter(center);
|
|
620
|
+
let maxRadiusSq = 0;
|
|
621
|
+
const vector = new threepipe.Vector3();
|
|
622
|
+
for (let i = 0, il = position.count; i < il; i++) {
|
|
623
|
+
vector.fromBufferAttribute(position, i);
|
|
624
|
+
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector));
|
|
625
|
+
}
|
|
626
|
+
this.boundingSphere.radius = Math.sqrt(maxRadiusSq);
|
|
627
|
+
if (isNaN(this.boundingSphere.radius)) {
|
|
628
|
+
console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
class GaussianSplatMesh extends threepipe.Mesh2 {
|
|
634
|
+
constructor(geometry, material) {
|
|
635
|
+
super(geometry, material);
|
|
636
|
+
this.isGaussianSplatMesh = true;
|
|
637
|
+
this.frustumCulled = false;
|
|
638
|
+
}
|
|
639
|
+
async update(camera, renderer) {
|
|
640
|
+
var _a;
|
|
641
|
+
if ((_a = this.material) == null ? void 0 : _a.isGaussianSplatMaterialRaw) {
|
|
642
|
+
this.material.update(camera, renderer);
|
|
643
|
+
} else if (this.material) {
|
|
644
|
+
const ext = this.material.gsplatExtension ?? this.material.materialExtensions.find((e) => e.isGaussianSplatMaterialExtension);
|
|
645
|
+
ext && ext.update(camera, renderer);
|
|
646
|
+
}
|
|
647
|
+
this.updateMatrixWorld(true);
|
|
648
|
+
return this.geometry.update(camera, this.matrixWorld);
|
|
649
|
+
}
|
|
650
|
+
raycast(raycaster, intersects) {
|
|
651
|
+
const geometry = this.geometry;
|
|
652
|
+
const matrixWorld = this.matrixWorld;
|
|
653
|
+
const threshold = 0.02;
|
|
654
|
+
if (geometry.boundingSphere === null)
|
|
655
|
+
geometry.computeBoundingSphere();
|
|
656
|
+
const sphere = new three.Sphere();
|
|
657
|
+
sphere.copy(geometry.boundingSphere);
|
|
658
|
+
sphere.applyMatrix4(matrixWorld);
|
|
659
|
+
sphere.radius += threshold;
|
|
660
|
+
if (!raycaster.ray.intersectsSphere(sphere))
|
|
661
|
+
return;
|
|
662
|
+
const inverseMatrix = new three.Matrix4();
|
|
663
|
+
const ray = new three.Ray();
|
|
664
|
+
inverseMatrix.copy(matrixWorld).invert();
|
|
665
|
+
ray.copy(raycaster.ray).applyMatrix4(inverseMatrix);
|
|
666
|
+
const localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3);
|
|
667
|
+
const localThresholdSq = localThreshold * localThreshold;
|
|
668
|
+
const attributes = geometry.attributes;
|
|
669
|
+
const positionAttribute = attributes.center;
|
|
670
|
+
const position = new three.Vector3();
|
|
671
|
+
for (let i = 0, l = positionAttribute.count; i < l; i++) {
|
|
672
|
+
position.fromBufferAttribute(positionAttribute, i);
|
|
673
|
+
const rayPointDistanceSq = ray.distanceSqToPoint(position);
|
|
674
|
+
if (rayPointDistanceSq < localThresholdSq) {
|
|
675
|
+
const intersectPoint = new three.Vector3();
|
|
676
|
+
ray.closestPointToPoint(position, intersectPoint);
|
|
677
|
+
intersectPoint.applyMatrix4(matrixWorld);
|
|
678
|
+
const distance = raycaster.ray.origin.distanceTo(intersectPoint);
|
|
679
|
+
if (distance < raycaster.near || distance > raycaster.far)
|
|
680
|
+
return;
|
|
681
|
+
intersects.push({
|
|
682
|
+
distance,
|
|
683
|
+
distanceToRay: Math.sqrt(rayPointDistanceSq),
|
|
684
|
+
point: intersectPoint,
|
|
685
|
+
face: null,
|
|
686
|
+
object: this
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
const styles = "";
|
|
693
|
+
const SPLAT_ROW_LENGTH = 3 * 4 + 3 * 4 + 4 + 4;
|
|
694
|
+
function trimBuffer(_buffer, _maxSplats, _vertexCount) {
|
|
695
|
+
const actualVertexCount = Math.min(_vertexCount, _maxSplats);
|
|
696
|
+
const actualBufferSize = SPLAT_ROW_LENGTH * actualVertexCount;
|
|
697
|
+
const buffer = _buffer.slice(0, actualBufferSize);
|
|
698
|
+
return { buffer, vertexCount: actualVertexCount };
|
|
699
|
+
}
|
|
700
|
+
class SortWorkerManager {
|
|
701
|
+
constructor() {
|
|
702
|
+
this._workers = [];
|
|
703
|
+
this._maxWorkers = 8;
|
|
704
|
+
this.onError = (e) => {
|
|
705
|
+
console.error(e);
|
|
706
|
+
console.error(
|
|
707
|
+
"ERROR: Line ",
|
|
708
|
+
e.lineno,
|
|
709
|
+
" in ",
|
|
710
|
+
e.filename,
|
|
711
|
+
": ",
|
|
712
|
+
e.message
|
|
713
|
+
);
|
|
714
|
+
};
|
|
715
|
+
const worker = new Worker(new URL("" + (typeof document === "undefined" && typeof location === "undefined" ? require("url").pathToFileURL(__dirname + "/assets/worker-dK7pvmNj.js").href : new URL("assets/worker-dK7pvmNj.js", typeof document === "undefined" ? location.href : document.currentScript && document.currentScript.src || document.baseURI).href), typeof document === "undefined" && typeof location === "undefined" ? require("url").pathToFileURL(__filename).href : typeof document === "undefined" ? location.href : _documentCurrentScript && _documentCurrentScript.src || new URL("index.js", document.baseURI).href), { type: "module" });
|
|
716
|
+
worker.addEventListener("error", this.onError, false);
|
|
717
|
+
this._workerCtor = wrap(worker);
|
|
718
|
+
}
|
|
719
|
+
async createWorker(data, maxSplats = 1e6) {
|
|
720
|
+
if (this._workers.length < this._maxWorkers) {
|
|
721
|
+
const vertexCount = Math.floor(data.length / SPLAT_ROW_LENGTH);
|
|
722
|
+
const bufferInfo = trimBuffer(data, maxSplats, vertexCount);
|
|
723
|
+
const globalBuffer = transfer(bufferInfo.buffer, [bufferInfo.buffer.buffer]);
|
|
724
|
+
const worker = await new this._workerCtor(vertexCount, globalBuffer);
|
|
725
|
+
await worker.load();
|
|
726
|
+
this._workers.push(worker);
|
|
727
|
+
return worker;
|
|
728
|
+
}
|
|
729
|
+
console.error("Max workers reached");
|
|
730
|
+
throw new Error("Max workers reached");
|
|
731
|
+
}
|
|
732
|
+
async disposeWorker(worker) {
|
|
733
|
+
const index2 = this._workers.indexOf(worker);
|
|
734
|
+
if (index2 !== -1) {
|
|
735
|
+
this._workers.splice(index2, 1);
|
|
736
|
+
await worker.dispose();
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
class SplatLoader extends threepipe.Loader {
|
|
741
|
+
constructor(manager) {
|
|
742
|
+
super(manager);
|
|
743
|
+
this.materialConstructor = (_) => new GaussianSplatMaterialUnlit();
|
|
744
|
+
this.onGeometryLoad = (_) => {
|
|
745
|
+
return;
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
load(url, onLoad, onProgress, onError) {
|
|
749
|
+
const loader = new threepipe.FileLoader(this.manager);
|
|
750
|
+
loader.setPath(this.path);
|
|
751
|
+
loader.setResponseType("arraybuffer");
|
|
752
|
+
loader.setRequestHeader(this.requestHeader);
|
|
753
|
+
loader.setWithCredentials(this.withCredentials);
|
|
754
|
+
loader.load(url, async (buffer) => {
|
|
755
|
+
try {
|
|
756
|
+
const data = new Uint8Array(buffer);
|
|
757
|
+
const maxSplats = 1e6;
|
|
758
|
+
const vertexCount = Math.floor(data.length / SPLAT_ROW_LENGTH);
|
|
759
|
+
const worker = await this.sortWorkerManager.createWorker(data, maxSplats);
|
|
760
|
+
const geometry = new GaussianSplatGeometry(worker, vertexCount, maxSplats, this.onGeometryLoad);
|
|
761
|
+
const mesh = new GaussianSplatMesh(geometry, this.materialConstructor(geometry));
|
|
762
|
+
mesh.rotation.x = Math.PI;
|
|
763
|
+
if (!url.startsWith("blob:") && !url.startsWith("data:"))
|
|
764
|
+
mesh.name = url.split("/").pop().split("?")[0];
|
|
765
|
+
onLoad && onLoad(mesh);
|
|
766
|
+
} catch (e) {
|
|
767
|
+
if (onError)
|
|
768
|
+
onError(e);
|
|
769
|
+
else
|
|
770
|
+
console.error(e);
|
|
771
|
+
this.manager.itemError(url);
|
|
772
|
+
}
|
|
773
|
+
}, onProgress, onError);
|
|
774
|
+
}
|
|
775
|
+
async loadAsync(url, onProgress) {
|
|
776
|
+
return new Promise((resolve, reject) => this.load(url, resolve, onProgress, reject));
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
const _ThreeGaussianSplatPlugin = class _ThreeGaussianSplatPlugin extends threepipe.AViewerPluginSync {
|
|
780
|
+
constructor() {
|
|
781
|
+
super();
|
|
782
|
+
this.enabled = true;
|
|
783
|
+
this.dependencies = [];
|
|
784
|
+
this.toJSON = null;
|
|
785
|
+
this.splats = [];
|
|
786
|
+
this._ready = false;
|
|
787
|
+
this._activeCameraUpdate = () => {
|
|
788
|
+
if (!this._ready || this.isDisabled())
|
|
789
|
+
return;
|
|
790
|
+
this.splats.forEach(async (splat) => splat.update(this._viewer.scene.mainCamera, this._viewer.renderManager.webglRenderer));
|
|
791
|
+
};
|
|
792
|
+
this._geometryUpdate = (event) => {
|
|
793
|
+
var _a;
|
|
794
|
+
if (!this._ready || this.isDisabled() || !((_a = event.geometry) == null ? void 0 : _a.isGaussianSplatGeometry))
|
|
795
|
+
return;
|
|
796
|
+
event.geometry.appliedMeshes.forEach(async (splat) => splat.update ? splat.update(this._viewer.scene.mainCamera, this._viewer.renderManager.webglRenderer) : void 0);
|
|
797
|
+
};
|
|
798
|
+
this._sortWorkerManager = new SortWorkerManager();
|
|
799
|
+
this._importer = new threepipe.Importer(class extends SplatLoader {
|
|
800
|
+
constructor() {
|
|
801
|
+
super(...arguments);
|
|
802
|
+
this.onDispose = () => {
|
|
803
|
+
return;
|
|
804
|
+
};
|
|
805
|
+
this.onCreate = () => {
|
|
806
|
+
return;
|
|
807
|
+
};
|
|
808
|
+
}
|
|
809
|
+
transform(res, _) {
|
|
810
|
+
res.addEventListener("dispose", () => this.onDispose(res));
|
|
811
|
+
this.onCreate(res);
|
|
812
|
+
return res;
|
|
813
|
+
}
|
|
814
|
+
}, ["splat"], [], true, (l) => {
|
|
815
|
+
if (!l)
|
|
816
|
+
return l;
|
|
817
|
+
l.sortWorkerManager = this._sortWorkerManager;
|
|
818
|
+
l.onDispose = (mesh) => {
|
|
819
|
+
this.splats = this.splats.filter((splat) => splat !== mesh);
|
|
820
|
+
};
|
|
821
|
+
l.onCreate = (mesh) => {
|
|
822
|
+
this.splats.push(mesh);
|
|
823
|
+
};
|
|
824
|
+
l.onGeometryLoad = (_) => {
|
|
825
|
+
var _a;
|
|
826
|
+
(_a = this._viewer) == null ? void 0 : _a.setDirty();
|
|
827
|
+
};
|
|
828
|
+
return l;
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
onAdded(viewer) {
|
|
832
|
+
super.onAdded(viewer);
|
|
833
|
+
threepipe.createStyles(styles);
|
|
834
|
+
viewer.assetManager.importer.addImporter(this._importer);
|
|
835
|
+
viewer.scene.addEventListener("mainCameraUpdate", this._activeCameraUpdate);
|
|
836
|
+
viewer.scene.addEventListener("geometryUpdate", this._geometryUpdate);
|
|
837
|
+
this._ready = true;
|
|
838
|
+
}
|
|
839
|
+
onRemove(viewer) {
|
|
840
|
+
viewer.assetManager.importer.removeImporter(this._importer);
|
|
841
|
+
}
|
|
842
|
+
// protected _viewerListeners = {
|
|
843
|
+
// preRender: (_: IViewerEvent) => {
|
|
844
|
+
// },
|
|
845
|
+
// }
|
|
846
|
+
};
|
|
847
|
+
_ThreeGaussianSplatPlugin.PluginType = "ThreeGaussianSplatPlugin";
|
|
848
|
+
let ThreeGaussianSplatPlugin = _ThreeGaussianSplatPlugin;
|
|
849
|
+
/**
|
|
850
|
+
* ThreeGaussianSplatPlugin: Threejs utilities and threepipe plugin and material extension for Gaussian Splatting
|
|
851
|
+
*
|
|
852
|
+
* @license
|
|
853
|
+
* A port of -
|
|
854
|
+
* https://github.com/zappar-xr/three-gaussian-splat
|
|
855
|
+
* MIT License (c) 2023 Zappar Limited
|
|
856
|
+
* Which is based on -
|
|
857
|
+
* gsplat.js, MIT License (c) 2023 Dylan Ebert
|
|
858
|
+
* antimatter15/splat, MIT License (c) 2023 Kevin Kwok
|
|
859
|
+
*/
|
|
860
|
+
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
861
|
+
__proto__: null,
|
|
862
|
+
GaussianSplatGeometry,
|
|
863
|
+
GaussianSplatMaterialExtension,
|
|
864
|
+
GaussianSplatMaterialPhysical,
|
|
865
|
+
GaussianSplatMaterialRaw,
|
|
866
|
+
GaussianSplatMaterialUnlit,
|
|
867
|
+
GaussianSplatMesh,
|
|
868
|
+
SplatLoader,
|
|
869
|
+
ThreeGaussianSplatPlugin,
|
|
870
|
+
computeFocalLengths,
|
|
871
|
+
gaussianSplatShaders
|
|
872
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
873
|
+
class GaussianSplattingPlugin extends ThreeGaussianSplatPlugin {
|
|
874
|
+
}
|
|
875
|
+
exports2.GaussianSplattingPlugin = GaussianSplattingPlugin;
|
|
876
|
+
exports2.threeGaussianSplat = index;
|
|
877
|
+
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
878
|
+
});
|
|
879
|
+
//# sourceMappingURL=index.js.map
|