@rings-webgpu/core 1.0.26 → 1.0.27
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/rings.es.js +213 -211
- package/dist/rings.es.js.map +3 -3
- package/dist/rings.es.max.js +930 -6
- package/dist/rings.umd.js +215 -213
- package/dist/rings.umd.js.map +3 -3
- package/dist/rings.umd.max.js +934 -5
- package/dist/types/index.d.ts +1 -0
- package/dist/types/loader/parser/ply/PlyLoader.d.ts +6 -2
- package/dist/types/loader/parser/ply/PlyParser.d.ts +7 -0
- package/dist/types/loader/parser/ply/PlyTypes.d.ts +25 -0
- package/package.json +1 -1
package/dist/rings.umd.max.js
CHANGED
|
@@ -41432,7 +41432,7 @@ else if (typeof exports === 'object')
|
|
|
41432
41432
|
}
|
|
41433
41433
|
}
|
|
41434
41434
|
|
|
41435
|
-
const version = "1.0.
|
|
41435
|
+
const version = "1.0.26";
|
|
41436
41436
|
|
|
41437
41437
|
class Engine3D {
|
|
41438
41438
|
/**
|
|
@@ -59144,6 +59144,15 @@ fn frag(){
|
|
|
59144
59144
|
return "unknown" /* UNKNOWN */;
|
|
59145
59145
|
}
|
|
59146
59146
|
|
|
59147
|
+
var PlyMode = /* @__PURE__ */ ((PlyMode2) => {
|
|
59148
|
+
PlyMode2[PlyMode2["Splat"] = 0] = "Splat";
|
|
59149
|
+
PlyMode2[PlyMode2["PointCloud"] = 1] = "PointCloud";
|
|
59150
|
+
PlyMode2[PlyMode2["Mesh"] = 2] = "Mesh";
|
|
59151
|
+
return PlyMode2;
|
|
59152
|
+
})(PlyMode || {});
|
|
59153
|
+
const splatProperties = ["x", "y", "z", "scale_0", "scale_1", "scale_2", "opacity", "rot_0", "rot_1", "rot_2", "rot_3"];
|
|
59154
|
+
const splatColorProperties = ["red", "green", "blue", "f_dc_0", "f_dc_1", "f_dc_2"];
|
|
59155
|
+
|
|
59147
59156
|
function byteSizeOfType(t) {
|
|
59148
59157
|
switch (t) {
|
|
59149
59158
|
case "char":
|
|
@@ -59219,34 +59228,85 @@ fn frag(){
|
|
|
59219
59228
|
const lines = headerText.split(/\r?\n/);
|
|
59220
59229
|
let format = "";
|
|
59221
59230
|
let vertexCount = 0;
|
|
59231
|
+
let faceCount = 0;
|
|
59222
59232
|
const properties = [];
|
|
59233
|
+
const faceProperties = [];
|
|
59234
|
+
const textureFiles = [];
|
|
59223
59235
|
let inVertexElement = false;
|
|
59236
|
+
let inFaceElement = false;
|
|
59224
59237
|
for (const line of lines) {
|
|
59225
59238
|
if (line.startsWith("format ")) {
|
|
59226
59239
|
format = line.split(/\s+/)[1];
|
|
59240
|
+
} else if (line.startsWith("comment TextureFile ")) {
|
|
59241
|
+
const texturePath = line.substring("comment TextureFile ".length).trim();
|
|
59242
|
+
if (texturePath) {
|
|
59243
|
+
textureFiles.push(texturePath);
|
|
59244
|
+
}
|
|
59227
59245
|
} else if (line.startsWith("element ")) {
|
|
59228
59246
|
const toks = line.split(/\s+/);
|
|
59229
59247
|
inVertexElement = toks[1] === "vertex";
|
|
59230
|
-
|
|
59248
|
+
inFaceElement = toks[1] === "face";
|
|
59249
|
+
if (inVertexElement) {
|
|
59250
|
+
vertexCount = parseInt(toks[2]);
|
|
59251
|
+
inFaceElement = false;
|
|
59252
|
+
}
|
|
59253
|
+
if (inFaceElement) {
|
|
59254
|
+
faceCount = parseInt(toks[2]);
|
|
59255
|
+
inVertexElement = false;
|
|
59256
|
+
}
|
|
59231
59257
|
} else if (inVertexElement && line.startsWith("property ")) {
|
|
59232
59258
|
const toks = line.split(/\s+/);
|
|
59233
59259
|
const type = toks[1];
|
|
59234
59260
|
const name = toks[2];
|
|
59235
59261
|
properties.push({ name, type });
|
|
59262
|
+
} else if (inFaceElement && line.startsWith("property ")) {
|
|
59263
|
+
const toks = line.split(/\s+/);
|
|
59264
|
+
if (toks[1] === "list") {
|
|
59265
|
+
const countType = toks[2];
|
|
59266
|
+
const itemType = toks[3];
|
|
59267
|
+
const name = toks[4];
|
|
59268
|
+
faceProperties.push({ name, type: `list ${countType} ${itemType}` });
|
|
59269
|
+
} else {
|
|
59270
|
+
const type = toks[1];
|
|
59271
|
+
const name = toks[2];
|
|
59272
|
+
faceProperties.push({ name, type });
|
|
59273
|
+
}
|
|
59236
59274
|
}
|
|
59237
59275
|
}
|
|
59238
|
-
if (format !== "binary_little_endian") {
|
|
59239
|
-
throw new Error(
|
|
59276
|
+
if (format !== "binary_little_endian" && format !== "ascii") {
|
|
59277
|
+
throw new Error(`PLY: Unsupported format: ${format}. Only binary_little_endian and ascii are supported.`);
|
|
59278
|
+
}
|
|
59279
|
+
let splatPropertyCount = 0;
|
|
59280
|
+
let splatPropertyColorCount = 0;
|
|
59281
|
+
for (const property of properties) {
|
|
59282
|
+
if (splatProperties.includes(property.name)) {
|
|
59283
|
+
splatPropertyCount++;
|
|
59284
|
+
}
|
|
59285
|
+
if (splatColorProperties.includes(property.name)) {
|
|
59286
|
+
splatPropertyColorCount++;
|
|
59287
|
+
}
|
|
59240
59288
|
}
|
|
59241
59289
|
return {
|
|
59242
59290
|
format,
|
|
59243
59291
|
vertexCount,
|
|
59292
|
+
faceCount,
|
|
59244
59293
|
properties,
|
|
59245
|
-
|
|
59294
|
+
faceProperties: faceProperties.length > 0 ? faceProperties : void 0,
|
|
59295
|
+
textureFiles,
|
|
59296
|
+
headerByteLength: headerText.length,
|
|
59297
|
+
mode: faceCount ? PlyMode.Mesh : splatPropertyCount === splatProperties.length && splatPropertyColorCount === 3 ? PlyMode.Splat : PlyMode.PointCloud
|
|
59246
59298
|
};
|
|
59247
59299
|
}
|
|
59248
59300
|
function parsePlyGaussianSplat(buffer) {
|
|
59249
59301
|
const header = parsePlyHeader(buffer);
|
|
59302
|
+
const { format } = header;
|
|
59303
|
+
if (format === "ascii") {
|
|
59304
|
+
return parsePlyGaussianSplatASCII(buffer, header);
|
|
59305
|
+
} else {
|
|
59306
|
+
return parsePlyGaussianSplatBinary(buffer, header);
|
|
59307
|
+
}
|
|
59308
|
+
}
|
|
59309
|
+
function parsePlyGaussianSplatBinary(buffer, header) {
|
|
59250
59310
|
const { vertexCount, properties, headerByteLength } = header;
|
|
59251
59311
|
const payload = new DataView(buffer, headerByteLength);
|
|
59252
59312
|
const has = (n) => properties.find((p) => p.name === n) != null;
|
|
@@ -59368,6 +59428,743 @@ fn frag(){
|
|
|
59368
59428
|
sh: hasSH && shCoeffs ? { order: shOrder, coeffs: shCoeffs } : void 0
|
|
59369
59429
|
};
|
|
59370
59430
|
}
|
|
59431
|
+
function parsePlyGaussianSplatASCII(buffer, header) {
|
|
59432
|
+
const { vertexCount, properties } = header;
|
|
59433
|
+
const text = new TextDecoder("utf-8").decode(buffer);
|
|
59434
|
+
const headerEnd = text.indexOf("end_header");
|
|
59435
|
+
if (headerEnd < 0) {
|
|
59436
|
+
throw new Error("PLY: Invalid PLY header");
|
|
59437
|
+
}
|
|
59438
|
+
let bodyStart = headerEnd + "end_header".length;
|
|
59439
|
+
while (bodyStart < text.length && (text[bodyStart] === " " || text[bodyStart] === "\n" || text[bodyStart] === "\r")) {
|
|
59440
|
+
bodyStart++;
|
|
59441
|
+
}
|
|
59442
|
+
const bodyText = text.substring(bodyStart);
|
|
59443
|
+
const tokens = bodyText.split(/\s+/).filter((token) => token.length > 0);
|
|
59444
|
+
let tokenIndex = 0;
|
|
59445
|
+
const has = (n) => properties.find((p) => p.name === n) != null;
|
|
59446
|
+
const propIndex = (n) => properties.findIndex((p) => p.name === n);
|
|
59447
|
+
const parseASCIINumber = (type) => {
|
|
59448
|
+
if (tokenIndex >= tokens.length) {
|
|
59449
|
+
throw new Error("PLY: Unexpected end of file");
|
|
59450
|
+
}
|
|
59451
|
+
const value = tokens[tokenIndex++];
|
|
59452
|
+
switch (type) {
|
|
59453
|
+
case "char":
|
|
59454
|
+
case "uchar":
|
|
59455
|
+
case "short":
|
|
59456
|
+
case "ushort":
|
|
59457
|
+
case "int":
|
|
59458
|
+
case "uint":
|
|
59459
|
+
case "int8":
|
|
59460
|
+
case "uint8":
|
|
59461
|
+
case "int16":
|
|
59462
|
+
case "uint16":
|
|
59463
|
+
case "int32":
|
|
59464
|
+
case "uint32":
|
|
59465
|
+
return parseInt(value);
|
|
59466
|
+
case "float":
|
|
59467
|
+
case "double":
|
|
59468
|
+
case "float32":
|
|
59469
|
+
case "float64":
|
|
59470
|
+
return parseFloat(value);
|
|
59471
|
+
default:
|
|
59472
|
+
return parseFloat(value);
|
|
59473
|
+
}
|
|
59474
|
+
};
|
|
59475
|
+
const position = new Float32Array(vertexCount * 3);
|
|
59476
|
+
const scale = has("scale_0") ? new Float32Array(vertexCount * 3) : void 0;
|
|
59477
|
+
const rotation = has("rot_0") ? new Float32Array(vertexCount * 4) : void 0;
|
|
59478
|
+
const opacity = has("opacity") ? new Float32Array(vertexCount) : void 0;
|
|
59479
|
+
const dcIdx = [propIndex("f_dc_0"), propIndex("f_dc_1"), propIndex("f_dc_2")];
|
|
59480
|
+
const restIndices = [];
|
|
59481
|
+
for (let i = 0; i < properties.length; i++) {
|
|
59482
|
+
if (properties[i].name.startsWith("f_rest_")) restIndices.push(i);
|
|
59483
|
+
}
|
|
59484
|
+
const hasSH = dcIdx[0] >= 0 && dcIdx[1] >= 0 && dcIdx[2] >= 0;
|
|
59485
|
+
let shCoeffs = void 0;
|
|
59486
|
+
let shOrder = 0;
|
|
59487
|
+
if (hasSH) {
|
|
59488
|
+
const coeffsPerColor = 1 + restIndices.length / 3;
|
|
59489
|
+
shOrder = inferSHOrder(coeffsPerColor);
|
|
59490
|
+
shCoeffs = new Float32Array(vertexCount * coeffsPerColor * 3);
|
|
59491
|
+
}
|
|
59492
|
+
const ix = propIndex("x");
|
|
59493
|
+
const iy = propIndex("y");
|
|
59494
|
+
const iz = propIndex("z");
|
|
59495
|
+
if (ix < 0 || iy < 0 || iz < 0) {
|
|
59496
|
+
throw new Error("PLY: Missing x/y/z for vertex");
|
|
59497
|
+
}
|
|
59498
|
+
const s0 = scale ? propIndex("scale_0") : -1;
|
|
59499
|
+
const s1 = scale ? propIndex("scale_1") : -1;
|
|
59500
|
+
const s2 = scale ? propIndex("scale_2") : -1;
|
|
59501
|
+
const r0 = rotation ? propIndex("rot_0") : -1;
|
|
59502
|
+
const r1 = rotation ? propIndex("rot_1") : -1;
|
|
59503
|
+
const r2 = rotation ? propIndex("rot_2") : -1;
|
|
59504
|
+
const r3 = rotation ? propIndex("rot_3") : -1;
|
|
59505
|
+
const oi = opacity ? propIndex("opacity") : -1;
|
|
59506
|
+
for (let v = 0; v < vertexCount; v++) {
|
|
59507
|
+
for (let pIdx = 0; pIdx < properties.length; pIdx++) {
|
|
59508
|
+
const prop = properties[pIdx];
|
|
59509
|
+
const value = parseASCIINumber(prop.type);
|
|
59510
|
+
if (pIdx === ix) {
|
|
59511
|
+
position[v * 3 + 0] = value;
|
|
59512
|
+
} else if (pIdx === iy) {
|
|
59513
|
+
position[v * 3 + 1] = value;
|
|
59514
|
+
} else if (pIdx === iz) {
|
|
59515
|
+
position[v * 3 + 2] = value;
|
|
59516
|
+
}
|
|
59517
|
+
if (scale && pIdx === s0) {
|
|
59518
|
+
scale[v * 3 + 0] = value;
|
|
59519
|
+
} else if (scale && pIdx === s1) {
|
|
59520
|
+
scale[v * 3 + 1] = value;
|
|
59521
|
+
} else if (scale && pIdx === s2) {
|
|
59522
|
+
scale[v * 3 + 2] = value;
|
|
59523
|
+
}
|
|
59524
|
+
if (rotation && pIdx === r0) {
|
|
59525
|
+
rotation[v * 4 + 3] = value;
|
|
59526
|
+
} else if (rotation && pIdx === r1) {
|
|
59527
|
+
rotation[v * 4 + 0] = value;
|
|
59528
|
+
} else if (rotation && pIdx === r2) {
|
|
59529
|
+
rotation[v * 4 + 1] = value;
|
|
59530
|
+
} else if (rotation && pIdx === r3) {
|
|
59531
|
+
rotation[v * 4 + 2] = value;
|
|
59532
|
+
}
|
|
59533
|
+
if (opacity && pIdx === oi) {
|
|
59534
|
+
opacity[v] = value;
|
|
59535
|
+
}
|
|
59536
|
+
if (hasSH && shCoeffs) {
|
|
59537
|
+
const coeffsPerColor = 1 + restIndices.length / 3;
|
|
59538
|
+
const baseIndex = v * coeffsPerColor * 3;
|
|
59539
|
+
if (pIdx === dcIdx[0]) {
|
|
59540
|
+
shCoeffs[baseIndex + 0] = value;
|
|
59541
|
+
} else if (pIdx === dcIdx[1]) {
|
|
59542
|
+
shCoeffs[baseIndex + coeffsPerColor + 0] = value;
|
|
59543
|
+
} else if (pIdx === dcIdx[2]) {
|
|
59544
|
+
shCoeffs[baseIndex + 2 * coeffsPerColor + 0] = value;
|
|
59545
|
+
}
|
|
59546
|
+
for (let i = 0; i < restIndices.length; i += 3) {
|
|
59547
|
+
const ri = restIndices[i + 0];
|
|
59548
|
+
const gi = restIndices[i + 1];
|
|
59549
|
+
const bi = restIndices[i + 2];
|
|
59550
|
+
if (pIdx === ri) {
|
|
59551
|
+
shCoeffs[baseIndex + (i / 3 + 1)] = value;
|
|
59552
|
+
} else if (pIdx === gi) {
|
|
59553
|
+
shCoeffs[baseIndex + coeffsPerColor + (i / 3 + 1)] = value;
|
|
59554
|
+
} else if (pIdx === bi) {
|
|
59555
|
+
shCoeffs[baseIndex + 2 * coeffsPerColor + (i / 3 + 1)] = value;
|
|
59556
|
+
}
|
|
59557
|
+
}
|
|
59558
|
+
}
|
|
59559
|
+
}
|
|
59560
|
+
}
|
|
59561
|
+
return {
|
|
59562
|
+
vertexCount,
|
|
59563
|
+
position,
|
|
59564
|
+
scale,
|
|
59565
|
+
rotation,
|
|
59566
|
+
opacity,
|
|
59567
|
+
sh: hasSH && shCoeffs ? { order: shOrder, coeffs: shCoeffs } : void 0
|
|
59568
|
+
};
|
|
59569
|
+
}
|
|
59570
|
+
function parsePlyMesh(buffer) {
|
|
59571
|
+
const header = parsePlyHeader(buffer);
|
|
59572
|
+
const { format, vertexCount, faceCount, properties, faceProperties, textureFiles, headerByteLength } = header;
|
|
59573
|
+
if (format === "ascii") {
|
|
59574
|
+
return parsePlyMeshASCII(buffer, header);
|
|
59575
|
+
} else {
|
|
59576
|
+
return parsePlyMeshBinary(buffer, header);
|
|
59577
|
+
}
|
|
59578
|
+
}
|
|
59579
|
+
function parsePlyMeshBinary(buffer, header) {
|
|
59580
|
+
const { vertexCount, faceCount, properties, faceProperties, textureFiles, headerByteLength } = header;
|
|
59581
|
+
const payload = new DataView(buffer, headerByteLength);
|
|
59582
|
+
const has = (n) => properties.find((p) => p.name === n) != null;
|
|
59583
|
+
const propIndex = (n) => properties.findIndex((p) => p.name === n);
|
|
59584
|
+
const hasTexcoord = faceProperties?.some((p) => p.name === "texcoord") || false;
|
|
59585
|
+
const hasTexnumber = faceProperties?.some((p) => p.name === "texnumber") || false;
|
|
59586
|
+
faceProperties?.find((p) => p.name === "texcoord");
|
|
59587
|
+
faceProperties?.find((p) => p.name === "texnumber");
|
|
59588
|
+
const position = new Float32Array(vertexCount * 3);
|
|
59589
|
+
const hasNormalData = has("nx") && has("ny") && has("nz");
|
|
59590
|
+
const normal = hasNormalData ? new Float32Array(vertexCount * 3) : new Float32Array(vertexCount * 3);
|
|
59591
|
+
const color = (has("red") || has("r")) && (has("green") || has("g")) && (has("blue") || has("b")) ? new Float32Array(vertexCount * 3) : void 0;
|
|
59592
|
+
const hasVertexUV = (has("u") || has("s")) && (has("v") || has("t"));
|
|
59593
|
+
const uv = hasVertexUV || hasTexcoord ? new Float32Array(vertexCount * 2) : void 0;
|
|
59594
|
+
const faceTexcoords = /* @__PURE__ */ new Map();
|
|
59595
|
+
const faceTexnumbers = hasTexnumber ? new Array(faceCount) : [];
|
|
59596
|
+
const propOffsets = [];
|
|
59597
|
+
let stride = 0;
|
|
59598
|
+
for (const p of properties) {
|
|
59599
|
+
propOffsets.push(stride);
|
|
59600
|
+
stride += byteSizeOfType(p.type);
|
|
59601
|
+
}
|
|
59602
|
+
let base = 0;
|
|
59603
|
+
for (let v = 0; v < vertexCount; v++) {
|
|
59604
|
+
const vOffset = base;
|
|
59605
|
+
const ix = propIndex("x");
|
|
59606
|
+
const iy = propIndex("y");
|
|
59607
|
+
const iz = propIndex("z");
|
|
59608
|
+
if (ix < 0 || iy < 0 || iz < 0) {
|
|
59609
|
+
throw new Error("PLY: Missing x/y/z for vertex");
|
|
59610
|
+
}
|
|
59611
|
+
position[v * 3 + 0] = readByType(payload, vOffset + propOffsets[ix], properties[ix].type);
|
|
59612
|
+
position[v * 3 + 1] = readByType(payload, vOffset + propOffsets[iy], properties[iy].type);
|
|
59613
|
+
position[v * 3 + 2] = readByType(payload, vOffset + propOffsets[iz], properties[iz].type);
|
|
59614
|
+
if (hasNormalData) {
|
|
59615
|
+
const nx = propIndex("nx");
|
|
59616
|
+
const ny = propIndex("ny");
|
|
59617
|
+
const nz = propIndex("nz");
|
|
59618
|
+
normal[v * 3 + 0] = readByType(payload, vOffset + propOffsets[nx], properties[nx].type);
|
|
59619
|
+
normal[v * 3 + 1] = readByType(payload, vOffset + propOffsets[ny], properties[ny].type);
|
|
59620
|
+
normal[v * 3 + 2] = readByType(payload, vOffset + propOffsets[nz], properties[nz].type);
|
|
59621
|
+
}
|
|
59622
|
+
if (color) {
|
|
59623
|
+
const rIdx = propIndex("red") >= 0 ? propIndex("red") : propIndex("r");
|
|
59624
|
+
const gIdx = propIndex("green") >= 0 ? propIndex("green") : propIndex("g");
|
|
59625
|
+
const bIdx = propIndex("blue") >= 0 ? propIndex("blue") : propIndex("b");
|
|
59626
|
+
if (rIdx >= 0 && gIdx >= 0 && bIdx >= 0) {
|
|
59627
|
+
let r = readByType(payload, vOffset + propOffsets[rIdx], properties[rIdx].type);
|
|
59628
|
+
let g = readByType(payload, vOffset + propOffsets[gIdx], properties[gIdx].type);
|
|
59629
|
+
let b = readByType(payload, vOffset + propOffsets[bIdx], properties[bIdx].type);
|
|
59630
|
+
if (properties[rIdx].type === "uchar" || properties[rIdx].type === "uint8") {
|
|
59631
|
+
r /= 255;
|
|
59632
|
+
g /= 255;
|
|
59633
|
+
b /= 255;
|
|
59634
|
+
}
|
|
59635
|
+
color[v * 3 + 0] = r;
|
|
59636
|
+
color[v * 3 + 1] = g;
|
|
59637
|
+
color[v * 3 + 2] = b;
|
|
59638
|
+
}
|
|
59639
|
+
}
|
|
59640
|
+
if (uv) {
|
|
59641
|
+
const uIdx = propIndex("u") >= 0 ? propIndex("u") : propIndex("s");
|
|
59642
|
+
const vIdx = propIndex("v") >= 0 ? propIndex("v") : propIndex("t");
|
|
59643
|
+
if (uIdx >= 0 && vIdx >= 0) {
|
|
59644
|
+
uv[v * 2 + 0] = readByType(payload, vOffset + propOffsets[uIdx], properties[uIdx].type);
|
|
59645
|
+
uv[v * 2 + 1] = readByType(payload, vOffset + propOffsets[vIdx], properties[vIdx].type);
|
|
59646
|
+
}
|
|
59647
|
+
}
|
|
59648
|
+
base += stride;
|
|
59649
|
+
}
|
|
59650
|
+
const indices = [];
|
|
59651
|
+
const triangleTexnumbers = [];
|
|
59652
|
+
const faceVertexUvs = [];
|
|
59653
|
+
let faceBase = base;
|
|
59654
|
+
uv && !hasVertexUV && !hasTexcoord ? new Array(vertexCount).fill(false) : null;
|
|
59655
|
+
for (let f = 0; f < faceCount; f++) {
|
|
59656
|
+
let currentOffset = faceBase;
|
|
59657
|
+
let faceIndices = [];
|
|
59658
|
+
let faceTexcoordArray = void 0;
|
|
59659
|
+
let faceTexnum = 0;
|
|
59660
|
+
let vertexCountInFace = 0;
|
|
59661
|
+
if (!faceProperties || faceProperties.length === 0) {
|
|
59662
|
+
throw new Error("PLY: Face element must have properties");
|
|
59663
|
+
}
|
|
59664
|
+
for (const prop of faceProperties) {
|
|
59665
|
+
if (prop.name === "vertex_indices") {
|
|
59666
|
+
const parts = prop.type.split(" ");
|
|
59667
|
+
if (parts.length !== 3 || parts[0] !== "list") {
|
|
59668
|
+
throw new Error(`PLY: Invalid vertex_indices property type: ${prop.type}`);
|
|
59669
|
+
}
|
|
59670
|
+
const countType = parts[1];
|
|
59671
|
+
const itemType = parts[2];
|
|
59672
|
+
vertexCountInFace = readByType(payload, currentOffset, countType);
|
|
59673
|
+
currentOffset += byteSizeOfType(countType);
|
|
59674
|
+
if (vertexCountInFace < 3) {
|
|
59675
|
+
throw new Error(`PLY: Face ${f} has less than 3 vertices`);
|
|
59676
|
+
}
|
|
59677
|
+
const indexSize = byteSizeOfType(itemType);
|
|
59678
|
+
faceIndices = [];
|
|
59679
|
+
for (let i = 0; i < vertexCountInFace; i++) {
|
|
59680
|
+
const idx = readByType(payload, currentOffset, itemType);
|
|
59681
|
+
faceIndices.push(idx);
|
|
59682
|
+
currentOffset += indexSize;
|
|
59683
|
+
}
|
|
59684
|
+
} else if (prop.name === "texcoord") {
|
|
59685
|
+
const parts = prop.type.split(" ");
|
|
59686
|
+
if (parts.length !== 3 || parts[0] !== "list") {
|
|
59687
|
+
throw new Error(`PLY: Invalid texcoord property type: ${prop.type}`);
|
|
59688
|
+
}
|
|
59689
|
+
const countType = parts[1];
|
|
59690
|
+
const itemType = parts[2];
|
|
59691
|
+
const texcoordCount = readByType(payload, currentOffset, countType);
|
|
59692
|
+
currentOffset += byteSizeOfType(countType);
|
|
59693
|
+
const itemSize = byteSizeOfType(itemType);
|
|
59694
|
+
faceTexcoordArray = new Float32Array(texcoordCount);
|
|
59695
|
+
for (let i = 0; i < texcoordCount; i++) {
|
|
59696
|
+
faceTexcoordArray[i] = readByType(payload, currentOffset, itemType);
|
|
59697
|
+
currentOffset += itemSize;
|
|
59698
|
+
}
|
|
59699
|
+
faceTexcoords.set(f, faceTexcoordArray);
|
|
59700
|
+
} else if (prop.name === "texnumber") {
|
|
59701
|
+
faceTexnum = readByType(payload, currentOffset, prop.type);
|
|
59702
|
+
currentOffset += byteSizeOfType(prop.type);
|
|
59703
|
+
faceTexnumbers[f] = faceTexnum;
|
|
59704
|
+
} else {
|
|
59705
|
+
if (prop.type.startsWith("list ")) {
|
|
59706
|
+
const parts = prop.type.split(" ");
|
|
59707
|
+
if (parts.length === 3) {
|
|
59708
|
+
const countType = parts[1];
|
|
59709
|
+
const itemType = parts[2];
|
|
59710
|
+
const count = readByType(payload, currentOffset, countType);
|
|
59711
|
+
currentOffset += byteSizeOfType(countType);
|
|
59712
|
+
const itemSize = byteSizeOfType(itemType);
|
|
59713
|
+
currentOffset += count * itemSize;
|
|
59714
|
+
}
|
|
59715
|
+
} else {
|
|
59716
|
+
currentOffset += byteSizeOfType(prop.type);
|
|
59717
|
+
}
|
|
59718
|
+
}
|
|
59719
|
+
}
|
|
59720
|
+
faceBase = currentOffset;
|
|
59721
|
+
const texnum = hasTexnumber ? faceTexnumbers[f] ?? 0 : 0;
|
|
59722
|
+
if (vertexCountInFace === 3) {
|
|
59723
|
+
indices.push(faceIndices[0], faceIndices[1], faceIndices[2]);
|
|
59724
|
+
if (hasTexnumber) {
|
|
59725
|
+
triangleTexnumbers.push(texnum);
|
|
59726
|
+
}
|
|
59727
|
+
if (hasTexcoord && faceTexcoordArray && faceTexcoordArray.length >= 6) {
|
|
59728
|
+
faceVertexUvs.push(
|
|
59729
|
+
faceTexcoordArray[0],
|
|
59730
|
+
1 - faceTexcoordArray[1],
|
|
59731
|
+
// vertex 0
|
|
59732
|
+
faceTexcoordArray[2],
|
|
59733
|
+
1 - faceTexcoordArray[3],
|
|
59734
|
+
// vertex 1
|
|
59735
|
+
faceTexcoordArray[4],
|
|
59736
|
+
1 - faceTexcoordArray[5]
|
|
59737
|
+
// vertex 2
|
|
59738
|
+
);
|
|
59739
|
+
}
|
|
59740
|
+
} else {
|
|
59741
|
+
for (let i = 1; i < vertexCountInFace - 1; i++) {
|
|
59742
|
+
indices.push(faceIndices[0], faceIndices[i], faceIndices[i + 1]);
|
|
59743
|
+
if (hasTexnumber) {
|
|
59744
|
+
triangleTexnumbers.push(texnum);
|
|
59745
|
+
}
|
|
59746
|
+
if (hasTexcoord && faceTexcoordArray && faceTexcoordArray.length >= vertexCountInFace * 2) {
|
|
59747
|
+
faceVertexUvs.push(
|
|
59748
|
+
faceTexcoordArray[0],
|
|
59749
|
+
1 - faceTexcoordArray[1],
|
|
59750
|
+
// vertex 0 (center of fan)
|
|
59751
|
+
faceTexcoordArray[i * 2 + 0],
|
|
59752
|
+
1 - faceTexcoordArray[i * 2 + 1],
|
|
59753
|
+
// vertex i
|
|
59754
|
+
faceTexcoordArray[(i + 1) * 2 + 0],
|
|
59755
|
+
1 - faceTexcoordArray[(i + 1) * 2 + 1]
|
|
59756
|
+
// vertex i+1
|
|
59757
|
+
);
|
|
59758
|
+
}
|
|
59759
|
+
}
|
|
59760
|
+
}
|
|
59761
|
+
}
|
|
59762
|
+
if (!hasNormalData) {
|
|
59763
|
+
for (let i = 0; i < vertexCount * 3; i++) {
|
|
59764
|
+
normal[i] = 0;
|
|
59765
|
+
}
|
|
59766
|
+
for (let i = 0; i < indices.length; i += 3) {
|
|
59767
|
+
const i0 = indices[i];
|
|
59768
|
+
const i1 = indices[i + 1];
|
|
59769
|
+
const i2 = indices[i + 2];
|
|
59770
|
+
const v0x = position[i0 * 3 + 0];
|
|
59771
|
+
const v0y = position[i0 * 3 + 1];
|
|
59772
|
+
const v0z = position[i0 * 3 + 2];
|
|
59773
|
+
const v1x = position[i1 * 3 + 0];
|
|
59774
|
+
const v1y = position[i1 * 3 + 1];
|
|
59775
|
+
const v1z = position[i1 * 3 + 2];
|
|
59776
|
+
const v2x = position[i2 * 3 + 0];
|
|
59777
|
+
const v2y = position[i2 * 3 + 1];
|
|
59778
|
+
const v2z = position[i2 * 3 + 2];
|
|
59779
|
+
const edge1x = v1x - v0x;
|
|
59780
|
+
const edge1y = v1y - v0y;
|
|
59781
|
+
const edge1z = v1z - v0z;
|
|
59782
|
+
const edge2x = v2x - v0x;
|
|
59783
|
+
const edge2y = v2y - v0y;
|
|
59784
|
+
const edge2z = v2z - v0z;
|
|
59785
|
+
const nx = edge1y * edge2z - edge1z * edge2y;
|
|
59786
|
+
const ny = edge1z * edge2x - edge1x * edge2z;
|
|
59787
|
+
const nz = edge1x * edge2y - edge1y * edge2x;
|
|
59788
|
+
normal[i0 * 3 + 0] += nx;
|
|
59789
|
+
normal[i0 * 3 + 1] += ny;
|
|
59790
|
+
normal[i0 * 3 + 2] += nz;
|
|
59791
|
+
normal[i1 * 3 + 0] += nx;
|
|
59792
|
+
normal[i1 * 3 + 1] += ny;
|
|
59793
|
+
normal[i1 * 3 + 2] += nz;
|
|
59794
|
+
normal[i2 * 3 + 0] += nx;
|
|
59795
|
+
normal[i2 * 3 + 1] += ny;
|
|
59796
|
+
normal[i2 * 3 + 2] += nz;
|
|
59797
|
+
}
|
|
59798
|
+
for (let v = 0; v < vertexCount; v++) {
|
|
59799
|
+
const nx = normal[v * 3 + 0];
|
|
59800
|
+
const ny = normal[v * 3 + 1];
|
|
59801
|
+
const nz = normal[v * 3 + 2];
|
|
59802
|
+
const length = Math.sqrt(nx * nx + ny * ny + nz * nz);
|
|
59803
|
+
if (length > 1e-5) {
|
|
59804
|
+
normal[v * 3 + 0] = nx / length;
|
|
59805
|
+
normal[v * 3 + 1] = ny / length;
|
|
59806
|
+
normal[v * 3 + 2] = nz / length;
|
|
59807
|
+
} else {
|
|
59808
|
+
normal[v * 3 + 0] = 0;
|
|
59809
|
+
normal[v * 3 + 1] = 1;
|
|
59810
|
+
normal[v * 3 + 2] = 0;
|
|
59811
|
+
}
|
|
59812
|
+
}
|
|
59813
|
+
}
|
|
59814
|
+
let finalPosition = position;
|
|
59815
|
+
let finalNormal = normal;
|
|
59816
|
+
let finalColor = color;
|
|
59817
|
+
let finalUv = void 0;
|
|
59818
|
+
let finalIndices = void 0;
|
|
59819
|
+
if (hasTexcoord && faceVertexUvs.length > 0) {
|
|
59820
|
+
const triangleCount = indices.length / 3;
|
|
59821
|
+
const expandedPosition = new Float32Array(triangleCount * 3 * 3);
|
|
59822
|
+
const expandedNormal = new Float32Array(triangleCount * 3 * 3);
|
|
59823
|
+
const expandedColor = color ? new Float32Array(triangleCount * 3 * 3) : void 0;
|
|
59824
|
+
finalUv = new Float32Array(faceVertexUvs);
|
|
59825
|
+
for (let i = 0; i < triangleCount; i++) {
|
|
59826
|
+
const baseIdx = i * 3;
|
|
59827
|
+
const i0 = indices[baseIdx + 0];
|
|
59828
|
+
const i1 = indices[baseIdx + 1];
|
|
59829
|
+
const i2 = indices[baseIdx + 2];
|
|
59830
|
+
expandedPosition[i * 9 + 0] = position[i0 * 3 + 0];
|
|
59831
|
+
expandedPosition[i * 9 + 1] = position[i0 * 3 + 1];
|
|
59832
|
+
expandedPosition[i * 9 + 2] = position[i0 * 3 + 2];
|
|
59833
|
+
expandedPosition[i * 9 + 3] = position[i1 * 3 + 0];
|
|
59834
|
+
expandedPosition[i * 9 + 4] = position[i1 * 3 + 1];
|
|
59835
|
+
expandedPosition[i * 9 + 5] = position[i1 * 3 + 2];
|
|
59836
|
+
expandedPosition[i * 9 + 6] = position[i2 * 3 + 0];
|
|
59837
|
+
expandedPosition[i * 9 + 7] = position[i2 * 3 + 1];
|
|
59838
|
+
expandedPosition[i * 9 + 8] = position[i2 * 3 + 2];
|
|
59839
|
+
expandedNormal[i * 9 + 0] = normal[i0 * 3 + 0];
|
|
59840
|
+
expandedNormal[i * 9 + 1] = normal[i0 * 3 + 1];
|
|
59841
|
+
expandedNormal[i * 9 + 2] = normal[i0 * 3 + 2];
|
|
59842
|
+
expandedNormal[i * 9 + 3] = normal[i1 * 3 + 0];
|
|
59843
|
+
expandedNormal[i * 9 + 4] = normal[i1 * 3 + 1];
|
|
59844
|
+
expandedNormal[i * 9 + 5] = normal[i1 * 3 + 2];
|
|
59845
|
+
expandedNormal[i * 9 + 6] = normal[i2 * 3 + 0];
|
|
59846
|
+
expandedNormal[i * 9 + 7] = normal[i2 * 3 + 1];
|
|
59847
|
+
expandedNormal[i * 9 + 8] = normal[i2 * 3 + 2];
|
|
59848
|
+
if (expandedColor && color) {
|
|
59849
|
+
expandedColor[i * 9 + 0] = color[i0 * 3 + 0];
|
|
59850
|
+
expandedColor[i * 9 + 1] = color[i0 * 3 + 1];
|
|
59851
|
+
expandedColor[i * 9 + 2] = color[i0 * 3 + 2];
|
|
59852
|
+
expandedColor[i * 9 + 3] = color[i1 * 3 + 0];
|
|
59853
|
+
expandedColor[i * 9 + 4] = color[i1 * 3 + 1];
|
|
59854
|
+
expandedColor[i * 9 + 5] = color[i1 * 3 + 2];
|
|
59855
|
+
expandedColor[i * 9 + 6] = color[i2 * 3 + 0];
|
|
59856
|
+
expandedColor[i * 9 + 7] = color[i2 * 3 + 1];
|
|
59857
|
+
expandedColor[i * 9 + 8] = color[i2 * 3 + 2];
|
|
59858
|
+
}
|
|
59859
|
+
}
|
|
59860
|
+
finalPosition = expandedPosition;
|
|
59861
|
+
finalNormal = expandedNormal;
|
|
59862
|
+
finalColor = expandedColor;
|
|
59863
|
+
const sequentialIndices = new Uint32Array(triangleCount * 3);
|
|
59864
|
+
for (let i = 0; i < triangleCount * 3; i++) {
|
|
59865
|
+
sequentialIndices[i] = i;
|
|
59866
|
+
}
|
|
59867
|
+
finalIndices = sequentialIndices;
|
|
59868
|
+
} else {
|
|
59869
|
+
finalIndices = new Uint32Array(indices);
|
|
59870
|
+
finalUv = uv;
|
|
59871
|
+
}
|
|
59872
|
+
return {
|
|
59873
|
+
vertexCount: hasTexcoord && faceVertexUvs.length > 0 ? finalPosition.length / 3 : vertexCount,
|
|
59874
|
+
faceCount,
|
|
59875
|
+
position: finalPosition,
|
|
59876
|
+
normal: finalNormal,
|
|
59877
|
+
color: finalColor,
|
|
59878
|
+
uv: finalUv,
|
|
59879
|
+
indices: finalIndices,
|
|
59880
|
+
textureFiles: textureFiles.length > 0 ? textureFiles : void 0,
|
|
59881
|
+
triangleTexnumbers: triangleTexnumbers.length > 0 ? triangleTexnumbers : void 0
|
|
59882
|
+
};
|
|
59883
|
+
}
|
|
59884
|
+
function parsePlyMeshASCII(buffer, header) {
|
|
59885
|
+
const { vertexCount, faceCount, properties, faceProperties, textureFiles, headerByteLength } = header;
|
|
59886
|
+
const text = new TextDecoder("utf-8").decode(buffer);
|
|
59887
|
+
const headerEnd = text.indexOf("end_header");
|
|
59888
|
+
if (headerEnd < 0) {
|
|
59889
|
+
throw new Error("PLY: Invalid PLY header");
|
|
59890
|
+
}
|
|
59891
|
+
let bodyStart = headerEnd + "end_header".length;
|
|
59892
|
+
while (bodyStart < text.length && (text[bodyStart] === " " || text[bodyStart] === "\n" || text[bodyStart] === "\r")) {
|
|
59893
|
+
bodyStart++;
|
|
59894
|
+
}
|
|
59895
|
+
const bodyText = text.substring(bodyStart);
|
|
59896
|
+
const tokens = bodyText.split(/\s+/).filter((token) => token.length > 0);
|
|
59897
|
+
let tokenIndex = 0;
|
|
59898
|
+
const has = (n) => properties.find((p) => p.name === n) != null;
|
|
59899
|
+
const parseASCIINumber = (type) => {
|
|
59900
|
+
if (tokenIndex >= tokens.length) {
|
|
59901
|
+
throw new Error("PLY: Unexpected end of file");
|
|
59902
|
+
}
|
|
59903
|
+
const value = tokens[tokenIndex++];
|
|
59904
|
+
switch (type) {
|
|
59905
|
+
case "char":
|
|
59906
|
+
case "uchar":
|
|
59907
|
+
case "short":
|
|
59908
|
+
case "ushort":
|
|
59909
|
+
case "int":
|
|
59910
|
+
case "uint":
|
|
59911
|
+
case "int8":
|
|
59912
|
+
case "uint8":
|
|
59913
|
+
case "int16":
|
|
59914
|
+
case "uint16":
|
|
59915
|
+
case "int32":
|
|
59916
|
+
case "uint32":
|
|
59917
|
+
return parseInt(value);
|
|
59918
|
+
case "float":
|
|
59919
|
+
case "double":
|
|
59920
|
+
case "float32":
|
|
59921
|
+
case "float64":
|
|
59922
|
+
return parseFloat(value);
|
|
59923
|
+
default:
|
|
59924
|
+
return parseFloat(value);
|
|
59925
|
+
}
|
|
59926
|
+
};
|
|
59927
|
+
const position = new Float32Array(vertexCount * 3);
|
|
59928
|
+
const hasNormalData = has("nx") && has("ny") && has("nz");
|
|
59929
|
+
const normal = hasNormalData ? new Float32Array(vertexCount * 3) : new Float32Array(vertexCount * 3);
|
|
59930
|
+
const color = (has("red") || has("r")) && (has("green") || has("g")) && (has("blue") || has("b")) ? new Float32Array(vertexCount * 3) : void 0;
|
|
59931
|
+
const hasVertexUV = (has("u") || has("s")) && (has("v") || has("t"));
|
|
59932
|
+
const hasTexcoord = faceProperties?.some((p) => p.name === "texcoord") || false;
|
|
59933
|
+
const uv = hasVertexUV || hasTexcoord ? new Float32Array(vertexCount * 2) : void 0;
|
|
59934
|
+
const faceTexcoords = /* @__PURE__ */ new Map();
|
|
59935
|
+
const hasTexnumber = faceProperties?.some((p) => p.name === "texnumber") || false;
|
|
59936
|
+
const faceTexnumbers = hasTexnumber ? new Array(faceCount) : [];
|
|
59937
|
+
const indices = [];
|
|
59938
|
+
const triangleTexnumbers = [];
|
|
59939
|
+
const faceVertexUvs = [];
|
|
59940
|
+
const propIndex = (n) => properties.findIndex((p) => p.name === n);
|
|
59941
|
+
const xIdx = propIndex("x");
|
|
59942
|
+
const yIdx = propIndex("y");
|
|
59943
|
+
const zIdx = propIndex("z");
|
|
59944
|
+
const nxIdx = hasNormalData ? propIndex("nx") : -1;
|
|
59945
|
+
const nyIdx = hasNormalData ? propIndex("ny") : -1;
|
|
59946
|
+
const nzIdx = hasNormalData ? propIndex("nz") : -1;
|
|
59947
|
+
const rIdx = color ? propIndex("red") >= 0 ? propIndex("red") : propIndex("r") : -1;
|
|
59948
|
+
const gIdx = color ? propIndex("green") >= 0 ? propIndex("green") : propIndex("g") : -1;
|
|
59949
|
+
const bIdx = color ? propIndex("blue") >= 0 ? propIndex("blue") : propIndex("b") : -1;
|
|
59950
|
+
const uIdx = uv && hasVertexUV ? propIndex("u") >= 0 ? propIndex("u") : propIndex("s") : -1;
|
|
59951
|
+
const vIdx = uv && hasVertexUV ? propIndex("v") >= 0 ? propIndex("v") : propIndex("t") : -1;
|
|
59952
|
+
for (let v = 0; v < vertexCount; v++) {
|
|
59953
|
+
for (let pIdx = 0; pIdx < properties.length; pIdx++) {
|
|
59954
|
+
const prop = properties[pIdx];
|
|
59955
|
+
const value = parseASCIINumber(prop.type);
|
|
59956
|
+
if (pIdx === xIdx) {
|
|
59957
|
+
position[v * 3 + 0] = value;
|
|
59958
|
+
} else if (pIdx === yIdx) {
|
|
59959
|
+
position[v * 3 + 1] = value;
|
|
59960
|
+
} else if (pIdx === zIdx) {
|
|
59961
|
+
position[v * 3 + 2] = value;
|
|
59962
|
+
} else if (pIdx === nxIdx) {
|
|
59963
|
+
normal[v * 3 + 0] = value;
|
|
59964
|
+
} else if (pIdx === nyIdx) {
|
|
59965
|
+
normal[v * 3 + 1] = value;
|
|
59966
|
+
} else if (pIdx === nzIdx) {
|
|
59967
|
+
normal[v * 3 + 2] = value;
|
|
59968
|
+
} else if (pIdx === rIdx && color) {
|
|
59969
|
+
color[v * 3 + 0] = prop.type === "uchar" || prop.type === "uint8" ? value / 255 : value;
|
|
59970
|
+
} else if (pIdx === gIdx && color) {
|
|
59971
|
+
color[v * 3 + 1] = prop.type === "uchar" || prop.type === "uint8" ? value / 255 : value;
|
|
59972
|
+
} else if (pIdx === bIdx && color) {
|
|
59973
|
+
color[v * 3 + 2] = prop.type === "uchar" || prop.type === "uint8" ? value / 255 : value;
|
|
59974
|
+
} else if (pIdx === uIdx && uv) {
|
|
59975
|
+
uv[v * 2 + 0] = value;
|
|
59976
|
+
} else if (pIdx === vIdx && uv) {
|
|
59977
|
+
uv[v * 2 + 1] = value;
|
|
59978
|
+
}
|
|
59979
|
+
}
|
|
59980
|
+
}
|
|
59981
|
+
for (let f = 0; f < faceCount; f++) {
|
|
59982
|
+
let faceIndices = [];
|
|
59983
|
+
let faceTexcoordArray = void 0;
|
|
59984
|
+
let faceTexnum = 0;
|
|
59985
|
+
for (const prop of faceProperties || []) {
|
|
59986
|
+
if (prop.name === "vertex_indices") {
|
|
59987
|
+
const parts = prop.type.split(" ");
|
|
59988
|
+
const countType = parts[1];
|
|
59989
|
+
const itemType = parts[2];
|
|
59990
|
+
const vertexCountInFace2 = parseASCIINumber(countType);
|
|
59991
|
+
faceIndices = [];
|
|
59992
|
+
for (let i = 0; i < vertexCountInFace2; i++) {
|
|
59993
|
+
faceIndices.push(parseASCIINumber(itemType));
|
|
59994
|
+
}
|
|
59995
|
+
} else if (prop.name === "texcoord") {
|
|
59996
|
+
const parts = prop.type.split(" ");
|
|
59997
|
+
const countType = parts[1];
|
|
59998
|
+
const itemType = parts[2];
|
|
59999
|
+
const texcoordCount = parseASCIINumber(countType);
|
|
60000
|
+
faceTexcoordArray = new Float32Array(texcoordCount);
|
|
60001
|
+
for (let i = 0; i < texcoordCount; i++) {
|
|
60002
|
+
faceTexcoordArray[i] = parseASCIINumber(itemType);
|
|
60003
|
+
}
|
|
60004
|
+
faceTexcoords.set(f, faceTexcoordArray);
|
|
60005
|
+
} else if (prop.name === "texnumber") {
|
|
60006
|
+
faceTexnum = parseASCIINumber(prop.type);
|
|
60007
|
+
faceTexnumbers[f] = faceTexnum;
|
|
60008
|
+
}
|
|
60009
|
+
}
|
|
60010
|
+
const vertexCountInFace = faceIndices.length;
|
|
60011
|
+
const texnum = hasTexnumber ? faceTexnumbers[f] ?? 0 : 0;
|
|
60012
|
+
if (vertexCountInFace === 3) {
|
|
60013
|
+
indices.push(faceIndices[0], faceIndices[1], faceIndices[2]);
|
|
60014
|
+
if (hasTexnumber) {
|
|
60015
|
+
triangleTexnumbers.push(texnum);
|
|
60016
|
+
}
|
|
60017
|
+
if (hasTexcoord && faceTexcoordArray && faceTexcoordArray.length >= 6) {
|
|
60018
|
+
faceVertexUvs.push(
|
|
60019
|
+
faceTexcoordArray[0],
|
|
60020
|
+
1 - faceTexcoordArray[1],
|
|
60021
|
+
faceTexcoordArray[2],
|
|
60022
|
+
1 - faceTexcoordArray[3],
|
|
60023
|
+
faceTexcoordArray[4],
|
|
60024
|
+
1 - faceTexcoordArray[5]
|
|
60025
|
+
);
|
|
60026
|
+
}
|
|
60027
|
+
} else {
|
|
60028
|
+
for (let i = 1; i < vertexCountInFace - 1; i++) {
|
|
60029
|
+
indices.push(faceIndices[0], faceIndices[i], faceIndices[i + 1]);
|
|
60030
|
+
if (hasTexnumber) {
|
|
60031
|
+
triangleTexnumbers.push(texnum);
|
|
60032
|
+
}
|
|
60033
|
+
if (hasTexcoord && faceTexcoordArray && faceTexcoordArray.length >= vertexCountInFace * 2) {
|
|
60034
|
+
faceVertexUvs.push(
|
|
60035
|
+
faceTexcoordArray[0],
|
|
60036
|
+
1 - faceTexcoordArray[1],
|
|
60037
|
+
faceTexcoordArray[i * 2 + 0],
|
|
60038
|
+
1 - faceTexcoordArray[i * 2 + 1],
|
|
60039
|
+
faceTexcoordArray[(i + 1) * 2 + 0],
|
|
60040
|
+
1 - faceTexcoordArray[(i + 1) * 2 + 1]
|
|
60041
|
+
);
|
|
60042
|
+
}
|
|
60043
|
+
}
|
|
60044
|
+
}
|
|
60045
|
+
}
|
|
60046
|
+
if (!hasNormalData) {
|
|
60047
|
+
for (let i = 0; i < vertexCount * 3; i++) {
|
|
60048
|
+
normal[i] = 0;
|
|
60049
|
+
}
|
|
60050
|
+
for (let i = 0; i < indices.length; i += 3) {
|
|
60051
|
+
const i0 = indices[i];
|
|
60052
|
+
const i1 = indices[i + 1];
|
|
60053
|
+
const i2 = indices[i + 2];
|
|
60054
|
+
const v0x = position[i0 * 3 + 0];
|
|
60055
|
+
const v0y = position[i0 * 3 + 1];
|
|
60056
|
+
const v0z = position[i0 * 3 + 2];
|
|
60057
|
+
const v1x = position[i1 * 3 + 0];
|
|
60058
|
+
const v1y = position[i1 * 3 + 1];
|
|
60059
|
+
const v1z = position[i1 * 3 + 2];
|
|
60060
|
+
const v2x = position[i2 * 3 + 0];
|
|
60061
|
+
const v2y = position[i2 * 3 + 1];
|
|
60062
|
+
const v2z = position[i2 * 3 + 2];
|
|
60063
|
+
const edge1x = v1x - v0x;
|
|
60064
|
+
const edge1y = v1y - v0y;
|
|
60065
|
+
const edge1z = v1z - v0z;
|
|
60066
|
+
const edge2x = v2x - v0x;
|
|
60067
|
+
const edge2y = v2y - v0y;
|
|
60068
|
+
const edge2z = v2z - v0z;
|
|
60069
|
+
const nx = edge1y * edge2z - edge1z * edge2y;
|
|
60070
|
+
const ny = edge1z * edge2x - edge1x * edge2z;
|
|
60071
|
+
const nz = edge1x * edge2y - edge1y * edge2x;
|
|
60072
|
+
normal[i0 * 3 + 0] += nx;
|
|
60073
|
+
normal[i0 * 3 + 1] += ny;
|
|
60074
|
+
normal[i0 * 3 + 2] += nz;
|
|
60075
|
+
normal[i1 * 3 + 0] += nx;
|
|
60076
|
+
normal[i1 * 3 + 1] += ny;
|
|
60077
|
+
normal[i1 * 3 + 2] += nz;
|
|
60078
|
+
normal[i2 * 3 + 0] += nx;
|
|
60079
|
+
normal[i2 * 3 + 1] += ny;
|
|
60080
|
+
normal[i2 * 3 + 2] += nz;
|
|
60081
|
+
}
|
|
60082
|
+
for (let v = 0; v < vertexCount; v++) {
|
|
60083
|
+
const nx = normal[v * 3 + 0];
|
|
60084
|
+
const ny = normal[v * 3 + 1];
|
|
60085
|
+
const nz = normal[v * 3 + 2];
|
|
60086
|
+
const length = Math.sqrt(nx * nx + ny * ny + nz * nz);
|
|
60087
|
+
if (length > 1e-5) {
|
|
60088
|
+
normal[v * 3 + 0] = nx / length;
|
|
60089
|
+
normal[v * 3 + 1] = ny / length;
|
|
60090
|
+
normal[v * 3 + 2] = nz / length;
|
|
60091
|
+
} else {
|
|
60092
|
+
normal[v * 3 + 0] = 0;
|
|
60093
|
+
normal[v * 3 + 1] = 1;
|
|
60094
|
+
normal[v * 3 + 2] = 0;
|
|
60095
|
+
}
|
|
60096
|
+
}
|
|
60097
|
+
}
|
|
60098
|
+
let finalPosition = position;
|
|
60099
|
+
let finalNormal = normal;
|
|
60100
|
+
let finalColor = color;
|
|
60101
|
+
let finalUv = void 0;
|
|
60102
|
+
let finalIndices = void 0;
|
|
60103
|
+
if (hasTexcoord && faceVertexUvs.length > 0) {
|
|
60104
|
+
const triangleCount = indices.length / 3;
|
|
60105
|
+
const expandedPosition = new Float32Array(triangleCount * 3 * 3);
|
|
60106
|
+
const expandedNormal = new Float32Array(triangleCount * 3 * 3);
|
|
60107
|
+
const expandedColor = color ? new Float32Array(triangleCount * 3 * 3) : void 0;
|
|
60108
|
+
finalUv = new Float32Array(faceVertexUvs);
|
|
60109
|
+
for (let i = 0; i < triangleCount; i++) {
|
|
60110
|
+
const baseIdx = i * 3;
|
|
60111
|
+
const i0 = indices[baseIdx + 0];
|
|
60112
|
+
const i1 = indices[baseIdx + 1];
|
|
60113
|
+
const i2 = indices[baseIdx + 2];
|
|
60114
|
+
expandedPosition[i * 9 + 0] = position[i0 * 3 + 0];
|
|
60115
|
+
expandedPosition[i * 9 + 1] = position[i0 * 3 + 1];
|
|
60116
|
+
expandedPosition[i * 9 + 2] = position[i0 * 3 + 2];
|
|
60117
|
+
expandedPosition[i * 9 + 3] = position[i1 * 3 + 0];
|
|
60118
|
+
expandedPosition[i * 9 + 4] = position[i1 * 3 + 1];
|
|
60119
|
+
expandedPosition[i * 9 + 5] = position[i1 * 3 + 2];
|
|
60120
|
+
expandedPosition[i * 9 + 6] = position[i2 * 3 + 0];
|
|
60121
|
+
expandedPosition[i * 9 + 7] = position[i2 * 3 + 1];
|
|
60122
|
+
expandedPosition[i * 9 + 8] = position[i2 * 3 + 2];
|
|
60123
|
+
expandedNormal[i * 9 + 0] = normal[i0 * 3 + 0];
|
|
60124
|
+
expandedNormal[i * 9 + 1] = normal[i0 * 3 + 1];
|
|
60125
|
+
expandedNormal[i * 9 + 2] = normal[i0 * 3 + 2];
|
|
60126
|
+
expandedNormal[i * 9 + 3] = normal[i1 * 3 + 0];
|
|
60127
|
+
expandedNormal[i * 9 + 4] = normal[i1 * 3 + 1];
|
|
60128
|
+
expandedNormal[i * 9 + 5] = normal[i1 * 3 + 2];
|
|
60129
|
+
expandedNormal[i * 9 + 6] = normal[i2 * 3 + 0];
|
|
60130
|
+
expandedNormal[i * 9 + 7] = normal[i2 * 3 + 1];
|
|
60131
|
+
expandedNormal[i * 9 + 8] = normal[i2 * 3 + 2];
|
|
60132
|
+
if (expandedColor && color) {
|
|
60133
|
+
expandedColor[i * 9 + 0] = color[i0 * 3 + 0];
|
|
60134
|
+
expandedColor[i * 9 + 1] = color[i0 * 3 + 1];
|
|
60135
|
+
expandedColor[i * 9 + 2] = color[i0 * 3 + 2];
|
|
60136
|
+
expandedColor[i * 9 + 3] = color[i1 * 3 + 0];
|
|
60137
|
+
expandedColor[i * 9 + 4] = color[i1 * 3 + 1];
|
|
60138
|
+
expandedColor[i * 9 + 5] = color[i1 * 3 + 2];
|
|
60139
|
+
expandedColor[i * 9 + 6] = color[i2 * 3 + 0];
|
|
60140
|
+
expandedColor[i * 9 + 7] = color[i2 * 3 + 1];
|
|
60141
|
+
expandedColor[i * 9 + 8] = color[i2 * 3 + 2];
|
|
60142
|
+
}
|
|
60143
|
+
}
|
|
60144
|
+
finalPosition = expandedPosition;
|
|
60145
|
+
finalNormal = expandedNormal;
|
|
60146
|
+
finalColor = expandedColor;
|
|
60147
|
+
const sequentialIndices = new Uint32Array(triangleCount * 3);
|
|
60148
|
+
for (let i = 0; i < triangleCount * 3; i++) {
|
|
60149
|
+
sequentialIndices[i] = i;
|
|
60150
|
+
}
|
|
60151
|
+
finalIndices = sequentialIndices;
|
|
60152
|
+
} else {
|
|
60153
|
+
finalIndices = new Uint32Array(indices);
|
|
60154
|
+
finalUv = uv;
|
|
60155
|
+
}
|
|
60156
|
+
return {
|
|
60157
|
+
vertexCount: hasTexcoord && faceVertexUvs.length > 0 ? finalPosition.length / 3 : vertexCount,
|
|
60158
|
+
faceCount,
|
|
60159
|
+
position: finalPosition,
|
|
60160
|
+
normal: finalNormal,
|
|
60161
|
+
color: finalColor,
|
|
60162
|
+
uv: finalUv,
|
|
60163
|
+
indices: finalIndices,
|
|
60164
|
+
textureFiles: textureFiles.length > 0 ? textureFiles : void 0,
|
|
60165
|
+
triangleTexnumbers: triangleTexnumbers.length > 0 ? triangleTexnumbers : void 0
|
|
60166
|
+
};
|
|
60167
|
+
}
|
|
59371
60168
|
|
|
59372
60169
|
class GaussianSplatParser extends ParserBase {
|
|
59373
60170
|
static format = ParserFormat.BIN;
|
|
@@ -59476,6 +60273,133 @@ fn frag(){
|
|
|
59476
60273
|
class KHR_materials_ior {
|
|
59477
60274
|
}
|
|
59478
60275
|
|
|
60276
|
+
class PlyParser extends ParserBase {
|
|
60277
|
+
static format = ParserFormat.BIN;
|
|
60278
|
+
async parseBuffer(buffer) {
|
|
60279
|
+
const header = parsePlyHeader(buffer);
|
|
60280
|
+
switch (header.mode) {
|
|
60281
|
+
case PlyMode.Splat: {
|
|
60282
|
+
const plyData = parsePlyGaussianSplat(buffer);
|
|
60283
|
+
const asset = {
|
|
60284
|
+
count: plyData.vertexCount,
|
|
60285
|
+
position: plyData.position,
|
|
60286
|
+
rotation: plyData.rotation,
|
|
60287
|
+
scale: plyData.scale,
|
|
60288
|
+
opacity: plyData.opacity,
|
|
60289
|
+
sh: plyData.sh
|
|
60290
|
+
};
|
|
60291
|
+
asset.bbox = computeAABBFromPositions(plyData.position);
|
|
60292
|
+
const gsplatObj = new exports.Object3D();
|
|
60293
|
+
gsplatObj.name = "GaussianSplat";
|
|
60294
|
+
const renderer = gsplatObj.addComponent(exports.GSplatRenderer);
|
|
60295
|
+
renderer.initAsset(asset);
|
|
60296
|
+
this.data = gsplatObj;
|
|
60297
|
+
break;
|
|
60298
|
+
}
|
|
60299
|
+
case PlyMode.PointCloud: {
|
|
60300
|
+
break;
|
|
60301
|
+
}
|
|
60302
|
+
case PlyMode.Mesh: {
|
|
60303
|
+
const plyData = parsePlyMesh(buffer);
|
|
60304
|
+
const rootObj = new exports.Object3D();
|
|
60305
|
+
rootObj.name = "PLYMesh";
|
|
60306
|
+
const textureGroups = /* @__PURE__ */ new Map();
|
|
60307
|
+
if (plyData.triangleTexnumbers && plyData.triangleTexnumbers.length > 0) {
|
|
60308
|
+
for (let i = 0; i < plyData.triangleTexnumbers.length; i++) {
|
|
60309
|
+
const texnum = plyData.triangleTexnumbers[i];
|
|
60310
|
+
if (!textureGroups.has(texnum)) {
|
|
60311
|
+
textureGroups.set(texnum, []);
|
|
60312
|
+
}
|
|
60313
|
+
textureGroups.get(texnum).push(i);
|
|
60314
|
+
}
|
|
60315
|
+
} else {
|
|
60316
|
+
const triangleCount = plyData.indices.length / 3;
|
|
60317
|
+
const allTriangles = [];
|
|
60318
|
+
for (let i = 0; i < triangleCount; i++) {
|
|
60319
|
+
allTriangles.push(i);
|
|
60320
|
+
}
|
|
60321
|
+
textureGroups.set(0, allTriangles);
|
|
60322
|
+
}
|
|
60323
|
+
const materials = /* @__PURE__ */ new Map();
|
|
60324
|
+
if (plyData.textureFiles && plyData.textureFiles.length > 0) {
|
|
60325
|
+
const promiseList = [];
|
|
60326
|
+
for (let texnum = 0; texnum < plyData.textureFiles.length; texnum++) {
|
|
60327
|
+
const material = new LitMaterial();
|
|
60328
|
+
const texturePath = StringUtil.normalizePath(
|
|
60329
|
+
this.baseUrl + plyData.textureFiles[texnum]
|
|
60330
|
+
);
|
|
60331
|
+
promiseList.push(Engine3D.res.loadTexture(texturePath).then((texture) => {
|
|
60332
|
+
material.baseMap = texture;
|
|
60333
|
+
materials.set(texnum, material);
|
|
60334
|
+
}));
|
|
60335
|
+
}
|
|
60336
|
+
await Promise.all(promiseList);
|
|
60337
|
+
}
|
|
60338
|
+
if (materials.size === 0) {
|
|
60339
|
+
materials.set(0, new LitMaterial());
|
|
60340
|
+
}
|
|
60341
|
+
for (const [texnum, triangleIndices] of textureGroups) {
|
|
60342
|
+
const groupIndices = [];
|
|
60343
|
+
for (const triIdx of triangleIndices) {
|
|
60344
|
+
const baseIdx = triIdx * 3;
|
|
60345
|
+
groupIndices.push(
|
|
60346
|
+
plyData.indices[baseIdx + 0],
|
|
60347
|
+
plyData.indices[baseIdx + 1],
|
|
60348
|
+
plyData.indices[baseIdx + 2]
|
|
60349
|
+
);
|
|
60350
|
+
}
|
|
60351
|
+
const geometry = new GeometryBase();
|
|
60352
|
+
geometry.setAttribute(
|
|
60353
|
+
VertexAttributeName.position,
|
|
60354
|
+
plyData.position
|
|
60355
|
+
);
|
|
60356
|
+
geometry.setAttribute(
|
|
60357
|
+
VertexAttributeName.normal,
|
|
60358
|
+
plyData.normal
|
|
60359
|
+
);
|
|
60360
|
+
if (plyData.uv) {
|
|
60361
|
+
geometry.setAttribute(
|
|
60362
|
+
VertexAttributeName.uv,
|
|
60363
|
+
plyData.uv
|
|
60364
|
+
);
|
|
60365
|
+
}
|
|
60366
|
+
if (plyData.color) {
|
|
60367
|
+
geometry.setAttribute(
|
|
60368
|
+
VertexAttributeName.color,
|
|
60369
|
+
plyData.color
|
|
60370
|
+
);
|
|
60371
|
+
}
|
|
60372
|
+
geometry.setIndices(new Uint32Array(groupIndices));
|
|
60373
|
+
geometry.addSubGeometry({
|
|
60374
|
+
indexStart: 0,
|
|
60375
|
+
indexCount: groupIndices.length,
|
|
60376
|
+
vertexStart: 0,
|
|
60377
|
+
vertexCount: 0,
|
|
60378
|
+
firstStart: 0,
|
|
60379
|
+
index: 0,
|
|
60380
|
+
topology: 0
|
|
60381
|
+
});
|
|
60382
|
+
let material = materials.get(texnum);
|
|
60383
|
+
if (!material) {
|
|
60384
|
+
material = materials.values().next().value || new LitMaterial();
|
|
60385
|
+
}
|
|
60386
|
+
const meshObj = new exports.Object3D();
|
|
60387
|
+
meshObj.name = `PLYMesh_Texture_${texnum}`;
|
|
60388
|
+
const renderer = meshObj.addComponent(exports.MeshRenderer);
|
|
60389
|
+
renderer.geometry = geometry;
|
|
60390
|
+
renderer.material = material;
|
|
60391
|
+
rootObj.addChild(meshObj);
|
|
60392
|
+
}
|
|
60393
|
+
this.data = rootObj;
|
|
60394
|
+
break;
|
|
60395
|
+
}
|
|
60396
|
+
}
|
|
60397
|
+
}
|
|
60398
|
+
verification() {
|
|
60399
|
+
return !!this.data;
|
|
60400
|
+
}
|
|
60401
|
+
}
|
|
60402
|
+
|
|
59479
60403
|
class PrefabBoneData {
|
|
59480
60404
|
boneName;
|
|
59481
60405
|
bonePath;
|
|
@@ -69459,6 +70383,8 @@ fn frag(){
|
|
|
69459
70383
|
exports.Plane3D = Plane3D;
|
|
69460
70384
|
exports.PlaneClassification = PlaneClassification;
|
|
69461
70385
|
exports.PlaneGeometry = PlaneGeometry;
|
|
70386
|
+
exports.PlyMode = PlyMode;
|
|
70387
|
+
exports.PlyParser = PlyParser;
|
|
69462
70388
|
exports.PointClassification = PointClassification;
|
|
69463
70389
|
exports.PointLightShadowRenderer = PointLightShadowRenderer;
|
|
69464
70390
|
exports.PointShadowCubeCamera = PointShadowCubeCamera;
|
|
@@ -69799,6 +70725,7 @@ fn frag(){
|
|
|
69799
70725
|
exports.outlinePostManager = outlinePostManager;
|
|
69800
70726
|
exports.parsePlyGaussianSplat = parsePlyGaussianSplat;
|
|
69801
70727
|
exports.parsePlyHeader = parsePlyHeader;
|
|
70728
|
+
exports.parsePlyMesh = parsePlyMesh;
|
|
69802
70729
|
exports.perm = perm;
|
|
69803
70730
|
exports.post = post;
|
|
69804
70731
|
exports.priorityCallback = priorityCallback;
|
|
@@ -69834,6 +70761,8 @@ fn frag(){
|
|
|
69834
70761
|
exports.snoise2 = snoise2;
|
|
69835
70762
|
exports.snoise3 = snoise3;
|
|
69836
70763
|
exports.snoise4 = snoise4;
|
|
70764
|
+
exports.splatColorProperties = splatColorProperties;
|
|
70765
|
+
exports.splatProperties = splatProperties;
|
|
69837
70766
|
exports.sqrMagnitude = sqrMagnitude;
|
|
69838
70767
|
exports.sqrtImpl = sqrtImpl;
|
|
69839
70768
|
exports.stencilStateFace = stencilStateFace;
|