@d5techs/3dgs-lib 1.4.5 → 1.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/3dgs-lib.js CHANGED
@@ -439,7 +439,7 @@ class Camera {
439
439
  // 45度
440
440
  __publicField(this, "aspect", 1);
441
441
  __publicField(this, "near", 0.01);
442
- __publicField(this, "far", 9e3);
442
+ __publicField(this, "far", 1e5);
443
443
  // 矩阵
444
444
  __publicField(this, "viewMatrix", new Float32Array(16));
445
445
  __publicField(this, "projectionMatrix", new Float32Array(16));
@@ -4269,7 +4269,7 @@ function transformSHCoeffsYZSwap$1(sh, base, perChannel) {
4269
4269
  for (let ch = 0; ch < 3; ch++) {
4270
4270
  const a = sh[base + ch];
4271
4271
  const b = sh[base + 3 + ch];
4272
- sh[base + ch] = -b;
4272
+ sh[base + ch] = b;
4273
4273
  sh[base + 3 + ch] = -a;
4274
4274
  }
4275
4275
  }
@@ -4280,8 +4280,8 @@ function transformSHCoeffsYZSwap$1(sh, base, perChannel) {
4280
4280
  const g2 = sh[base + 15 + ch];
4281
4281
  const g3 = sh[base + 18 + ch];
4282
4282
  const g4 = sh[base + 21 + ch];
4283
- sh[base + 9 + ch] = -g3;
4284
- sh[base + 12 + ch] = g1;
4283
+ sh[base + 9 + ch] = g3;
4284
+ sh[base + 12 + ch] = -g1;
4285
4285
  sh[base + 15 + ch] = -0.5 * g2 - SQRT3_2 * g4;
4286
4286
  sh[base + 18 + ch] = -g0;
4287
4287
  sh[base + 21 + ch] = -SQRT3_2 * g2 + 0.5 * g4;
@@ -4299,9 +4299,9 @@ function transformSHCoeffsYZSwap$1(sh, base, perChannel) {
4299
4299
  const g4 = sh[base + 36 + ch];
4300
4300
  const g5 = sh[base + 39 + ch];
4301
4301
  const g6 = sh[base + 42 + ch];
4302
- sh[base + 24 + ch] = A * g3 - B * g5;
4303
- sh[base + 27 + ch] = g1;
4304
- sh[base + 30 + ch] = B * g3 + A * g5;
4302
+ sh[base + 24 + ch] = -A * g3 + B * g5;
4303
+ sh[base + 27 + ch] = -g1;
4304
+ sh[base + 30 + ch] = -B * g3 - A * g5;
4305
4305
  sh[base + 33 + ch] = A * g0 + B * g2;
4306
4306
  sh[base + 36 + ch] = -0.25 * g4 - P * g6;
4307
4307
  sh[base + 39 + ch] = -B * g0 + A * g2;
@@ -4539,13 +4539,13 @@ async function loadPLY(url, options = {}) {
4539
4539
  transformSHCoeffsYZSwap$1(shRestBuffer, shOffset, perChannel);
4540
4540
  }
4541
4541
  splats[i] = {
4542
- mean: swapYZ ? [x, z, y] : [x, y, z],
4542
+ mean: swapYZ ? [x, z, -y] : [x, y, z],
4543
4543
  scale: swapYZ ? [scale_0, scale_2, scale_1] : [scale_0, scale_1, scale_2],
4544
4544
  rotation: swapYZ ? [
4545
- -rot_0 * qnorm,
4545
+ rot_0 * qnorm,
4546
4546
  rot_1 * qnorm,
4547
4547
  rot_3 * qnorm,
4548
- rot_2 * qnorm
4548
+ -rot_2 * qnorm
4549
4549
  ] : [
4550
4550
  rot_0 * qnorm,
4551
4551
  rot_1 * qnorm,
@@ -4583,7 +4583,7 @@ function transformSHCoeffsYZSwap(sh, base, perChannel) {
4583
4583
  for (let ch = 0; ch < 3; ch++) {
4584
4584
  const a = sh[base + ch];
4585
4585
  const b = sh[base + 3 + ch];
4586
- sh[base + ch] = -b;
4586
+ sh[base + ch] = b;
4587
4587
  sh[base + 3 + ch] = -a;
4588
4588
  }
4589
4589
  }
@@ -4594,8 +4594,8 @@ function transformSHCoeffsYZSwap(sh, base, perChannel) {
4594
4594
  const g2 = sh[base + 15 + ch];
4595
4595
  const g3 = sh[base + 18 + ch];
4596
4596
  const g4 = sh[base + 21 + ch];
4597
- sh[base + 9 + ch] = -g3;
4598
- sh[base + 12 + ch] = g1;
4597
+ sh[base + 9 + ch] = g3;
4598
+ sh[base + 12 + ch] = -g1;
4599
4599
  sh[base + 15 + ch] = -0.5 * g2 - SQRT3_2 * g4;
4600
4600
  sh[base + 18 + ch] = -g0;
4601
4601
  sh[base + 21 + ch] = -SQRT3_2 * g2 + 0.5 * g4;
@@ -4613,9 +4613,9 @@ function transformSHCoeffsYZSwap(sh, base, perChannel) {
4613
4613
  const g4 = sh[base + 36 + ch];
4614
4614
  const g5 = sh[base + 39 + ch];
4615
4615
  const g6 = sh[base + 42 + ch];
4616
- sh[base + 24 + ch] = A * g3 - B * g5;
4617
- sh[base + 27 + ch] = g1;
4618
- sh[base + 30 + ch] = B * g3 + A * g5;
4616
+ sh[base + 24 + ch] = -A * g3 + B * g5;
4617
+ sh[base + 27 + ch] = -g1;
4618
+ sh[base + 30 + ch] = -B * g3 - A * g5;
4619
4619
  sh[base + 33 + ch] = A * g0 + B * g2;
4620
4620
  sh[base + 36 + ch] = -0.25 * g4 - P * g6;
4621
4621
  sh[base + 39 + ch] = -B * g0 + A * g2;
@@ -4910,7 +4910,7 @@ async function parsePLYBuffer(buffer, options = {}) {
4910
4910
  const pz = offsets.z >= 0 ? readProperty(dataView, base + offsets.z, types.z, littleEndian) : 0;
4911
4911
  positions[outputIdx * 3 + 0] = px;
4912
4912
  positions[outputIdx * 3 + 1] = swapYZ ? pz : py;
4913
- positions[outputIdx * 3 + 2] = swapYZ ? py : pz;
4913
+ positions[outputIdx * 3 + 2] = swapYZ ? -py : pz;
4914
4914
  const sx = offsets.scale_0 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_0, types.scale_0, littleEndian)) : 1;
4915
4915
  const sy = offsets.scale_1 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_1, types.scale_1, littleEndian)) : 1;
4916
4916
  const sz = offsets.scale_2 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_2, types.scale_2, littleEndian)) : 1;
@@ -4924,10 +4924,10 @@ async function parsePLYBuffer(buffer, options = {}) {
4924
4924
  const qlen = Math.sqrt(rot_0 * rot_0 + rot_1 * rot_1 + rot_2 * rot_2 + rot_3 * rot_3);
4925
4925
  const qnorm = qlen > 0 ? 1 / qlen : 1;
4926
4926
  if (swapYZ) {
4927
- rotations[outputIdx * 4 + 0] = -rot_0 * qnorm;
4927
+ rotations[outputIdx * 4 + 0] = rot_0 * qnorm;
4928
4928
  rotations[outputIdx * 4 + 1] = rot_1 * qnorm;
4929
4929
  rotations[outputIdx * 4 + 2] = rot_3 * qnorm;
4930
- rotations[outputIdx * 4 + 3] = rot_2 * qnorm;
4930
+ rotations[outputIdx * 4 + 3] = -rot_2 * qnorm;
4931
4931
  } else {
4932
4932
  rotations[outputIdx * 4 + 0] = rot_0 * qnorm;
4933
4933
  rotations[outputIdx * 4 + 1] = rot_1 * qnorm;
@@ -5585,8 +5585,16 @@ async function decodeWebP(bytes) {
5585
5585
  });
5586
5586
  const w = bitmap.width;
5587
5587
  const h = bitmap.height;
5588
- const canvas = new OffscreenCanvas(w, h);
5589
- const ctx = canvas.getContext("2d");
5588
+ let ctx;
5589
+ if (typeof OffscreenCanvas !== "undefined") {
5590
+ const oc = new OffscreenCanvas(w, h);
5591
+ ctx = oc.getContext("2d");
5592
+ } else {
5593
+ const hc = document.createElement("canvas");
5594
+ hc.width = w;
5595
+ hc.height = h;
5596
+ ctx = hc.getContext("2d");
5597
+ }
5590
5598
  ctx.drawImage(bitmap, 0, 0);
5591
5599
  bitmap.close();
5592
5600
  return { width: w, height: h, data: ctx.getImageData(0, 0, w, h).data };
@@ -9413,6 +9421,7 @@ class GSSplatRendererMobile {
9413
9421
  const memoryMB = (this.compressedTextures.width * this.compressedTextures.height * 52 / // 约 52 bytes per texel (16+16+16+4)
9414
9422
  (1024 * 1024)).toFixed(2);
9415
9423
  } catch (error) {
9424
+ console.error("[GSSplatRendererMobile] setCompactData failed:", error);
9416
9425
  this.splatCount = 0;
9417
9426
  this.compressedTextures = null;
9418
9427
  this.sorter = null;
@@ -16346,6 +16355,7 @@ class App {
16346
16355
  */
16347
16356
  async addSplat(urlOrBuffer, onProgress, isLocalFile = false, coordinateSystem = "blender") {
16348
16357
  try {
16358
+ const isMobile = isMobileDevice();
16349
16359
  let buffer;
16350
16360
  if (typeof urlOrBuffer === "string") {
16351
16361
  buffer = await this.fetchWithProgress(urlOrBuffer, (downloadProgress) => {
@@ -16364,26 +16374,67 @@ class App {
16364
16374
  if (coordinateSystem === "blender") {
16365
16375
  for (const s of splats) {
16366
16376
  const [mx, my, mz] = s.mean;
16367
- s.mean = [mx, mz, my];
16377
+ s.mean = [mx, mz, -my];
16368
16378
  const [sx, sy, sz] = s.scale;
16369
16379
  s.scale = [sx, sz, sy];
16370
16380
  const [rw, rx, ry, rz] = s.rotation;
16371
- s.rotation = [-rw, rx, rz, ry];
16381
+ s.rotation = [rw, rx, rz, -ry];
16372
16382
  }
16373
16383
  }
16374
16384
  if (onProgress) onProgress(90, "parse");
16375
16385
  if (onProgress) onProgress(90, "upload");
16376
- const gsRenderer = new GSSplatRenderer(this.renderer, this.camera);
16377
- gsRenderer.setData(splats);
16386
+ let gsRenderer;
16387
+ if (isMobile) {
16388
+ const mobileRenderer = new GSSplatRendererMobile(this.renderer, this.camera);
16389
+ this.useMobileRenderer = true;
16390
+ const compactData = App.splatCpuToCompactData(splats);
16391
+ mobileRenderer.setCompactData(compactData);
16392
+ this.lastCompactData = compactData;
16393
+ gsRenderer = mobileRenderer;
16394
+ } else {
16395
+ const desktopRenderer = new GSSplatRenderer(this.renderer, this.camera);
16396
+ this.useMobileRenderer = false;
16397
+ desktopRenderer.setData(splats);
16398
+ gsRenderer = desktopRenderer;
16399
+ }
16378
16400
  this.sceneManager.setGSRenderer(gsRenderer);
16379
16401
  this.hotspotManager.setGSRenderer(gsRenderer);
16380
- this.useMobileRenderer = false;
16381
16402
  if (onProgress) onProgress(100, "upload");
16382
16403
  return splats.length;
16383
16404
  } catch (error) {
16384
16405
  throw error;
16385
16406
  }
16386
16407
  }
16408
+ /**
16409
+ * 将 SplatCPU[] 转换为 CompactSplatData(用于移动端渲染器)
16410
+ */
16411
+ static splatCpuToCompactData(splats) {
16412
+ const count = splats.length;
16413
+ const positions = new Float32Array(count * 3);
16414
+ const scales = new Float32Array(count * 3);
16415
+ const rotations = new Float32Array(count * 4);
16416
+ const colors = new Float32Array(count * 3);
16417
+ const opacities = new Float32Array(count);
16418
+ for (let i = 0; i < count; i++) {
16419
+ const s = splats[i];
16420
+ const i3 = i * 3, i4 = i * 4;
16421
+ positions[i3] = s.mean[0];
16422
+ positions[i3 + 1] = s.mean[1];
16423
+ positions[i3 + 2] = s.mean[2];
16424
+ scales[i3] = s.scale[0];
16425
+ scales[i3 + 1] = s.scale[1];
16426
+ scales[i3 + 2] = s.scale[2];
16427
+ rotations[i4] = s.rotation[0];
16428
+ rotations[i4 + 1] = s.rotation[1];
16429
+ rotations[i4 + 2] = s.rotation[2];
16430
+ rotations[i4 + 3] = s.rotation[3];
16431
+ colors[i3] = s.colorDC[0];
16432
+ colors[i3 + 1] = s.colorDC[1];
16433
+ colors[i3 + 2] = s.colorDC[2];
16434
+ opacities[i] = s.opacity;
16435
+ }
16436
+ return { count, positions, scales, rotations, colors, opacities };
16437
+ }
16387
16438
  /**
16388
16439
  * 加载 SOG 文件 (Spatially Ordered Gaussians)
16389
16440
  * @param coordinateSystem 源数据坐标系,默认 'blender'(Z-up → Y-up 自动转换)
@@ -16416,14 +16467,13 @@ class App {
16416
16467
  const i3 = i * 3, i4 = i * 4;
16417
16468
  const py = positions[i3 + 1], pz = positions[i3 + 2];
16418
16469
  positions[i3 + 1] = pz;
16419
- positions[i3 + 2] = py;
16470
+ positions[i3 + 2] = -py;
16420
16471
  const sy = scales[i3 + 1], sz = scales[i3 + 2];
16421
16472
  scales[i3 + 1] = sz;
16422
16473
  scales[i3 + 2] = sy;
16423
- const rw = rotations[i4], ry = rotations[i4 + 2], rz = rotations[i4 + 3];
16424
- rotations[i4] = -rw;
16474
+ const ry = rotations[i4 + 2], rz = rotations[i4 + 3];
16425
16475
  rotations[i4 + 2] = rz;
16426
- rotations[i4 + 3] = ry;
16476
+ rotations[i4 + 3] = -ry;
16427
16477
  if (shCoeffs) {
16428
16478
  transformSHCoeffsYZSwap(shCoeffs, i * 45, 15);
16429
16479
  }