@d5techs/3dgs-lib 1.2.0 → 1.3.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.
- package/dist/3dgs-lib.cjs +46 -18
- package/dist/3dgs-lib.cjs.map +1 -1
- package/dist/3dgs-lib.js +46 -18
- package/dist/3dgs-lib.js.map +1 -1
- package/dist/App.d.ts +6 -1
- package/dist/gs/PLYLoader.d.ts +7 -1
- package/dist/gs/PLYLoaderMobile.d.ts +8 -0
- package/dist/index.d.ts +2 -2
- package/package.json +1 -1
package/dist/3dgs-lib.js
CHANGED
|
@@ -4411,7 +4411,8 @@ function readProperty$1(dataView, baseOffset, prop, littleEndian) {
|
|
|
4411
4411
|
function sigmoid$1(x) {
|
|
4412
4412
|
return 1 / (1 + Math.exp(-x));
|
|
4413
4413
|
}
|
|
4414
|
-
async function loadPLY(url) {
|
|
4414
|
+
async function loadPLY(url, options = {}) {
|
|
4415
|
+
const { coordinateSystem = "blender" } = options;
|
|
4415
4416
|
const response = await fetch(url);
|
|
4416
4417
|
if (!response.ok) {
|
|
4417
4418
|
throw new Error(`无法加载 PLY 文件: ${url}`);
|
|
@@ -4423,6 +4424,7 @@ async function loadPLY(url) {
|
|
|
4423
4424
|
throw new Error("不支持 ASCII 格式的 PLY 文件,请使用 binary_little_endian 或 binary_big_endian 格式");
|
|
4424
4425
|
}
|
|
4425
4426
|
const littleEndian = format === "binary_little_endian";
|
|
4427
|
+
const swapYZ = coordinateSystem === "blender";
|
|
4426
4428
|
const propMap = buildPropertyMap(properties);
|
|
4427
4429
|
const props = {
|
|
4428
4430
|
x: propMap.get("x"),
|
|
@@ -4488,9 +4490,14 @@ async function loadPLY(url) {
|
|
|
4488
4490
|
shRest[dstBase + 2] = srcB < shRestProps.length ? readProperty$1(dataView, base, shRestProps[srcB], littleEndian) : 0;
|
|
4489
4491
|
}
|
|
4490
4492
|
splats[i] = {
|
|
4491
|
-
mean: [x, y, z],
|
|
4492
|
-
scale: [scale_0, scale_1, scale_2],
|
|
4493
|
-
rotation: [
|
|
4493
|
+
mean: swapYZ ? [x, z, y] : [x, y, z],
|
|
4494
|
+
scale: swapYZ ? [scale_0, scale_2, scale_1] : [scale_0, scale_1, scale_2],
|
|
4495
|
+
rotation: swapYZ ? [
|
|
4496
|
+
-rot_0 * qnorm,
|
|
4497
|
+
rot_1 * qnorm,
|
|
4498
|
+
rot_3 * qnorm,
|
|
4499
|
+
rot_2 * qnorm
|
|
4500
|
+
] : [
|
|
4494
4501
|
rot_0 * qnorm,
|
|
4495
4502
|
rot_1 * qnorm,
|
|
4496
4503
|
rot_2 * qnorm,
|
|
@@ -4706,7 +4713,8 @@ async function parsePLYBuffer(buffer, options = {}) {
|
|
|
4706
4713
|
const {
|
|
4707
4714
|
maxSplats = 2e5,
|
|
4708
4715
|
loadSH = false,
|
|
4709
|
-
onProgress
|
|
4716
|
+
onProgress,
|
|
4717
|
+
coordinateSystem = "blender"
|
|
4710
4718
|
} = options;
|
|
4711
4719
|
const seed = options.seed ?? buffer.byteLength;
|
|
4712
4720
|
const { headerText, dataOffset } = extractHeader(buffer);
|
|
@@ -4796,27 +4804,41 @@ async function parsePLYBuffer(buffer, options = {}) {
|
|
|
4796
4804
|
const opacities = new Float32Array(actualCount);
|
|
4797
4805
|
const shCoeffs = loadSH ? new Float32Array(actualCount * 45) : void 0;
|
|
4798
4806
|
const dataView = new DataView(buffer, dataOffset);
|
|
4807
|
+
const swapYZ = coordinateSystem === "blender";
|
|
4799
4808
|
let outputIdx = 0;
|
|
4800
4809
|
let lastProgress = 0;
|
|
4801
4810
|
for (let i = 0; i < actualCount; i++) {
|
|
4802
4811
|
const srcIdx = sampleIndices ? sampleIndices[i] : i;
|
|
4803
4812
|
const base = srcIdx * stride;
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4813
|
+
const px = offsets.x >= 0 ? readProperty(dataView, base + offsets.x, types.x, littleEndian) : 0;
|
|
4814
|
+
const py = offsets.y >= 0 ? readProperty(dataView, base + offsets.y, types.y, littleEndian) : 0;
|
|
4815
|
+
const pz = offsets.z >= 0 ? readProperty(dataView, base + offsets.z, types.z, littleEndian) : 0;
|
|
4816
|
+
positions[outputIdx * 3 + 0] = px;
|
|
4817
|
+
positions[outputIdx * 3 + 1] = swapYZ ? pz : py;
|
|
4818
|
+
positions[outputIdx * 3 + 2] = swapYZ ? py : pz;
|
|
4819
|
+
const sx = offsets.scale_0 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_0, types.scale_0, littleEndian)) : 1;
|
|
4820
|
+
const sy = offsets.scale_1 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_1, types.scale_1, littleEndian)) : 1;
|
|
4821
|
+
const sz = offsets.scale_2 >= 0 ? Math.exp(readProperty(dataView, base + offsets.scale_2, types.scale_2, littleEndian)) : 1;
|
|
4822
|
+
scales[outputIdx * 3 + 0] = sx;
|
|
4823
|
+
scales[outputIdx * 3 + 1] = swapYZ ? sz : sy;
|
|
4824
|
+
scales[outputIdx * 3 + 2] = swapYZ ? sy : sz;
|
|
4810
4825
|
const rot_0 = offsets.rot_0 >= 0 ? readProperty(dataView, base + offsets.rot_0, types.rot_0, littleEndian) : 1;
|
|
4811
4826
|
const rot_1 = offsets.rot_1 >= 0 ? readProperty(dataView, base + offsets.rot_1, types.rot_1, littleEndian) : 0;
|
|
4812
4827
|
const rot_2 = offsets.rot_2 >= 0 ? readProperty(dataView, base + offsets.rot_2, types.rot_2, littleEndian) : 0;
|
|
4813
4828
|
const rot_3 = offsets.rot_3 >= 0 ? readProperty(dataView, base + offsets.rot_3, types.rot_3, littleEndian) : 0;
|
|
4814
4829
|
const qlen = Math.sqrt(rot_0 * rot_0 + rot_1 * rot_1 + rot_2 * rot_2 + rot_3 * rot_3);
|
|
4815
4830
|
const qnorm = qlen > 0 ? 1 / qlen : 1;
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4831
|
+
if (swapYZ) {
|
|
4832
|
+
rotations[outputIdx * 4 + 0] = -rot_0 * qnorm;
|
|
4833
|
+
rotations[outputIdx * 4 + 1] = rot_1 * qnorm;
|
|
4834
|
+
rotations[outputIdx * 4 + 2] = rot_3 * qnorm;
|
|
4835
|
+
rotations[outputIdx * 4 + 3] = rot_2 * qnorm;
|
|
4836
|
+
} else {
|
|
4837
|
+
rotations[outputIdx * 4 + 0] = rot_0 * qnorm;
|
|
4838
|
+
rotations[outputIdx * 4 + 1] = rot_1 * qnorm;
|
|
4839
|
+
rotations[outputIdx * 4 + 2] = rot_2 * qnorm;
|
|
4840
|
+
rotations[outputIdx * 4 + 3] = rot_3 * qnorm;
|
|
4841
|
+
}
|
|
4820
4842
|
const f_dc_0 = offsets.f_dc_0 >= 0 ? readProperty(dataView, base + offsets.f_dc_0, types.f_dc_0, littleEndian) : 0;
|
|
4821
4843
|
const f_dc_1 = offsets.f_dc_1 >= 0 ? readProperty(dataView, base + offsets.f_dc_1, types.f_dc_1, littleEndian) : 0;
|
|
4822
4844
|
const f_dc_2 = offsets.f_dc_2 >= 0 ? readProperty(dataView, base + offsets.f_dc_2, types.f_dc_2, littleEndian) : 0;
|
|
@@ -13968,8 +13990,12 @@ class App {
|
|
|
13968
13990
|
}
|
|
13969
13991
|
/**
|
|
13970
13992
|
* 加载 PLY 文件 (3D Gaussian Splatting)
|
|
13993
|
+
* @param urlOrBuffer PLY 文件 URL 或 ArrayBuffer
|
|
13994
|
+
* @param onProgress 进度回调
|
|
13995
|
+
* @param isLocalFile 是否为本地文件
|
|
13996
|
+
* @param coordinateSystem 源数据坐标系,默认 'blender'(Z-up → Y-up 自动转换)
|
|
13971
13997
|
*/
|
|
13972
|
-
async addPLY(urlOrBuffer, onProgress, isLocalFile = false) {
|
|
13998
|
+
async addPLY(urlOrBuffer, onProgress, isLocalFile = false, coordinateSystem = "blender") {
|
|
13973
13999
|
try {
|
|
13974
14000
|
const isMobile = isMobileDevice();
|
|
13975
14001
|
let buffer;
|
|
@@ -13998,7 +14024,8 @@ class App {
|
|
|
13998
14024
|
const compactData = await this.parsePLYBuffer(buffer, {
|
|
13999
14025
|
maxSplats: Infinity,
|
|
14000
14026
|
loadSH: false,
|
|
14001
|
-
onProgress: parseProgressCallback
|
|
14027
|
+
onProgress: parseProgressCallback,
|
|
14028
|
+
coordinateSystem
|
|
14002
14029
|
});
|
|
14003
14030
|
if (onProgress) onProgress(90, "upload");
|
|
14004
14031
|
gsRenderer.setCompactData(compactData);
|
|
@@ -14012,7 +14039,8 @@ class App {
|
|
|
14012
14039
|
const compactData = await this.parsePLYBuffer(buffer, {
|
|
14013
14040
|
maxSplats: Infinity,
|
|
14014
14041
|
loadSH: true,
|
|
14015
|
-
onProgress: parseProgressCallback
|
|
14042
|
+
onProgress: parseProgressCallback,
|
|
14043
|
+
coordinateSystem
|
|
14016
14044
|
});
|
|
14017
14045
|
if (onProgress) onProgress(90, "upload");
|
|
14018
14046
|
gsRenderer.setCompactData(compactData);
|