@heliguy-xyz/splat-viewer 1.0.0-rc.25 → 1.0.0-rc.26

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 (24) hide show
  1. package/README.md +39 -0
  2. package/dist/web-component/splat-viewer.esm.js +601 -548
  3. package/dist/web-component/splat-viewer.esm.min.js +1 -1
  4. package/dist/web-component/splat-viewer.js +601 -548
  5. package/dist/web-component/splat-viewer.min.js +1 -1
  6. package/dist/web-component/types/web-component/SplatViewerCore.d.ts +1 -0
  7. package/dist/web-component/types/web-component/SplatViewerCore.d.ts.map +1 -1
  8. package/dist/web-component/types/web-component/SplatViewerElement.d.ts +2 -0
  9. package/dist/web-component/types/web-component/SplatViewerElement.d.ts.map +1 -1
  10. package/dist/web-component/types/web-component/types/attributes.d.ts +3 -0
  11. package/dist/web-component/types/web-component/types/attributes.d.ts.map +1 -1
  12. package/dist/web-component/types/web-component/types/core.d.ts +2 -0
  13. package/dist/web-component/types/web-component/types/core.d.ts.map +1 -1
  14. package/dist/web-component/types/web-component/utils/config.d.ts.map +1 -1
  15. package/dist/web-component/web-component/SplatViewerCore.d.ts +1 -0
  16. package/dist/web-component/web-component/SplatViewerCore.d.ts.map +1 -1
  17. package/dist/web-component/web-component/SplatViewerElement.d.ts +2 -0
  18. package/dist/web-component/web-component/SplatViewerElement.d.ts.map +1 -1
  19. package/dist/web-component/web-component/types/attributes.d.ts +3 -0
  20. package/dist/web-component/web-component/types/attributes.d.ts.map +1 -1
  21. package/dist/web-component/web-component/types/core.d.ts +2 -0
  22. package/dist/web-component/web-component/types/core.d.ts.map +1 -1
  23. package/dist/web-component/web-component/utils/config.d.ts.map +1 -1
  24. package/package.json +1 -1
