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