@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.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