@@ -139519,6 +139519,7 @@ const DEFAULT_CONFIG = {
139519
139519
  enableStats: false,
139520
139520
  autoFocus: true,
139521
139521
  maxSplats: 2000000,
139522
+ previewMode: false,
139522
139523
  camera: {
139523
139524
  position: { x: 0, y: 0, z: 10 },
139524
139525
  target: { x: 0, y: 0, z: 0 },
@@ -139608,6 +139609,10 @@ function getConfigFromAttributes(element) {
139608
139609
  if (enableStats !== null) {
139609
139610
  config.enableStats = parseBoolean(enableStats);
139610
139611
  }
139612
+ const previewMode = element.getAttribute('preview-mode');
139613
+ if (previewMode !== null) {
139614
+ config.previewMode = parseBoolean(previewMode);
139615
+ }
139611
139616
  // Parse number attributes
139612
139617
  const maxSplats = element.getAttribute('max-splats');
139613
139618
  if (maxSplats !== null) {
@@ -143161,222 +143166,222 @@ class AssetLoader {
143161
143166
  }
143162
143167
  }
143163
143168
 
143164
- const vertexShader$6 = /* glsl */ `
143165
- attribute vec2 vertex_position;
143166
- void main(void) {
143167
- gl_Position = vec4(vertex_position, 0.0, 1.0);
143168
- }
143169
- `;
143170
- const fragmentShader$6 = /* glsl */ `
143171
- uniform highp usampler2D transformA; // splat center x, y, z
143172
- uniform highp usampler2D splatTransform; // transform palette index
143173
- uniform sampler2D transformPalette; // palette of transforms
143174
- uniform sampler2D splatState; // per-splat state
143175
- uniform highp ivec3 splat_params; // texture width, texture height, num splats
143176
- uniform highp uint mode; // 0: selected, 1: visible
143177
-
143178
- // calculate min and max for a single column of splats
143179
- void main(void) {
143180
-
143181
- vec3 boundMin = vec3(1e6);
143182
- vec3 boundMax = vec3(-1e6);
143183
-
143184
- for (int id = 0; id < splat_params.y; id++) {
143185
- // calculate splatUV
143186
- ivec2 splatUV = ivec2(gl_FragCoord.x, id);
143187
-
143188
- // skip out-of-range splats
143189
- if ((splatUV.x + splatUV.y * splat_params.x) >= splat_params.z) {
143190
- continue;
143191
- }
143192
-
143193
- // read splat state
143194
- uint state = uint(texelFetch(splatState, splatUV, 0).r * 255.0);
143195
-
143196
- // skip deleted or locked splats
143197
- if (((mode == 0u) && (state != 1u)) || ((mode == 1u) && ((state & 4u) != 0u))) {
143198
- continue;
143199
- }
143200
-
143201
- // read splat center
143202
- vec3 center = uintBitsToFloat(texelFetch(transformA, splatUV, 0).xyz);
143203
-
143204
- // apply optional per-splat transform
143205
- uint transformIndex = texelFetch(splatTransform, splatUV, 0).r;
143206
- if (transformIndex > 0u) {
143207
- // read transform matrix
143208
- int u = int(transformIndex % 512u) * 3;
143209
- int v = int(transformIndex / 512u);
143210
-
143211
- mat3x4 t;
143212
- t[0] = texelFetch(transformPalette, ivec2(u, v), 0);
143213
- t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0);
143214
- t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0);
143215
-
143216
- center = vec4(center, 1.0) * t;
143217
- }
143218
-
143219
- boundMin = min(boundMin, mix(center, boundMin, isinf(center)));
143220
- boundMax = max(boundMax, mix(center, boundMax, isinf(center)));
143221
- }
143222
-
143223
- pcFragColor0 = vec4(boundMin, 0.0);
143224
- pcFragColor1 = vec4(boundMax, 0.0);
143225
- }
143226
- `;
143227
-
143228
- const vertexShader$5 = /* glsl */ `
143229
- attribute vec2 vertex_position;
143230
- void main(void) {
143231
- gl_Position = vec4(vertex_position, 0.0, 1.0);
143232
- }
143233
- `;
143234
- const fragmentShader$5 = /* glsl */ `
143235
- uniform highp usampler2D transformA; // splat center x, y, z
143236
- uniform highp usampler2D splatTransform; // transform palette index
143237
- uniform sampler2D transformPalette; // palette of transforms
143238
- uniform uvec2 splat_params; // splat texture width, num splats
143239
-
143240
- uniform mat4 matrix_model;
143241
- uniform mat4 matrix_viewProjection;
143242
-
143243
- uniform uvec2 output_params; // output width, height
143244
-
143245
- // 0: mask, 1: rect, 2: sphere
143246
- uniform int mode;
143247
-
143248
- // mask params
143249
- uniform sampler2D mask; // mask in alpha channel
143250
- uniform vec2 mask_params; // mask width, height
143251
-
143252
- // rect params
143253
- uniform vec4 rect_params; // rect x, y, width, height
143254
-
143255
- // sphere params
143256
- uniform vec4 sphere_params; // sphere x, y, z, radius
143257
-
143258
- // box params
143259
- uniform vec4 box_params; // box x, y, z
143260
- uniform vec4 aabb_params; // len x, y, z
143261
-
143262
- void main(void) {
143263
- // calculate output id
143264
- uvec2 outputUV = uvec2(gl_FragCoord);
143265
- uint outputId = (outputUV.x + outputUV.y * output_params.x) * 4u;
143266
-
143267
- vec4 clr = vec4(0.0);
143268
-
143269
- for (uint i = 0u; i < 4u; i++) {
143270
- uint id = outputId + i;
143271
-
143272
- if (id >= splat_params.y) {
143273
- continue;
143274
- }
143275
-
143276
- // calculate splatUV
143277
- ivec2 splatUV = ivec2(
143278
- int(id % splat_params.x),
143279
- int(id / splat_params.x)
143280
- );
143281
-
143282
- // read splat center
143283
- vec3 center = uintBitsToFloat(texelFetch(transformA, splatUV, 0).xyz);
143284
-
143285
- // apply optional per-splat transform
143286
- uint transformIndex = texelFetch(splatTransform, splatUV, 0).r;
143287
- if (transformIndex > 0u) {
143288
- // read transform matrix
143289
- int u = int(transformIndex % 512u) * 3;
143290
- int v = int(transformIndex / 512u);
143291
-
143292
- mat3x4 t;
143293
- t[0] = texelFetch(transformPalette, ivec2(u, v), 0);
143294
- t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0);
143295
- t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0);
143296
-
143297
- center = vec4(center, 1.0) * t;
143298
- }
143299
-
143300
- // transform to clip space and discard if outside
143301
- vec3 world = (matrix_model * vec4(center, 1.0)).xyz;
143302
- vec4 clip = matrix_viewProjection * vec4(world, 1.0);
143303
- vec3 ndc = clip.xyz / clip.w;
143304
-
143305
- // skip offscreen fragments
143306
- if (!any(greaterThan(abs(ndc), vec3(1.0)))) {
143307
- if (mode == 0) {
143308
- // select by mask
143309
- ivec2 maskUV = ivec2((ndc.xy * vec2(0.5, -0.5) + 0.5) * mask_params);
143310
- clr[i] = texelFetch(mask, maskUV, 0).a < 1.0 ? 0.0 : 1.0;
143311
- } else if (mode == 1) {
143312
- // select by rect
143313
- clr[i] = all(greaterThan(ndc.xy * vec2(1.0, -1.0), rect_params.xy)) && all(lessThan(ndc.xy * vec2(1.0, -1.0), rect_params.zw)) ? 1.0 : 0.0;
143314
- } else if (mode == 2) {
143315
- // select by sphere
143316
- clr[i] = length(world - sphere_params.xyz) < sphere_params.w ? 1.0 : 0.0;
143317
- } else if (mode == 3) {
143318
- // select by box
143319
- vec3 relativePosition = world - box_params.xyz;
143320
- bool isInsideCube = true;
143321
- if (relativePosition.x < -aabb_params.x || relativePosition.x > aabb_params.x) {
143322
- isInsideCube = false;
143323
- }
143324
- if (relativePosition.y < -aabb_params.y || relativePosition.y > aabb_params.y) {
143325
- isInsideCube = false;
143326
- }
143327
- if (relativePosition.z < -aabb_params.z || relativePosition.z > aabb_params.z) {
143328
- isInsideCube = false;
143329
- }
143330
- clr[i] = isInsideCube ? 1.0 : 0.0;
143331
- }
143332
- }
143333
- }
143334
-
143335
- gl_FragColor = clr;
143336
- }
143337
- `;
143338
-
143339
- const vertexShader$4 = /* glsl */ `
143340
- attribute vec2 vertex_position;
143341
- void main(void) {
143342
- gl_Position = vec4(vertex_position, 0.0, 1.0);
143343
- }
143344
- `;
143345
- const fragmentShader$4 = /* glsl */ `
143346
- uniform highp usampler2D transformA; // splat center x, y, z
143347
- uniform highp usampler2D splatTransform; // transform palette index
143348
- uniform sampler2D transformPalette; // palette of transforms
143349
- uniform ivec2 splat_params; // splat texture width, num splats
143350
-
143351
- void main(void) {
143352
- // calculate output id
143353
- ivec2 splatUV = ivec2(gl_FragCoord);
143354
-
143355
- // skip if splat index is out of bounds
143356
- if (splatUV.x + splatUV.y * splat_params.x >= splat_params.y) {
143357
- discard;
143358
- }
143359
-
143360
- // read splat center
143361
- vec3 center = uintBitsToFloat(texelFetch(transformA, splatUV, 0).xyz);
143362
-
143363
- // apply optional per-splat transform
143364
- uint transformIndex = texelFetch(splatTransform, splatUV, 0).r;
143365
- if (transformIndex > 0u) {
143366
- // read transform matrix
143367
- int u = int(transformIndex % 512u) * 3;
143368
- int v = int(transformIndex / 512u);
143369
-
143370
- mat3x4 t;
143371
- t[0] = texelFetch(transformPalette, ivec2(u, v), 0);
143372
- t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0);
143373
- t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0);
143374
-
143375
- center = vec4(center, 1.0) * t;
143376
- }
143377
-
143378
- gl_FragColor = vec4(center, 0.0);
143379
- }
143169
+ const vertexShader$6 = /* glsl */ `
143170
+ attribute vec2 vertex_position;
143171
+ void main(void) {
143172
+ gl_Position = vec4(vertex_position, 0.0, 1.0);
143173
+ }
143174
+ `;
143175
+ const fragmentShader$6 = /* glsl */ `
143176
+ uniform highp usampler2D transformA; // splat center x, y, z
143177
+ uniform highp usampler2D splatTransform; // transform palette index
143178
+ uniform sampler2D transformPalette; // palette of transforms
143179
+ uniform sampler2D splatState; // per-splat state
143180
+ uniform highp ivec3 splat_params; // texture width, texture height, num splats
143181
+ uniform highp uint mode; // 0: selected, 1: visible
143182
+
143183
+ // calculate min and max for a single column of splats
143184
+ void main(void) {
143185
+
143186
+ vec3 boundMin = vec3(1e6);
143187
+ vec3 boundMax = vec3(-1e6);
143188
+
143189
+ for (int id = 0; id < splat_params.y; id++) {
143190
+ // calculate splatUV
143191
+ ivec2 splatUV = ivec2(gl_FragCoord.x, id);
143192
+
143193
+ // skip out-of-range splats
143194
+ if ((splatUV.x + splatUV.y * splat_params.x) >= splat_params.z) {
143195
+ continue;
143196
+ }
143197
+
143198
+ // read splat state
143199
+ uint state = uint(texelFetch(splatState, splatUV, 0).r * 255.0);
143200
+
143201
+ // skip deleted or locked splats
143202
+ if (((mode == 0u) && (state != 1u)) || ((mode == 1u) && ((state & 4u) != 0u))) {
143203
+ continue;
143204
+ }
143205
+
143206
+ // read splat center
143207
+ vec3 center = uintBitsToFloat(texelFetch(transformA, splatUV, 0).xyz);
143208
+
143209
+ // apply optional per-splat transform
143210
+ uint transformIndex = texelFetch(splatTransform, splatUV, 0).r;
143211
+ if (transformIndex > 0u) {
143212
+ // read transform matrix
143213
+ int u = int(transformIndex % 512u) * 3;
143214
+ int v = int(transformIndex / 512u);
143215
+
143216
+ mat3x4 t;
143217
+ t[0] = texelFetch(transformPalette, ivec2(u, v), 0);
143218
+ t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0);
143219
+ t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0);
143220
+
143221
+ center = vec4(center, 1.0) * t;
143222
+ }
143223
+
143224
+ boundMin = min(boundMin, mix(center, boundMin, isinf(center)));
143225
+ boundMax = max(boundMax, mix(center, boundMax, isinf(center)));
143226
+ }
143227
+
143228
+ pcFragColor0 = vec4(boundMin, 0.0);
143229
+ pcFragColor1 = vec4(boundMax, 0.0);
143230
+ }
143231
+ `;
143232
+
143233
+ const vertexShader$5 = /* glsl */ `
143234
+ attribute vec2 vertex_position;
143235
+ void main(void) {
143236
+ gl_Position = vec4(vertex_position, 0.0, 1.0);
143237
+ }
143238
+ `;
143239
+ const fragmentShader$5 = /* glsl */ `
143240
+ uniform highp usampler2D transformA; // splat center x, y, z
143241
+ uniform highp usampler2D splatTransform; // transform palette index
143242
+ uniform sampler2D transformPalette; // palette of transforms
143243
+ uniform uvec2 splat_params; // splat texture width, num splats
143244
+
143245
+ uniform mat4 matrix_model;
143246
+ uniform mat4 matrix_viewProjection;
143247
+
143248
+ uniform uvec2 output_params; // output width, height
143249
+
143250
+ // 0: mask, 1: rect, 2: sphere
143251
+ uniform int mode;
143252
+
143253
+ // mask params
143254
+ uniform sampler2D mask; // mask in alpha channel
143255
+ uniform vec2 mask_params; // mask width, height
143256
+
143257
+ // rect params
143258
+ uniform vec4 rect_params; // rect x, y, width, height
143259
+
143260
+ // sphere params
143261
+ uniform vec4 sphere_params; // sphere x, y, z, radius
143262
+
143263
+ // box params
143264
+ uniform vec4 box_params; // box x, y, z
143265
+ uniform vec4 aabb_params; // len x, y, z
143266
+
143267
+ void main(void) {
143268
+ // calculate output id
143269
+ uvec2 outputUV = uvec2(gl_FragCoord);
143270
+ uint outputId = (outputUV.x + outputUV.y * output_params.x) * 4u;
143271
+
143272
+ vec4 clr = vec4(0.0);
143273
+
143274
+ for (uint i = 0u; i < 4u; i++) {
143275
+ uint id = outputId + i;
143276
+
143277
+ if (id >= splat_params.y) {
143278
+ continue;
143279
+ }
143280
+
143281
+ // calculate splatUV
143282
+ ivec2 splatUV = ivec2(
143283
+ int(id % splat_params.x),
143284
+ int(id / splat_params.x)
143285
+ );
143286
+
143287
+ // read splat center
143288
+ vec3 center = uintBitsToFloat(texelFetch(transformA, splatUV, 0).xyz);
143289
+
143290
+ // apply optional per-splat transform
143291
+ uint transformIndex = texelFetch(splatTransform, splatUV, 0).r;
143292
+ if (transformIndex > 0u) {
143293
+ // read transform matrix
143294
+ int u = int(transformIndex % 512u) * 3;
143295
+ int v = int(transformIndex / 512u);
143296
+
143297
+ mat3x4 t;
143298
+ t[0] = texelFetch(transformPalette, ivec2(u, v), 0);
143299
+ t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0);
143300
+ t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0);
143301
+
143302
+ center = vec4(center, 1.0) * t;
143303
+ }
143304
+
143305
+ // transform to clip space and discard if outside
143306
+ vec3 world = (matrix_model * vec4(center, 1.0)).xyz;
143307
+ vec4 clip = matrix_viewProjection * vec4(world, 1.0);
143308
+ vec3 ndc = clip.xyz / clip.w;
143309
+
143310
+ // skip offscreen fragments
143311
+ if (!any(greaterThan(abs(ndc), vec3(1.0)))) {
143312
+ if (mode == 0) {
143313
+ // select by mask
143314
+ ivec2 maskUV = ivec2((ndc.xy * vec2(0.5, -0.5) + 0.5) * mask_params);
143315
+ clr[i] = texelFetch(mask, maskUV, 0).a < 1.0 ? 0.0 : 1.0;
143316
+ } else if (mode == 1) {
143317
+ // select by rect
143318
+ clr[i] = all(greaterThan(ndc.xy * vec2(1.0, -1.0), rect_params.xy)) && all(lessThan(ndc.xy * vec2(1.0, -1.0), rect_params.zw)) ? 1.0 : 0.0;
143319
+ } else if (mode == 2) {
143320
+ // select by sphere
143321
+ clr[i] = length(world - sphere_params.xyz) < sphere_params.w ? 1.0 : 0.0;
143322
+ } else if (mode == 3) {
143323
+ // select by box
143324
+ vec3 relativePosition = world - box_params.xyz;
143325
+ bool isInsideCube = true;
143326
+ if (relativePosition.x < -aabb_params.x || relativePosition.x > aabb_params.x) {
143327
+ isInsideCube = false;
143328
+ }
143329
+ if (relativePosition.y < -aabb_params.y || relativePosition.y > aabb_params.y) {
143330
+ isInsideCube = false;
143331
+ }
143332
+ if (relativePosition.z < -aabb_params.z || relativePosition.z > aabb_params.z) {
143333
+ isInsideCube = false;
143334
+ }
143335
+ clr[i] = isInsideCube ? 1.0 : 0.0;
143336
+ }
143337
+ }
143338
+ }
143339
+
143340
+ gl_FragColor = clr;
143341
+ }
143342
+ `;
143343
+
143344
+ const vertexShader$4 = /* glsl */ `
143345
+ attribute vec2 vertex_position;
143346
+ void main(void) {
143347
+ gl_Position = vec4(vertex_position, 0.0, 1.0);
143348
+ }
143349
+ `;
143350
+ const fragmentShader$4 = /* glsl */ `
143351
+ uniform highp usampler2D transformA; // splat center x, y, z
143352
+ uniform highp usampler2D splatTransform; // transform palette index
143353
+ uniform sampler2D transformPalette; // palette of transforms
143354
+ uniform ivec2 splat_params; // splat texture width, num splats
143355
+
143356
+ void main(void) {
143357
+ // calculate output id
143358
+ ivec2 splatUV = ivec2(gl_FragCoord);
143359
+
143360
+ // skip if splat index is out of bounds
143361
+ if (splatUV.x + splatUV.y * splat_params.x >= splat_params.y) {
143362
+ discard;
143363
+ }
143364
+
143365
+ // read splat center
143366
+ vec3 center = uintBitsToFloat(texelFetch(transformA, splatUV, 0).xyz);
143367
+
143368
+ // apply optional per-splat transform
143369
+ uint transformIndex = texelFetch(splatTransform, splatUV, 0).r;
143370
+ if (transformIndex > 0u) {
143371
+ // read transform matrix
143372
+ int u = int(transformIndex % 512u) * 3;
143373
+ int v = int(transformIndex / 512u);
143374
+
143375
+ mat3x4 t;
143376
+ t[0] = texelFetch(transformPalette, ivec2(u, v), 0);
143377
+ t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0);
143378
+ t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0);
143379
+
143380
+ center = vec4(center, 1.0) * t;
143381
+ }
143382
+
143383
+ gl_FragColor = vec4(center, 0.0);
143384
+ }
143380
143385
  `;
143381
143386
 
143382
143387
  const v1 = new Vec3();
@@ -143413,18 +143418,18 @@ class DataProcessor {
143413
143418
  attributes: {
143414
143419
  vertex_position: SEMANTIC_POSITION
143415
143420
  },
143416
- vertexGLSL: `
143417
- attribute vec2 vertex_position;
143418
- void main(void) {
143419
- gl_Position = vec4(vertex_position, 0.0, 1.0);
143420
- }
143421
+ vertexGLSL: `
143422
+ attribute vec2 vertex_position;
143423
+ void main(void) {
143424
+ gl_Position = vec4(vertex_position, 0.0, 1.0);
143425
+ }
143421
143426
  `,
