@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.cjs CHANGED
@@ -441,7 +441,7 @@ class Camera {
441
441
  // 45度
442
442
  __publicField(this, "aspect", 1);
443
443
  __publicField(this, "near", 0.01);
444
- __publicField(this, "far", 9e3);
444
+ __publicField(this, "far", 1e5);
445
445
  // 矩阵
446
446
  __publicField(this, "viewMatrix", new Float32Array(16));
447
447
  __publicField(this, "projectionMatrix", new Float32Array(16));
@@ -4271,7 +4271,7 @@ function transformSHCoeffsYZSwap$1(sh, base, perChannel) {
4271
4271
  for (let ch = 0; ch < 3; ch++) {
4272
4272
  const a = sh[base + ch];
4273
4273
  const b = sh[base + 3 + ch];
4274
- sh[base + ch] = -b;
4274
+ sh[base + ch] = b;
4275
4275
  sh[base + 3 + ch] = -a;
4276
4276
  }
4277
4277
  }
@@ -4282,8 +4282,8 @@ function transformSHCoeffsYZSwap$1(sh, base, perChannel) {
4282
4282
  const g2 = sh[base + 15 + ch];
4283
4283
  const g3 = sh[base + 18 + ch];
4284
4284
  const g4 = sh[base + 21 + ch];
4285
- sh[base + 9 + ch] = -g3;
4286
- sh[base + 12 + ch] = g1;
4285
+ sh[base + 9 + ch] = g3;
4286
+ sh[base + 12 + ch] = -g1;
4287
4287
  sh[base + 15 + ch] = -0.5 * g2 - SQRT3_2 * g4;
4288
4288
  sh[base + 18 + ch] = -g0;
4289
4289
  sh[base + 21 + ch] = -SQRT3_2 * g2 + 0.5 * g4;
@@ -4301,9 +4301,9 @@ function transformSHCoeffsYZSwap$1(sh, base, perChannel) {
4301
4301
  const g4 = sh[base + 36 + ch];
4302
4302
  const g5 = sh[base + 39 + ch];
4303
4303
  const g6 = sh[base + 42 + ch];
4304
- sh[base + 24 + ch] = A * g3 - B * g5;
4305
- sh[base + 27 + ch] = g1;
4306
- sh[base + 30 + ch] = B * g3 + A * g5;
4304
+ sh[base + 24 + ch] = -A * g3 + B * g5;
4305
+ sh[base + 27 + ch] = -g1;
4306
+ sh[base + 30 + ch] = -B * g3 - A * g5;
4307
4307
  sh[base + 33 + ch] = A * g0 + B * g2;
4308
4308
  sh[base + 36 + ch] = -0.25 * g4 - P * g6;
4309
4309
  sh[base + 39 + ch] = -B * g0 + A * g2;
@@ -4541,13 +4541,13 @@ async function loadPLY(url, options = {}) {
4541
4541
  transformSHCoeffsYZSwap$1(shRestBuffer, shOffset, perChannel);
4542
4542
  }
4543
4543
  splats[i] = {
4544
- mean: swapYZ ? [x, z, y] : [x, y, z],
4544
+ mean: swapYZ ? [x, z, -y] : [x, y, z],
4545
4545
  scale: swapYZ ? [scale_0, scale_2, scale_1] : [scale_0, scale_1, scale_2],
4546
4546
  rotation: swapYZ ? [
4547
- -rot_0 * qnorm,
4547
+ rot_0 * qnorm,
4548
4548
  rot_1 * qnorm,
4549
4549
  rot_3 * qnorm,
4550
- rot_2 * qnorm
4550
+ -rot_2 * qnorm
4551
4551
  ] : [
4552
4552
  rot_0 * qnorm,
4553
4553
  rot_1 * qnorm,
@@ -4585,7 +4585,7 @@ function transformSHCoeffsYZSwap(sh, base, perChannel) {
4585
4585
  for (let ch = 0; ch < 3; ch++) {
4586
4586
  const a = sh[base + ch];
4587
4587
  const b = sh[base + 3 + ch];
4588
- sh[base + ch] = -b;
4588
+ sh[base + ch] = b;
4589
4589
  sh[base + 3 + ch] = -a;
4590
4590
  }
4591
4591
  }
@@ -4596,8 +4596,8 @@ function transformSHCoeffsYZSwap(sh, base, perChannel) {
4596
4596
  const g2 = sh[base + 15 + ch];
4597
4597
  const g3 = sh[base + 18 + ch];
4598
4598
  const g4 = sh[base + 21 + ch];
4599
- sh[base + 9 + ch] = -g3;
4600
- sh[base + 12 + ch] = g1;
4599
+ sh[base + 9 + ch] = g3;
4600
+ sh[base + 12 + ch] = -g1;
4601
4601
  sh[base + 15 + ch] = -0.5 * g2 - SQRT3_2 * g4;
4602
4602
  sh[base + 18 + ch] = -g0;
4603
4603
  sh[base + 21 + ch] = -SQRT3_2 * g2 + 0.5 * g4;
@@ -4615,9 +4615,9 @@ function transformSHCoeffsYZSwap(sh, base, perChannel) {
4615
4615
  const g4 = sh[base + 36 + ch];
4616
4616
  const g5 = sh[base + 39 + ch];
4617
4617
  const g6 = sh[base + 42 + ch];
4618
- sh[base + 24 + ch] = A * g3 - B * g5;
4619
- sh[base + 27 + ch] = g1;
4620
- sh[base + 30 + ch] = B * g3 + A * g5;
4618
+ sh[base + 24 + ch] = -A * g3 + B * g5;
4619
+ sh[base + 27 + ch] = -g1;
4620
+ sh[base + 30 + ch] = -B * g3 - A * g5;
4621
4621
  sh[base + 33 + ch] = A * g0 + B * g2;
4622
4622
  sh[base + 36 + ch] = -0.25 * g4 - P * g6;
4623
4623
  sh[base + 39 + ch] = -B * g0 + A * g2;
@@ -4912,7 +4912,7 @@ async function parsePLYBuffer(buffer, options = {}) {
4912
4912
  const pz = offsets.z >= 0 ? readProperty(dataView, base + offsets.z, types.z, littleEndian) : 0;
4913
4913
  positions[outputIdx * 3 + 0] = px;
4914
4914
  positions[outputIdx * 3 + 1] = swapYZ ? pz : py;
4915
- positions[outputIdx * 3 + 2] = swapYZ ? py : pz;
4915
+ positions[outputIdx * 3 + 2] = swapYZ ? -py : pz;
4916
4916
  const sx = offsets.scale_0 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_0, types.scale_0, littleEndian)) : 1;
4917
4917
  const sy = offsets.scale_1 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_1, types.scale_1, littleEndian)) : 1;
4918
4918
  const sz = offsets.scale_2 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_2, types.scale_2, littleEndian)) : 1;
@@ -4926,10 +4926,10 @@ async function parsePLYBuffer(buffer, options = {}) {
4926
4926
  const qlen = Math.sqrt(rot_0 * rot_0 + rot_1 * rot_1 + rot_2 * rot_2 + rot_3 * rot_3);
4927
4927
  const qnorm = qlen > 0 ? 1 / qlen : 1;
4928
4928
  if (swapYZ) {
4929
- rotations[outputIdx * 4 + 0] = -rot_0 * qnorm;
4929
+ rotations[outputIdx * 4 + 0] = rot_0 * qnorm;
4930
4930
  rotations[outputIdx * 4 + 1] = rot_1 * qnorm;
4931
4931
  rotations[outputIdx * 4 + 2] = rot_3 * qnorm;
4932
- rotations[outputIdx * 4 + 3] = rot_2 * qnorm;
4932
+ rotations[outputIdx * 4 + 3] = -rot_2 * qnorm;
4933
4933
  } else {
4934
4934
  rotations[outputIdx * 4 + 0] = rot_0 * qnorm;
4935
4935
  rotations[outputIdx * 4 + 1] = rot_1 * qnorm;
@@ -5587,8 +5587,16 @@ async function decodeWebP(bytes) {
5587
5587
  });
5588
5588
  const w = bitmap.width;
5589
5589
  const h = bitmap.height;
5590
- const canvas = new OffscreenCanvas(w, h);
5591
- const ctx = canvas.getContext("2d");
5590
+ let ctx;
5591
+ if (typeof OffscreenCanvas !== "undefined") {
5592
+ const oc = new OffscreenCanvas(w, h);
5593
+ ctx = oc.getContext("2d");
5594
+ } else {
5595
+ const hc = document.createElement("canvas");
5596
+ hc.width = w;
5597
+ hc.height = h;
5598
+ ctx = hc.getContext("2d");
5599
+ }
5592
5600
  ctx.drawImage(bitmap, 0, 0);
5593
5601
  bitmap.close();
5594
5602
  return { width: w, height: h, data: ctx.getImageData(0, 0, w, h).data };
@@ -9415,6 +9423,7 @@ class GSSplatRendererMobile {
9415
9423
  const memoryMB = (this.compressedTextures.width * this.compressedTextures.height * 52 / // 约 52 bytes per texel (16+16+16+4)
9416
9424
  (1024 * 1024)).toFixed(2);
9417
9425
  } catch (error) {
9426
+ console.error("[GSSplatRendererMobile] setCompactData failed:", error);
9418
9427
  this.splatCount = 0;
9419
9428
  this.compressedTextures = null;
9420
9429
  this.sorter = null;
@@ -16348,6 +16357,7 @@ class App {
16348
16357
  */
16349
16358
  async addSplat(urlOrBuffer, onProgress, isLocalFile = false, coordinateSystem = "blender") {
16350
16359
  try {
16360
+ const isMobile = isMobileDevice();
16351
16361
  let buffer;
16352
16362
  if (typeof urlOrBuffer === "string") {
16353
16363
  buffer = await this.fetchWithProgress(urlOrBuffer, (downloadProgress) => {
@@ -16366,26 +16376,67 @@ class App {
16366
16376
  if (coordinateSystem === "blender") {
16367
16377
  for (const s of splats) {
16368
16378
  const [mx, my, mz] = s.mean;
16369
- s.mean = [mx, mz, my];
16379
+ s.mean = [mx, mz, -my];
16370
16380
  const [sx, sy, sz] = s.scale;
16371
16381
  s.scale = [sx, sz, sy];
16372
16382
  const [rw, rx, ry, rz] = s.rotation;
16373
- s.rotation = [-rw, rx, rz, ry];
16383
+ s.rotation = [rw, rx, rz, -ry];
16374
16384
  }
16375
16385
  }
16376
16386
  if (onProgress) onProgress(90, "parse");
16377
16387
  if (onProgress) onProgress(90, "upload");
16378
- const gsRenderer = new GSSplatRenderer(this.renderer, this.camera);
16379
- gsRenderer.setData(splats);
16388
+ let gsRenderer;
16389
+ if (isMobile) {
16390
+ const mobileRenderer = new GSSplatRendererMobile(this.renderer, this.camera);
16391
+ this.useMobileRenderer = true;
16392
+ const compactData = App.splatCpuToCompactData(splats);
16393
+ mobileRenderer.setCompactData(compactData);
16394
+ this.lastCompactData = compactData;
16395
+ gsRenderer = mobileRenderer;
16396
+ } else {
16397
+ const desktopRenderer = new GSSplatRenderer(this.renderer, this.camera);
16398
+ this.useMobileRenderer = false;
16399
+ desktopRenderer.setData(splats);
16400
+ gsRenderer = desktopRenderer;
16401
+ }
16380
16402
  this.sceneManager.setGSRenderer(gsRenderer);
16381
16403
  this.hotspotManager.setGSRenderer(gsRenderer);
16382
- this.useMobileRenderer = false;
16383
16404
  if (onProgress) onProgress(100, "upload");
16384
16405
  return splats.length;
16385
16406
  } catch (error) {
16386
16407
  throw error;
16387
16408
  }
16388
16409
  }
16410
+ /**
16411
+ * 将 SplatCPU[] 转换为 CompactSplatData(用于移动端渲染器)
16412
+ */
16413
+ static splatCpuToCompactData(splats) {
16414
+ const count = splats.length;
16415
+ const positions = new Float32Array(count * 3);
16416
+ const scales = new Float32Array(count * 3);
16417
+ const rotations = new Float32Array(count * 4);
16418
+ const colors = new Float32Array(count * 3);
16419
+ const opacities = new Float32Array(count);
16420
+ for (let i = 0; i < count; i++) {
16421
+ const s = splats[i];
16422
+ const i3 = i * 3, i4 = i * 4;
16423
+ positions[i3] = s.mean[0];
16424
+ positions[i3 + 1] = s.mean[1];
16425
+ positions[i3 + 2] = s.mean[2];
16426
+ scales[i3] = s.scale[0];
16427
+ scales[i3 + 1] = s.scale[1];
16428
+ scales[i3 + 2] = s.scale[2];
16429
+ rotations[i4] = s.rotation[0];
16430
+ rotations[i4 + 1] = s.rotation[1];
16431
+ rotations[i4 + 2] = s.rotation[2];
16432
+ rotations[i4 + 3] = s.rotation[3];
16433
+ colors[i3] = s.colorDC[0];
16434
+ colors[i3 + 1] = s.colorDC[1];
16435
+ colors[i3 + 2] = s.colorDC[2];
16436
+ opacities[i] = s.opacity;
16437
+ }
16438
+ return { count, positions, scales, rotations, colors, opacities };
16439
+ }
16389
16440
  /**
16390
16441
  * 加载 SOG 文件 (Spatially Ordered Gaussians)
16391
16442
  * @param coordinateSystem 源数据坐标系,默认 'blender'(Z-up → Y-up 自动转换)
@@ -16418,14 +16469,13 @@ class App {
16418
16469
  const i3 = i * 3, i4 = i * 4;
16419
16470
  const py = positions[i3 + 1], pz = positions[i3 + 2];
16420
16471
  positions[i3 + 1] = pz;
16421
- positions[i3 + 2] = py;
16472
+ positions[i3 + 2] = -py;
16422
16473
  const sy = scales[i3 + 1], sz = scales[i3 + 2];
16423
16474
  scales[i3 + 1] = sz;
16424
16475
  scales[i3 + 2] = sy;
16425
- const rw = rotations[i4], ry = rotations[i4 + 2], rz = rotations[i4 + 3];
16426
- rotations[i4] = -rw;
16476
+ const ry = rotations[i4 + 2], rz = rotations[i4 + 3];
16427
16477
  rotations[i4 + 2] = rz;
16428
- rotations[i4 + 3] = ry;
16478
+ rotations[i4 + 3] = -ry;
16429
16479
  if (shCoeffs) {
16430
16480
  transformSHCoeffsYZSwap(shCoeffs, i * 45, 15);
16431
16481
  }