143422
- fragmentGLSL: `
143423
- uniform sampler2D colorTex;
143424
- void main(void) {
143425
- ivec2 texel = ivec2(gl_FragCoord.xy);
143426
- gl_FragColor = texelFetch(colorTex, texel, 0);
143427
- }
143427
+ fragmentGLSL: `
143428
+ uniform sampler2D colorTex;
143429
+ void main(void) {
143430
+ ivec2 texel = ivec2(gl_FragCoord.xy);
143431
+ gl_FragColor = texelFetch(colorTex, texel, 0);
143432
+ }
143428
143433
  `
143429
143434
  });
143430
143435
  // intersection test
@@ -144663,176 +144668,176 @@ class Camera extends Element$1 {
144663
144668
  }
144664
144669
  }
144665
144670
 
144666
- const vertexShader$3 = /* glsl*/ `
144667
- uniform vec3 near_origin;
144668
- uniform vec3 near_x;
144669
- uniform vec3 near_y;
144670
-
144671
- uniform vec3 far_origin;
144672
- uniform vec3 far_x;
144673
- uniform vec3 far_y;
144674
-
144675
- attribute vec2 vertex_position;
144676
-
144677
- varying vec3 worldFar;
144678
- varying vec3 worldNear;
144679
-
144680
- void main(void) {
144681
- gl_Position = vec4(vertex_position, 0.0, 1.0);
144682
-
144683
- vec2 p = vertex_position * 0.5 + 0.5;
144684
- worldNear = near_origin + near_x * p.x + near_y * p.y;
144685
- worldFar = far_origin + far_x * p.x + far_y * p.y;
144686
- }
144687
- `;
144688
- const fragmentShader$3 = /* glsl*/ `
144689
- uniform vec3 view_position;
144690
- uniform mat4 matrix_viewProjection;
144691
- uniform sampler2D blueNoiseTex32;
144692
-
144693
- uniform int plane; // 0: x (yz), 1: y (xz), 2: z (xy)
144694
-
144695
- vec4 planes[3] = vec4[3](
144696
- vec4(1.0, 0.0, 0.0, 0.0),
144697
- vec4(0.0, 1.0, 0.0, 0.0),
144698
- vec4(0.0, 0.0, 1.0, 0.0)
144699
- );
144700
-
144701
- vec3 colors[3] = vec3[3](
144702
- vec3(1.0, 0.2, 0.2),
144703
- vec3(0.2, 1.0, 0.2),
144704
- vec3(0.2, 0.2, 1.0)
144705
- );
144706
-
144707
- int axis0[3] = int[3](1, 0, 0);
144708
- int axis1[3] = int[3](2, 2, 1);
144709
-
144710
- varying vec3 worldNear;
144711
- varying vec3 worldFar;
144712
-
144713
- bool intersectPlane(inout float t, vec3 pos, vec3 dir, vec4 plane) {
144714
- float d = dot(dir, plane.xyz);
144715
- if (abs(d) < 1e-06) {
144716
- return false;
144717
- }
144718
-
144719
- float n = -(dot(pos, plane.xyz) + plane.w) / d;
144720
- if (n < 0.0) {
144721
- return false;
144722
- }
144723
-
144724
- t = n;
144725
-
144726
- return true;
144727
- }
144728
-
144729
- // https://bgolus.medium.com/the-best-darn-grid-shader-yet-727f9278b9d8#1e7c
144730
- float pristineGrid(in vec2 uv, in vec2 ddx, in vec2 ddy, vec2 lineWidth) {
144731
- vec2 uvDeriv = vec2(length(vec2(ddx.x, ddy.x)), length(vec2(ddx.y, ddy.y)));
144732
- bvec2 invertLine = bvec2(lineWidth.x > 0.5, lineWidth.y > 0.5);
144733
- vec2 targetWidth = vec2(
144734
- invertLine.x ? 1.0 - lineWidth.x : lineWidth.x,
144735
- invertLine.y ? 1.0 - lineWidth.y : lineWidth.y
144736
- );
144737
- vec2 drawWidth = clamp(targetWidth, uvDeriv, vec2(0.5));
144738
- vec2 lineAA = uvDeriv * 1.5;
144739
- vec2 gridUV = abs(fract(uv) * 2.0 - 1.0);
144740
- gridUV.x = invertLine.x ? gridUV.x : 1.0 - gridUV.x;
144741
- gridUV.y = invertLine.y ? gridUV.y : 1.0 - gridUV.y;
144742
- vec2 grid2 = smoothstep(drawWidth + lineAA, drawWidth - lineAA, gridUV);
144743
-
144744
- grid2 *= clamp(targetWidth / drawWidth, 0.0, 1.0);
144745
- grid2 = mix(grid2, targetWidth, clamp(uvDeriv * 2.0 - 1.0, 0.0, 1.0));
144746
- grid2.x = invertLine.x ? 1.0 - grid2.x : grid2.x;
144747
- grid2.y = invertLine.y ? 1.0 - grid2.y : grid2.y;
144748
-
144749
- return mix(grid2.x, 1.0, grid2.y);
144750
- }
144751
-
144752
- float calcDepth(vec3 p) {
144753
- vec4 v = matrix_viewProjection * vec4(p, 1.0);
144754
- return (v.z / v.w) * 0.5 + 0.5;
144755
- }
144756
-
144757
- bool writeDepth(float alpha) {
144758
- vec2 uv = fract(gl_FragCoord.xy / 32.0);
144759
- float noise = texture2DLod(blueNoiseTex32, uv, 0.0).y;
144760
- return alpha > noise;
144761
- }
144762
-
144763
- void main(void) {
144764
- vec3 p = worldNear;
144765
- vec3 v = normalize(worldFar - worldNear);
144766
-
144767
- // intersect ray with the world xz plane
144768
- float t;
144769
- if (!intersectPlane(t, p, v, planes[plane])) {
144770
- discard;
144771
- }
144772
-
144773
- // calculate grid intersection
144774
- vec3 worldPos = p + v * t;
144775
- vec2 pos = plane == 0 ? worldPos.yz : (plane == 1 ? worldPos.xz : worldPos.xy);
144776
- vec2 ddx = dFdx(pos);
144777
- vec2 ddy = dFdy(pos);
144778
-
144779
- float epsilon = 1.0 / 255.0;
144780
-
144781
- // calculate fade
144782
- float fade = 1.0 - smoothstep(400.0, 1000.0, length(worldPos - view_position));
144783
- if (fade < epsilon) {
144784
- discard;
144785
- }
144786
-
144787
- vec2 levelPos;
144788
- float levelSize;
144789
- float levelAlpha;
144790
-
144791
- // 10m grid with colored main axes
144792
- levelPos = pos * 0.1;
144793
- levelSize = 2.0 / 1000.0;
144794
- levelAlpha = pristineGrid(levelPos, ddx * 0.1, ddy * 0.1, vec2(levelSize)) * fade;
144795
- if (levelAlpha > epsilon) {
144796
- vec3 color;
144797
- vec2 loc = abs(levelPos);
144798
- if (loc.x < levelSize) {
144799
- if (loc.y < levelSize) {
144800
- color = vec3(1.0);
144801
- } else {
144802
- color = colors[axis1[plane]];
144803
- }
144804
- } else if (loc.y < levelSize) {
144805
- color = colors[axis0[plane]];
144806
- } else {
144807
- color = vec3(0.9);
144808
- }
144809
- gl_FragColor = vec4(color, levelAlpha);
144810
- gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(worldPos) : 1.0;
144811
- return;
144812
- }
144813
-
144814
- // 1m grid
144815
- levelPos = pos;
144816
- levelSize = 1.0 / 100.0;
144817
- levelAlpha = pristineGrid(levelPos, ddx, ddy, vec2(levelSize)) * fade;
144818
- if (levelAlpha > epsilon) {
144819
- gl_FragColor = vec4(vec3(0.7), levelAlpha);
144820
- gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(worldPos) : 1.0;
144821
- return;
144822
- }
144823
-
144824
- // 0.1m grid
144825
- levelPos = pos * 10.0;
144826
- levelSize = 1.0 / 100.0;
144827
- levelAlpha = pristineGrid(levelPos, ddx * 10.0, ddy * 10.0, vec2(levelSize)) * fade;
144828
- if (levelAlpha > epsilon) {
144829
- gl_FragColor = vec4(vec3(0.7), levelAlpha);
144830
- gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(worldPos) : 1.0;
144831
- return;
144832
- }
144833
-
144834
- discard;
144835
- }
144671
+ const vertexShader$3 = /* glsl*/ `
144672
+ uniform vec3 near_origin;
144673
+ uniform vec3 near_x;
144674
+ uniform vec3 near_y;
144675
+
144676
+ uniform vec3 far_origin;
144677
+ uniform vec3 far_x;
144678
+ uniform vec3 far_y;
144679
+
144680
+ attribute vec2 vertex_position;
144681
+
144682
+ varying vec3 worldFar;
144683
+ varying vec3 worldNear;
144684
+
144685
+ void main(void) {
144686
+ gl_Position = vec4(vertex_position, 0.0, 1.0);
144687
+
144688
+ vec2 p = vertex_position * 0.5 + 0.5;
144689
+ worldNear = near_origin + near_x * p.x + near_y * p.y;
144690
+ worldFar = far_origin + far_x * p.x + far_y * p.y;
144691
+ }
144692
+ `;
144693
+ const fragmentShader$3 = /* glsl*/ `
144694
+ uniform vec3 view_position;
144695
+ uniform mat4 matrix_viewProjection;
144696
+ uniform sampler2D blueNoiseTex32;
144697
+
144698
+ uniform int plane; // 0: x (yz), 1: y (xz), 2: z (xy)
144699
+
144700
+ vec4 planes[3] = vec4[3](
144701
+ vec4(1.0, 0.0, 0.0, 0.0),
144702
+ vec4(0.0, 1.0, 0.0, 0.0),
144703
+ vec4(0.0, 0.0, 1.0, 0.0)
144704
+ );
144705
+
144706
+ vec3 colors[3] = vec3[3](
144707
+ vec3(1.0, 0.2, 0.2),
144708
+ vec3(0.2, 1.0, 0.2),
144709
+ vec3(0.2, 0.2, 1.0)
144710
+ );
144711
+
144712
+ int axis0[3] = int[3](1, 0, 0);
144713
+ int axis1[3] = int[3](2, 2, 1);
144714
+
144715
+ varying vec3 worldNear;
144716
+ varying vec3 worldFar;
144717
+
144718
+ bool intersectPlane(inout float t, vec3 pos, vec3 dir, vec4 plane) {
144719
+ float d = dot(dir, plane.xyz);
144720
+ if (abs(d) < 1e-06) {
144721
+ return false;
144722
+ }
144723
+
144724
+ float n = -(dot(pos, plane.xyz) + plane.w) / d;
144725
+ if (n < 0.0) {
144726
+ return false;
144727
+ }
144728
+
144729
+ t = n;
144730
+
144731
+ return true;
144732
+ }
144733
+
144734
+ // https://bgolus.medium.com/the-best-darn-grid-shader-yet-727f9278b9d8#1e7c
144735
+ float pristineGrid(in vec2 uv, in vec2 ddx, in vec2 ddy, vec2 lineWidth) {
144736
+ vec2 uvDeriv = vec2(length(vec2(ddx.x, ddy.x)), length(vec2(ddx.y, ddy.y)));
144737
+ bvec2 invertLine = bvec2(lineWidth.x > 0.5, lineWidth.y > 0.5);
144738
+ vec2 targetWidth = vec2(
144739
+ invertLine.x ? 1.0 - lineWidth.x : lineWidth.x,
144740
+ invertLine.y ? 1.0 - lineWidth.y : lineWidth.y
144741
+ );
144742
+ vec2 drawWidth = clamp(targetWidth, uvDeriv, vec2(0.5));
144743
+ vec2 lineAA = uvDeriv * 1.5;
144744
+ vec2 gridUV = abs(fract(uv) * 2.0 - 1.0);
144745
+ gridUV.x = invertLine.x ? gridUV.x : 1.0 - gridUV.x;
144746
+ gridUV.y = invertLine.y ? gridUV.y : 1.0 - gridUV.y;
144747
+ vec2 grid2 = smoothstep(drawWidth + lineAA, drawWidth - lineAA, gridUV);
144748
+
144749
+ grid2 *= clamp(targetWidth / drawWidth, 0.0, 1.0);
144750
+ grid2 = mix(grid2, targetWidth, clamp(uvDeriv * 2.0 - 1.0, 0.0, 1.0));
144751
+ grid2.x = invertLine.x ? 1.0 - grid2.x : grid2.x;
144752
+ grid2.y = invertLine.y ? 1.0 - grid2.y : grid2.y;
144753
+
144754
+ return mix(grid2.x, 1.0, grid2.y);
144755
+ }
144756
+
144757
+ float calcDepth(vec3 p) {
144758
+ vec4 v = matrix_viewProjection * vec4(p, 1.0);
144759
+ return (v.z / v.w) * 0.5 + 0.5;
144760
+ }
144761
+
144762
+ bool writeDepth(float alpha) {
144763
+ vec2 uv = fract(gl_FragCoord.xy / 32.0);
144764
+ float noise = texture2DLod(blueNoiseTex32, uv, 0.0).y;
144765
+ return alpha > noise;
144766
+ }
144767
+
144768
+ void main(void) {
144769
+ vec3 p = worldNear;
144770
+ vec3 v = normalize(worldFar - worldNear);
144771
+
144772
+ // intersect ray with the world xz plane
144773
+ float t;
144774
+ if (!intersectPlane(t, p, v, planes[plane])) {
144775
+ discard;
144776
+ }
144777
+
144778
+ // calculate grid intersection
144779
+ vec3 worldPos = p + v * t;
144780
+ vec2 pos = plane == 0 ? worldPos.yz : (plane == 1 ? worldPos.xz : worldPos.xy);
144781
+ vec2 ddx = dFdx(pos);
144782
+ vec2 ddy = dFdy(pos);
144783
+
144784
+ float epsilon = 1.0 / 255.0;
144785
+
144786
+ // calculate fade
144787
+ float fade = 1.0 - smoothstep(400.0, 1000.0, length(worldPos - view_position));
144788
+ if (fade < epsilon) {
144789
+ discard;
144790
+ }
144791
+
144792
+ vec2 levelPos;
144793
+ float levelSize;
144794
+ float levelAlpha;
144795
+
144796
+ // 10m grid with colored main axes
144797
+ levelPos = pos * 0.1;
144798
+ levelSize = 2.0 / 1000.0;
144799
+ levelAlpha = pristineGrid(levelPos, ddx * 0.1, ddy * 0.1, vec2(levelSize)) * fade;
144800
+ if (levelAlpha > epsilon) {
144801
+ vec3 color;
144802
+ vec2 loc = abs(levelPos);
144803
+ if (loc.x < levelSize) {
144804
+ if (loc.y < levelSize) {
144805
+ color = vec3(1.0);
144806
+ } else {
144807
+ color = colors[axis1[plane]];
144808
+ }
144809
+ } else if (loc.y < levelSize) {
144810
+ color = colors[axis0[plane]];
144811
+ } else {
144812
+ color = vec3(0.9);
144813
+ }
144814
+ gl_FragColor = vec4(color, levelAlpha);
144815
+ gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(worldPos) : 1.0;
144816
+ return;
144817
+ }
144818
+
144819
+ // 1m grid
144820
+ levelPos = pos;
144821
+ levelSize = 1.0 / 100.0;
144822
+ levelAlpha = pristineGrid(levelPos, ddx, ddy, vec2(levelSize)) * fade;
144823
+ if (levelAlpha > epsilon) {
144824
+ gl_FragColor = vec4(vec3(0.7), levelAlpha);
144825
+ gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(worldPos) : 1.0;
144826
+ return;
144827
+ }
144828
+
144829
+ // 0.1m grid
144830
+ levelPos = pos * 10.0;
144831
+ levelSize = 1.0 / 100.0;
144832
+ levelAlpha = pristineGrid(levelPos, ddx * 10.0, ddy * 10.0, vec2(levelSize)) * fade;
144833
+ if (levelAlpha > epsilon) {
144834
+ gl_FragColor = vec4(vec3(0.7), levelAlpha);
144835
+ gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(worldPos) : 1.0;
144836
+ return;
144837
+ }
144838
+
144839
+ discard;
144840
+ }
144836
144841
  `;
144837
144842
 
144838
144843
  const resolve = (scope, values) => {
@@ -144903,36 +144908,36 @@ class InfiniteGrid extends Element$1 {
144903
144908
  }
144904
144909
  }
144905
144910
 
144906
- const vertexShader$2 = /* glsl*/ `
144907
- attribute vec2 vertex_position;
144908
- void main(void) {
144909
- gl_Position = vec4(vertex_position, 0.0, 1.0);
144910
- }
144911
- `;
144912
- const fragmentShader$2 = /* glsl*/ `
144913
- uniform sampler2D outlineTexture;
144914
- uniform float alphaCutoff;
144915
- uniform vec4 clr;
144916
-
144917
- void main(void) {
144918
- ivec2 texel = ivec2(gl_FragCoord.xy);
144919
-
144920
- // skip solid pixels
144921
- if (texelFetch(outlineTexture, texel, 0).a > alphaCutoff) {
144922
- discard;
144923
- }
144924
-
144925
- for (int x = -2; x <= 2; x++) {
144926
- for (int y = -2; y <= 2; y++) {
144927
- if ((x != 0) && (y != 0) && (texelFetch(outlineTexture, texel + ivec2(x, y), 0).a > alphaCutoff)) {
144928
- gl_FragColor = clr;
144929
- return;
144930
- }
144931
- }
144932
- }
144933
-
144934
- discard;
144935
- }
144911
+ const vertexShader$2 = /* glsl*/ `
144912
+ attribute vec2 vertex_position;
144913
+ void main(void) {
144914
+ gl_Position = vec4(vertex_position, 0.0, 1.0);
144915
+ }
144916
+ `;
144917
+ const fragmentShader$2 = /* glsl*/ `
144918
+ uniform sampler2D outlineTexture;
144919
+ uniform float alphaCutoff;
144920
+ uniform vec4 clr;
144921
+
144922
+ void main(void) {
144923
+ ivec2 texel = ivec2(gl_FragCoord.xy);
144924
+
144925
+ // skip solid pixels
144926
+ if (texelFetch(outlineTexture, texel, 0).a > alphaCutoff) {
144927
+ discard;
144928
+ }
144929
+
144930
+ for (int x = -2; x <= 2; x++) {
144931
+ for (int y = -2; y <= 2; y++) {
144932
+ if ((x != 0) && (y != 0) && (texelFetch(outlineTexture, texel + ivec2(x, y), 0).a > alphaCutoff)) {
144933
+ gl_FragColor = clr;
144934
+ return;
144935
+ }
144936
+ }
144937
+ }
144938
+
144939
+ discard;
144940
+ }
144936
144941
  `;
144937
144942
 
144938
144943
  class Outline extends Element$1 {
@@ -145250,72 +145255,72 @@ class SceneState {
145250
145255
  }
145251
145256
  }
145252
145257
 
145253
- const vertexShader$1 = /* glsl */ `
145254
- attribute uint vertex_id;
145255
-
145256
- uniform mat4 matrix_model;
145257
- uniform mat4 matrix_viewProjection;
145258
-
145259
- uniform sampler2D splatState;
145260
- uniform highp usampler2D splatPosition;
145261
- uniform highp usampler2D splatTransform; // per-splat index into transform palette
145262
- uniform sampler2D transformPalette; // palette of transform matrices
145263
-
145264
- uniform uvec2 texParams;
145265
-
145266
- uniform float splatSize;
145267
- uniform vec4 selectedClr;
145268
- uniform vec4 unselectedClr;
145269
-
145270
- varying vec4 varying_color;
145271
-
145272
- // calculate the current splat index and uv
145273
- ivec2 calcSplatUV(uint index, uint width) {
145274
- return ivec2(int(index % width), int(index / width));
145275
- }
145276
-
145277
- void main(void) {
145278
- ivec2 splatUV = calcSplatUV(vertex_id, texParams.x);
145279
- uint splatState = uint(texelFetch(splatState, splatUV, 0).r * 255.0);
145280
-
145281
- if ((splatState & 6u) != 0u) {
145282
- // deleted or locked (4 or 2)
145283
- gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
145284
- gl_PointSize = 0.0;
145285
- } else {
145286
- mat4 model = matrix_model;
145287
-
145288
- // handle per-splat transform
145289
- uint transformIndex = texelFetch(splatTransform, splatUV, 0).r;
145290
- if (transformIndex > 0u) {
145291
- // read transform matrix
145292
- int u = int(transformIndex % 512u) * 3;
145293
- int v = int(transformIndex / 512u);
145294
-
145295
- mat4 t;
145296
- t[0] = texelFetch(transformPalette, ivec2(u, v), 0);
145297
- t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0);
145298
- t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0);
145299
- t[3] = vec4(0.0, 0.0, 0.0, 1.0);
145300
-
145301
- model = matrix_model * transpose(t);
145302
- }
145303
-
145304
- varying_color = (splatState == 1u) ? selectedClr : unselectedClr;
145305
-
145306
- vec3 center = uintBitsToFloat(texelFetch(splatPosition, splatUV, 0).xyz);
145307
-
145308
- gl_Position = matrix_viewProjection * model * vec4(center, 1.0);
145309
- gl_PointSize = splatSize;
145310
- }
145311
- }
145312
- `;
145313
- const fragmentShader$1 = /* glsl */ `
145314
- varying vec4 varying_color;
145315
-
145316
- void main(void) {
145317
- gl_FragColor = varying_color;
145318
- }
145258
+ const vertexShader$1 = /* glsl */ `
145259
+ attribute uint vertex_id;
145260
+
145261
+ uniform mat4 matrix_model;
145262
+ uniform mat4 matrix_viewProjection;
145263
+
145264
+ uniform sampler2D splatState;
145265
+ uniform highp usampler2D splatPosition;
145266
+ uniform highp usampler2D splatTransform; // per-splat index into transform palette
145267
+ uniform sampler2D transformPalette; // palette of transform matrices
145268
+
145269
+ uniform uvec2 texParams;
145270
+
145271
+ uniform float splatSize;
145272
+ uniform vec4 selectedClr;
145273
+ uniform vec4 unselectedClr;
145274
+
145275
+ varying vec4 varying_color;
145276
+
145277
+ // calculate the current splat index and uv
145278
+ ivec2 calcSplatUV(uint index, uint width) {
145279
+ return ivec2(int(index % width), int(index / width));
145280
+ }
145281
+
145282
+ void main(void) {
145283
+ ivec2 splatUV = calcSplatUV(vertex_id, texParams.x);
145284
+ uint splatState = uint(texelFetch(splatState, splatUV, 0).r * 255.0);
145285
+
145286
+ if ((splatState & 6u) != 0u) {
145287
+ // deleted or locked (4 or 2)
145288
+ gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
145289
+ gl_PointSize = 0.0;
145290
+ } else {
145291
+ mat4 model = matrix_model;
145292
+
145293
+ // handle per-splat transform
145294
+ uint transformIndex = texelFetch(splatTransform, splatUV, 0).r;
145295
+ if (transformIndex > 0u) {
145296
+ // read transform matrix
145297
+ int u = int(transformIndex % 512u) * 3;
145298
+ int v = int(transformIndex / 512u);
145299
+
145300
+ mat4 t;
145301
+ t[0] = texelFetch(transformPalette, ivec2(u, v), 0);
145302
+ t[1] = texelFetch(transformPalette, ivec2(u + 1, v), 0);
145303
+ t[2] = texelFetch(transformPalette, ivec2(u + 2, v), 0);
145304
+ t[3] = vec4(0.0, 0.0, 0.0, 1.0);
145305
+
145306
+ model = matrix_model * transpose(t);
145307
+ }
145308
+
145309
+ varying_color = (splatState == 1u) ? selectedClr : unselectedClr;
145310
+
145311
+ vec3 center = uintBitsToFloat(texelFetch(splatPosition, splatUV, 0).xyz);
145312
+
145313
+ gl_Position = matrix_viewProjection * model * vec4(center, 1.0);
145314
+ gl_PointSize = splatSize;
145315
+ }
145316
+ }
145317
+ `;
145318
+ const fragmentShader$1 = /* glsl */ `
145319
+ varying vec4 varying_color;
145320
+
145321
+ void main(void) {
145322
+ gl_FragColor = varying_color;
145323
+ }
145319
145324
  `;
145320
145325
 
145321
145326
  class SplatOverlay extends Element$1 {
@@ -145404,19 +145409,19 @@ class SplatOverlay extends Element$1 {
145404
145409
  }
145405
145410
  }
145406
145411
 
145407
- const vertexShader = /* glsl*/ `
145408
- attribute vec2 vertex_position;
145409
- void main(void) {
145410
- gl_Position = vec4(vertex_position, 0.0, 1.0);
145411
- }
145412
+ const vertexShader = /* glsl*/ `
145413
+ attribute vec2 vertex_position;
145414
+ void main(void) {
145415
+ gl_Position = vec4(vertex_position, 0.0, 1.0);
145416
+ }
145412
145417
  `;
145413
- const fragmentShader = /* glsl*/ `
145414
- uniform sampler2D blitTexture;
145415
- void main(void) {
145416
- ivec2 texel = ivec2(gl_FragCoord.xy);
145417
-
145418
- gl_FragColor = texelFetch(blitTexture, texel, 0);
145419
- }
145418
+ const fragmentShader = /* glsl*/ `
145419
+ uniform sampler2D blitTexture;
145420
+ void main(void) {
145421
+ ivec2 texel = ivec2(gl_FragCoord.xy);
145422
+
145423
+ gl_FragColor = texelFetch(blitTexture, texel, 0);
145424
+ }
145420
145425
  `;
145421
145426
 
145422
145427
  class Underlay extends Element$1 {
@@ -147693,6 +147698,7 @@ class SplatViewerCore {
147693
147698
  };
147694
147699
  this.enableStats = false;
147695
147700
  this.autoFocus = true;
147701
+ this.previewMode = false;
147696
147702
  this.isLoading = false;
147697
147703
  this.hasModel = false;
147698
147704
  this.error = null;
@@ -147745,6 +147751,11 @@ class SplatViewerCore {
147745
147751
  this.canvas = options.canvas || null;
147746
147752
  this.enableStats = options.enableStats || false;
147747
147753
  this.autoFocus = options.autoFocus !== false;
147754
+ this.previewMode = options.previewMode || false;
147755
+ // In preview mode, always enable auto-focus
147756
+ if (this.previewMode) {
147757
+ this.autoFocus = true;
147758
+ }
147748
147759
  this._navigationCubeConfig = options.navigationCube || null;
147749
147760
  if (options.onStatsUpdate !== undefined) {
147750
147761
  this._onStatsUpdate = options.onStatsUpdate;
@@ -147775,11 +147786,20 @@ class SplatViewerCore {
147775
147786
  const emitEvent = (type, detail) => {
147776
147787
  this.emit({ type, detail });
147777
147788
  };
147778
- this._supersplat = new SupersplatAdapter(this.canvas, this._navigationCubeConfig, emitEvent);
147789
+ this._supersplat = new SupersplatAdapter(this.canvas,
147790
+ // Disable navigation cube in preview mode
147791
+ this.previewMode ? null : this._navigationCubeConfig, emitEvent);
147779
147792
  this._supersplatReady = this._supersplat.init();
147780
147793
  this._supersplatReady
147781
147794
  ?.then(() => {
147782
- this._setupFlyCameraForSupersplat();
147795
+ // Disable camera controls in preview mode
147796
+ if (this.previewMode && this._supersplat) {
147797
+ this._supersplat.setCameraControlsEnabled?.(false);
147798
+ }
147799
+ // Only set up fly camera if not in preview mode
147800
+ if (!this.previewMode) {
147801
+ this._setupFlyCameraForSupersplat();
147802
+ }
147783
147803
  })
147784
147804
  .catch(error => {
147785
147805
  console.error('SplatViewerCore.init: Failed to set up fly camera for supersplat path', error);
@@ -147818,7 +147838,9 @@ class SplatViewerCore {
147818
147838
  // SuperSplat's PCApp omits ScriptComponentSystem, so `addComponent('script')`
147819
147839
  // will not produce `camera.script.create()`. We keep the attempt (in case
147820
147840
  // the underlying app changes), but also support a controller-based fallback.
147821
- if (cameraAny && !cameraAny.script && typeof cameraAny.addComponent === 'function') {
147841
+ if (cameraAny &&
147842
+ !cameraAny.script &&
147843
+ typeof cameraAny.addComponent === 'function') {
147822
147844
  try {
147823
147845
  cameraAny.addComponent('script');
147824
147846
  }
@@ -147844,7 +147866,9 @@ class SplatViewerCore {
147844
147866
  // Prefer script-based fly when available; fallback to controller otherwise.
147845
147867
  const canCreateScript = typeof cameraAny?.script?.create === 'function';
147846
147868
  if (canCreateScript) {
147847
- const created = cameraAny.script.create('flyCamera', { attributes: flyAttributes });
147869
+ const created = cameraAny.script.create('flyCamera', {
147870
+ attributes: flyAttributes,
147871
+ });
147848
147872
  this._fly = created;
147849
147873
  if (this._fly) {
147850
147874
  ;
@@ -149708,6 +149732,11 @@ class SplatViewerCore {
149708
149732
  // Camera Mode / Fly Camera API
149709
149733
  // ==========================================
149710
149734
  setCameraMode(mode) {
149735
+ // Prevent camera mode changes in preview mode
149736
+ if (this.previewMode) {
149737
+ console.warn('SplatViewerCore.setCameraMode: Camera controls are disabled in preview mode');
149738
+ return;
149739
+ }
149711
149740
  // supersplat-core path: manage mode switching explicitly (camera entity is updated by supersplat-core each frame)
149712
149741
  if (this._supersplat) {
149713
149742
  const prev = this._cameraMode;
@@ -149737,7 +149766,9 @@ class SplatViewerCore {
149737
149766
  try {
149738
149767
  const pos = this.entities.camera?.getPosition?.();
149739
149768
  if (pos) {
149740
- const posVec = pos.clone ? pos.clone() : new Vec3(pos.x || 0, pos.y || 0, pos.z || 0);
149769
+ const posVec = pos.clone
149770
+ ? pos.clone()
149771
+ : new Vec3(pos.x || 0, pos.y || 0, pos.z || 0);
149741
149772
  this.entities.camera?.setPosition?.(posVec);
149742
149773
  }
149743
149774
  const euler = this.entities.camera?.getEulerAngles?.();
@@ -149960,8 +149991,8 @@ class SplatViewerCore {
149960
149991
  panSensitivity: 1.0,
149961
149992
  zoomSensitivity: 0.1,
149962
149993
  };
149963
- // Add navigation cube configuration if available
149964
- if (this._navigationCubeConfig) {
149994
+ // Add navigation cube configuration if available (but not in preview mode)
149995
+ if (this._navigationCubeConfig && !this.previewMode) {
149965
149996
  orbitAttributes.enableNavigationCube =
149966
149997
  this._navigationCubeConfig.enabled || false;
149967
149998
  this.entities.camera._navigationCubeConfig =
@@ -149976,48 +150007,57 @@ class SplatViewerCore {
149976
150007
  detail: { type: interactionType },
149977
150008
  });
149978
150009
  };
150010
+ // Disable camera controls in preview mode
150011
+ if (this.previewMode && this._orbit) {
150012
+ const orbitAny = this._orbit;
150013
+ if (typeof orbitAny.setEnabled === 'function') {
150014
+ orbitAny.setEnabled(false);
150015
+ }
150016
+ }
149979
150017
  this.entities.camera.setPosition(0, 0, 10);
149980
150018
  this.entities.camera.lookAt(Vec3.ZERO);
149981
150019
  // ==============================
149982
- // Setup fly camera (disabled by default)
150020
+ // Setup fly camera (disabled by default, skipped in preview mode)
149983
150021
  // ==============================
149984
- try {
149985
- registerFlyCameraScript();
149986
- // Ensure script component exists (created above)
149987
- const flyAttributes = {
149988
- moveSpeed: DEFAULT_FLY_CAMERA_CONFIG.moveSpeed,
149989
- fastSpeedMultiplier: DEFAULT_FLY_CAMERA_CONFIG.fastSpeedMultiplier,
149990
- slowSpeedMultiplier: DEFAULT_FLY_CAMERA_CONFIG.slowSpeedMultiplier,
149991
- lookSensitivity: DEFAULT_FLY_CAMERA_CONFIG.lookSensitivity,
149992
- invertY: DEFAULT_FLY_CAMERA_CONFIG.invertY,
149993
- keyBindings: DEFAULT_FLY_CAMERA_CONFIG.keyBindings,
149994
- smoothing: DEFAULT_FLY_CAMERA_CONFIG.smoothing,
149995
- friction: DEFAULT_FLY_CAMERA_CONFIG.friction,
149996
- enableCollision: DEFAULT_FLY_CAMERA_CONFIG.enableCollision,
149997
- minHeight: DEFAULT_FLY_CAMERA_CONFIG.minHeight,
149998
- maxHeight: DEFAULT_FLY_CAMERA_CONFIG.maxHeight,
149999
- };
150000
- this._fly = this.entities.camera.script.create('flyCamera', {
150001
- attributes: flyAttributes,
150002
- });
150003
- // Wire event emission to core
150004
- if (this._fly) {
150005
- ;
150006
- this._fly.emitFlyEvent = (type, detail) => {
150007
- this.emit({ type: type, detail });
150022
+ if (!this.previewMode) {
150023
+ try {
150024
+ registerFlyCameraScript();
150025
+ // Ensure script component exists (created above)
150026
+ const flyAttributes = {
150027
+ moveSpeed: DEFAULT_FLY_CAMERA_CONFIG.moveSpeed,
150028
+ fastSpeedMultiplier: DEFAULT_FLY_CAMERA_CONFIG.fastSpeedMultiplier,
150029
+ slowSpeedMultiplier: DEFAULT_FLY_CAMERA_CONFIG.slowSpeedMultiplier,
150030
+ lookSensitivity: DEFAULT_FLY_CAMERA_CONFIG.lookSensitivity,
150031
+ invertY: DEFAULT_FLY_CAMERA_CONFIG.invertY,
150032
+ keyBindings: DEFAULT_FLY_CAMERA_CONFIG.keyBindings,
150033
+ smoothing: DEFAULT_FLY_CAMERA_CONFIG.smoothing,
150034
+ friction: DEFAULT_FLY_CAMERA_CONFIG.friction,
150035
+ enableCollision: DEFAULT_FLY_CAMERA_CONFIG.enableCollision,
150036
+ minHeight: DEFAULT_FLY_CAMERA_CONFIG.minHeight,
150037
+ maxHeight: DEFAULT_FLY_CAMERA_CONFIG.maxHeight,
150008
150038
  };
150039
+ this._fly = this.entities.camera.script.create('flyCamera', {
150040
+ attributes: flyAttributes,
150041
+ });
150042
+ // Wire event emission to core
150043
+ if (this._fly) {
150044
+ ;
150045
+ this._fly.emitFlyEvent = (type, detail) => {
150046
+ this.emit({ type: type, detail });
150047
+ };
150048
+ }
150049
+ // Deactivate fly by default; orbit is the initial mode
150050
+ if (this._fly?.deactivate) {
150051
+ this._fly.deactivate();
150052
+ }
150053
+ // Initialize camera mode manager
150054
+ this._cameraModeManager = new CameraModeManager(this.app, this.entities.camera, this._orbit, this._fly, (eventType, detail) => {
150055
+ this.emit({ type: eventType, detail });
150056
+ }, 'orbit');
150009
150057
  }
150010
- // Deactivate fly by default; orbit is the initial mode
150011
- if (this._fly?.deactivate) {
150012
- this._fly.deactivate();
150058
+ catch (e) {
150059
+ console.warn('Failed to set up fly camera', e);
150013
150060
  }
150014
- // Initialize camera mode manager
150015
- this._cameraModeManager = new CameraModeManager(this.app, this.entities.camera, this._orbit, this._fly, (eventType, detail) => {
150016
- this.emit({ type: eventType, detail });
150017
- }, 'orbit');
150018
- }
150019
- catch (e) {
150020
- console.warn('Failed to set up fly camera', e);
150021
150061
  }
150022
150062
  }
150023
150063
  _setupStats() {
@@ -150262,6 +150302,7 @@ class SplatViewerElement extends HTMLElement {
150262
150302
  'enable-stats',
150263
150303
  'auto-focus',
150264
150304
  'max-splats',
150305
+ 'preview-mode',
150265
150306
  'camera-position',
150266
150307
  'camera-target',
150267
150308
  'orbit-sensitivity',
@@ -150292,6 +150333,9 @@ class SplatViewerElement extends HTMLElement {
150292
150333
  get autoFocus() {
150293
150334
  return this.hasAttribute('auto-focus');
150294
150335
  }
150336
+ get previewMode() {
150337
+ return this.hasAttribute('preview-mode');
150338
+ }
150295
150339
  get maxSplats() {
150296
150340
  return this.getAttribute('max-splats');
150297
150341
  }
@@ -150369,6 +150413,14 @@ class SplatViewerElement extends HTMLElement {
150369
150413
  this.removeAttribute('auto-focus');
150370
150414
  }
150371
150415
  }
150416
+ set previewMode(value) {
150417
+ if (value) {
150418
+ this.setAttribute('preview-mode', '');
150419
+ }
150420
+ else {
150421
+ this.removeAttribute('preview-mode');
150422
+ }
150423
+ }
150372
150424
  set maxSplats(value) {
150373
150425
  if (value === null) {
150374
150426
  this.removeAttribute('max-splats');
@@ -150550,6 +150602,7 @@ class SplatViewerElement extends HTMLElement {
150550
150602
  return value.length > 0;
150551
150603
  case 'enable-stats':
150552
150604
  case 'auto-focus':
150605
+ case 'preview-mode':
150553
150606
  case 'enable-navigation-cube':
150554
150607
  // Boolean attributes - any value is valid
150555
150608
  return true;
@@ -151496,7 +151549,7 @@ class SplatViewerElement extends HTMLElement {
151496
151549
  if (!this._core) {
151497
151550
  throw new Error('SplatViewerElement: Core not initialized. Call connectedCallback first.');
151498
151551
  }
151499
- return this._core.selectSplatsInSphere(center, radius, modelId, addToSelection);
151552
+ return this._core.selectSplatsInSphere(new Vec3(center.x, center.y, center.z), radius, modelId, addToSelection);
151500
151553
  }
151501
151554
  clearSplatSelection() {
151502
151555
  if (!this._core) {