@rings-webgpu/core 1.0.27 → 1.0.28

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.
@@ -2120,7 +2120,7 @@
2120
2120
  }
2121
2121
 
2122
2122
  var __defProp$2 = Object.defineProperty;
2123
- var __decorateClass$m = (decorators, target, key, kind) => {
2123
+ var __decorateClass$o = (decorators, target, key, kind) => {
2124
2124
  var result = void 0 ;
2125
2125
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
2126
2126
  if (decorator = decorators[i])
@@ -2223,10 +2223,10 @@
2223
2223
  return struct.__size;
2224
2224
  }
2225
2225
  };
2226
- __decorateClass$m([
2226
+ __decorateClass$o([
2227
2227
  NonSerialize
2228
2228
  ], _Struct.prototype, "__refection");
2229
- __decorateClass$m([
2229
+ __decorateClass$o([
2230
2230
  NonSerialize
2231
2231
  ], _Struct.prototype, "__size");
2232
2232
  let Struct = _Struct;
@@ -20496,6 +20496,10 @@ struct InstanceData {
20496
20496
  this.vsEntryPoint = vsEntryPoint;
20497
20497
  this.fsEntryPoint = fsEntryPoint;
20498
20498
  }
20499
+ setUniformArray(name, value) {
20500
+ super.setUniformArray(name, value);
20501
+ this.materialDataUniformBuffer.onChange();
20502
+ }
20499
20503
  setUniform(name, value) {
20500
20504
  super.setUniform(name, value);
20501
20505
  this.materialDataUniformBuffer.onChange();
@@ -20764,16 +20768,21 @@ struct InstanceData {
20764
20768
  if (buffer) {
20765
20769
  if (buffer.bufferType == GPUBufferType.MaterialDataUniformGPUBuffer) {
20766
20770
  let uniforms = [];
20767
- for (let i = 0; i < refs.dataFields.length; i++) {
20768
- const field = refs.dataFields[i];
20769
- if (!this.uniforms[field.name]) {
20770
- console.error(
20771
- `shader-${this.vsName}:${this.fsName} ${field.name}is empty`
20772
- );
20771
+ if (refs.dataFields) {
20772
+ for (let i = 0; i < refs.dataFields.length; i++) {
20773
+ const field = refs.dataFields[i];
20774
+ if (!this.uniforms[field.name]) {
20775
+ console.error(
20776
+ `shader-${this.vsName}:${this.fsName} ${field.name}is empty`
20777
+ );
20778
+ } else {
20779
+ uniforms.push(this.uniforms[field.name]);
20780
+ }
20773
20781
  }
20774
- uniforms.push(this.uniforms[field.name]);
20775
20782
  }
20776
- this.materialDataUniformBuffer.initDataUniform(uniforms);
20783
+ if (uniforms.length > 0) {
20784
+ this.materialDataUniformBuffer.initDataUniform(uniforms);
20785
+ }
20777
20786
  }
20778
20787
  let entry = {
20779
20788
  binding: refs.binding,
@@ -21963,9 +21972,9 @@ struct InstanceData {
21963
21972
  }
21964
21973
 
21965
21974
  var __defProp$1 = Object.defineProperty;
21966
- var __getOwnPropDesc$l = Object.getOwnPropertyDescriptor;
21967
- var __decorateClass$l = (decorators, target, key, kind) => {
21968
- var result = __getOwnPropDesc$l(target, key) ;
21975
+ var __getOwnPropDesc$n = Object.getOwnPropertyDescriptor;
21976
+ var __decorateClass$n = (decorators, target, key, kind) => {
21977
+ var result = __getOwnPropDesc$n(target, key) ;
21969
21978
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
21970
21979
  if (decorator = decorators[i])
21971
21980
  result = (decorator(target, key, result) ) || result;
@@ -22563,13 +22572,13 @@ struct InstanceData {
22563
22572
  this._combineShaderRefection = void 0;
22564
22573
  }
22565
22574
  }
22566
- __decorateClass$l([
22575
+ __decorateClass$n([
22567
22576
  EditorInspector
22568
22577
  ], RenderNode.prototype, "materials");
22569
- __decorateClass$l([
22578
+ __decorateClass$n([
22570
22579
  EditorInspector
22571
22580
  ], RenderNode.prototype, "castShadow");
22572
- __decorateClass$l([
22581
+ __decorateClass$n([
22573
22582
  EditorInspector
22574
22583
  ], RenderNode.prototype, "castGI");
22575
22584
 
@@ -22790,7 +22799,7 @@ struct InstanceData {
22790
22799
  @location(1) vTexCoord: vec2<f32>,
22791
22800
  };
22792
22801
 
22793
- // Textures (like PlayCanvas)
22802
+ // Textures
22794
22803
  @group(1) @binding(1) var splatColor: texture_2d<f32>;
22795
22804
  @group(1) @binding(2) var transformA: texture_2d<u32>;
22796
22805
  @group(1) @binding(3) var transformB: texture_2d<f32>;
@@ -22887,7 +22896,7 @@ struct InstanceData {
22887
22896
  return vec4f(v1.x, -v1.y, v2.x, -v2.y);
22888
22897
  }
22889
22898
 
22890
- // ===== SPLAT MAIN VS (from PlayCanvas gsplat-material.js) =====
22899
+ // ===== SPLAT MAIN VS =====
22891
22900
 
22892
22901
  @vertex
22893
22902
  fn VertMain(
@@ -23236,9 +23245,9 @@ struct InstanceData {
23236
23245
  }
23237
23246
  }
23238
23247
 
23239
- var __getOwnPropDesc$k = Object.getOwnPropertyDescriptor;
23240
- var __decorateClass$k = (decorators, target, key, kind) => {
23241
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$k(target, key) : target;
23248
+ var __getOwnPropDesc$m = Object.getOwnPropertyDescriptor;
23249
+ var __decorateClass$m = (decorators, target, key, kind) => {
23250
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$m(target, key) : target;
23242
23251
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
23243
23252
  if (decorator = decorators[i])
23244
23253
  result = (decorator(result)) || result;
@@ -23270,7 +23279,7 @@ struct InstanceData {
23270
23279
  pass.setUniform("pixelCull", new Float32Array([2, 0, 0, 0]));
23271
23280
  }
23272
23281
  };
23273
- exports.GSplatShader = __decorateClass$k([
23282
+ exports.GSplatShader = __decorateClass$m([
23274
23283
  RegisterShader(exports.GSplatShader, "GSplatShader")
23275
23284
  ], exports.GSplatShader);
23276
23285
 
@@ -24053,7 +24062,7 @@ struct InstanceData {
24053
24062
  size: data.byteLength,
24054
24063
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24055
24064
  });
24056
- device.queue.writeBuffer(textureDataBuffer, 0, data);
24065
+ device.queue.writeBuffer(textureDataBuffer, 0, data.buffer);
24057
24066
  const commandEncoder = GPUContext.beginCommandEncoder();
24058
24067
  commandEncoder.copyBufferToTexture(
24059
24068
  {
@@ -24085,7 +24094,7 @@ struct InstanceData {
24085
24094
  size: data.byteLength,
24086
24095
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
24087
24096
  });
24088
- device.queue.writeBuffer(textureDataBuffer, 0, data);
24097
+ device.queue.writeBuffer(textureDataBuffer, 0, data.buffer);
24089
24098
  const commandEncoder = GPUContext.beginCommandEncoder();
24090
24099
  commandEncoder.copyBufferToTexture(
24091
24100
  {
@@ -24287,9 +24296,9 @@ struct InstanceData {
24287
24296
  }
24288
24297
  }
24289
24298
 
24290
- var __getOwnPropDesc$j = Object.getOwnPropertyDescriptor;
24291
- var __decorateClass$j = (decorators, target, key, kind) => {
24292
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$j(target, key) : target;
24299
+ var __getOwnPropDesc$l = Object.getOwnPropertyDescriptor;
24300
+ var __decorateClass$l = (decorators, target, key, kind) => {
24301
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$l(target, key) : target;
24293
24302
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
24294
24303
  if (decorator = decorators[i])
24295
24304
  result = (decorator(result)) || result;
@@ -25088,10 +25097,689 @@ struct InstanceData {
25088
25097
  super.destroy(force);
25089
25098
  }
25090
25099
  };
25091
- exports.GSplatRenderer = __decorateClass$j([
25100
+ exports.GSplatRenderer = __decorateClass$l([
25092
25101
  RegisterComponent(exports.GSplatRenderer, "GSplatRenderer")
25093
25102
  ], exports.GSplatRenderer);
25094
25103
 
25104
+ const PointCloud_VS = (
25105
+ /* wgsl */
25106
+ `
25107
+ #include "GlobalUniform"
25108
+
25109
+ const ALPHA_THRESHOLD: f32 = 0.00392156863;
25110
+
25111
+ struct MaterialUniform {
25112
+ modelMatrix: mat4x4<f32>,
25113
+ tex_params: vec4<f32>,
25114
+ pointParams: vec4<f32>,
25115
+ };
25116
+ @group(1) @binding(0) var<uniform> materialUniform: MaterialUniform;
25117
+
25118
+ struct VSOut {
25119
+ @builtin(position) member: vec4<f32>,
25120
+ @location(0) vColor: vec4<f32>,
25121
+ @location(1) vTexCoord: vec2<f32>,
25122
+ };
25123
+
25124
+ @group(1) @binding(1) var pointColor: texture_2d<f32>;
25125
+ @group(1) @binding(2) var pointPosition: texture_2d<f32>;
25126
+ @group(1) @binding(3) var pointOrder: texture_2d<u32>;
25127
+
25128
+ fn discardPoint() -> VSOut {
25129
+ var o: VSOut;
25130
+ o.member = vec4f(0.0, 0.0, 2.0, 1.0);
25131
+ o.vColor = vec4f(0.0);
25132
+ o.vTexCoord = vec2f(0.0);
25133
+ return o;
25134
+ }
25135
+
25136
+ fn calcPointUV(orderId: u32, textureWidth: u32, numPoints: u32) -> vec2<i32> {
25137
+ let pointId = orderId;
25138
+ return vec2<i32>(
25139
+ i32(pointId % textureWidth),
25140
+ i32(pointId / textureWidth)
25141
+ );
25142
+ }
25143
+
25144
+ @vertex
25145
+ fn VertMain(
25146
+ @builtin(vertex_index) vid: u32,
25147
+ @builtin(instance_index) iid: u32,
25148
+ @location(0) position: vec3<f32>
25149
+ ) -> VSOut {
25150
+ let batchSize = max(1u, u32(materialUniform.pointParams.w));
25151
+ let orderId = iid * batchSize + u32(position.z);
25152
+
25153
+ let textureWidth = max(1u, u32(materialUniform.tex_params.y));
25154
+ let numPoints = max(1u, u32(materialUniform.tex_params.x));
25155
+ let safeOrderId = min(orderId, numPoints - 1u);
25156
+
25157
+ let pointUV = calcPointUV(safeOrderId, textureWidth, numPoints);
25158
+ let color = textureLoad(pointColor, pointUV, 0);
25159
+
25160
+ let posData = textureLoad(pointPosition, pointUV, 0);
25161
+ let pointPos = vec3f(
25162
+ posData.x,
25163
+ posData.y,
25164
+ posData.z
25165
+ );
25166
+
25167
+ let matrix_model = materialUniform.modelMatrix;
25168
+ let matrix_view = globalUniform.viewMat;
25169
+ let matrix_projection = globalUniform.projMat;
25170
+ let model_view = matrix_view * matrix_model;
25171
+
25172
+ let centerClip = matrix_projection * (model_view * vec4f(pointPos, 1.0));
25173
+
25174
+ let inv_w = 1.0 / centerClip.w;
25175
+ let ndc = centerClip.xyz * inv_w;
25176
+ if (ndc.x < -1.0 || ndc.x > 1.0 ||
25177
+ ndc.y < -1.0 || ndc.y > 1.0 ||
25178
+ ndc.z < 0.0 || ndc.z > 1.0) {
25179
+ return discardPoint();
25180
+ }
25181
+
25182
+ let viewPos = model_view * vec4f(pointPos, 1.0);
25183
+ if (viewPos.z <= 0.0) {
25184
+ return discardPoint();
25185
+ }
25186
+
25187
+ let pointSize = materialUniform.tex_params.w;
25188
+ let viewport = vec2f(globalUniform.windowWidth, globalUniform.windowHeight);
25189
+ let safeViewport = max(viewport, vec2f(1.0, 1.0));
25190
+ let inv_viewport = 2.0 / safeViewport;
25191
+ let offsetNDC = position.xy * pointSize * 0.5 * inv_viewport;
25192
+ let offsetClip = vec4f(offsetNDC * centerClip.w, 0.0, 0.0);
25193
+
25194
+ var o: VSOut;
25195
+ o.member = centerClip + offsetClip;
25196
+ o.vColor = color;
25197
+ o.vTexCoord = position.xy;
25198
+ return o;
25199
+ }
25200
+ `
25201
+ );
25202
+ const PointCloud_FS = (
25203
+ /* wgsl */
25204
+ `
25205
+ #include "FragmentOutput"
25206
+
25207
+ const ALPHA_THRESHOLD: f32 = 0.00392156863;
25208
+
25209
+ struct MaterialUniform {
25210
+ modelMatrix: mat4x4<f32>,
25211
+ tex_params: vec4<f32>,
25212
+ pointParams: vec4<f32>,
25213
+ };
25214
+ @group(1) @binding(0) var<uniform> materialUniform: MaterialUniform;
25215
+
25216
+ @fragment
25217
+ fn FragMain(
25218
+ @location(0) vColor: vec4<f32>,
25219
+ @location(1) vTexCoord: vec2<f32>
25220
+ ) -> FragmentOutput {
25221
+ var o: FragmentOutput;
25222
+
25223
+ let pointShape = materialUniform.pointParams.x;
25224
+ let distSq = dot(vTexCoord, vTexCoord);
25225
+ let isCircle = pointShape > 0.5;
25226
+ let discardPixel = isCircle && distSq > 1.0;
25227
+
25228
+ if (discardPixel) {
25229
+ discard;
25230
+ }
25231
+
25232
+ o.color = vColor;
25233
+ o.gBuffer = vec4f(0.0);
25234
+ return o;
25235
+ }
25236
+ `
25237
+ );
25238
+
25239
+ var __getOwnPropDesc$k = Object.getOwnPropertyDescriptor;
25240
+ var __decorateClass$k = (decorators, target, key, kind) => {
25241
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$k(target, key) : target;
25242
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
25243
+ if (decorator = decorators[i])
25244
+ result = (decorator(result)) || result;
25245
+ return result;
25246
+ };
25247
+ exports.PointCloudShader = class PointCloudShader extends Shader {
25248
+ constructor() {
25249
+ super();
25250
+ ShaderLib.register("pointcloud_vs_dc", PointCloud_VS);
25251
+ ShaderLib.register("pointcloud_fs_dc", PointCloud_FS);
25252
+ const pass = new RenderShaderPass("pointcloud_vs_dc", "pointcloud_fs_dc");
25253
+ pass.passType = PassType.COLOR;
25254
+ pass.setShaderEntry("VertMain", "FragMain");
25255
+ pass.topology = GPUPrimitiveTopology.triangle_list;
25256
+ pass.depthWriteEnabled = false;
25257
+ pass.cullMode = GPUCullMode.none;
25258
+ pass.shaderState.transparent = true;
25259
+ pass.shaderState.blendMode = BlendMode.NORMAL;
25260
+ pass.shaderState.writeMasks = [15, 15];
25261
+ pass.shaderState.castReflection = false;
25262
+ this.addRenderPass(pass);
25263
+ this.setDefault();
25264
+ }
25265
+ setDefault() {
25266
+ const pass = this.getDefaultColorShader();
25267
+ const identityMatrix = new Matrix4();
25268
+ pass.setUniform("modelMatrix", identityMatrix.rawData);
25269
+ pass.setUniformArray("tex_params", new Float32Array([0, 0, 0, 4]));
25270
+ pass.setUniformArray("pointParams", new Float32Array([0, 0, 0, 128]));
25271
+ }
25272
+ };
25273
+ exports.PointCloudShader = __decorateClass$k([
25274
+ RegisterShader(exports.PointCloudShader, "PointCloudShader")
25275
+ ], exports.PointCloudShader);
25276
+
25277
+ class PointCloudMaterial extends Material {
25278
+ _texParams = new Float32Array([0, 0, 0, 4]);
25279
+ _pointParamsArray = new Float32Array([0, 0, 0, 128]);
25280
+ constructor() {
25281
+ super();
25282
+ this.shader = new exports.PointCloudShader();
25283
+ }
25284
+ /**
25285
+ * Set point cloud textures
25286
+ * @param pointPosition Position texture (RGB = xyz)
25287
+ * @param pointColor Color texture (RGBA)
25288
+ * @param texParams Texture parameters [numPoints, texWidth, validCount, pointSize]
25289
+ * @param pointOrder Optional sorting texture (R32U format)
25290
+ */
25291
+ setPointTextures(pointPosition, pointColor, texParams, pointOrder) {
25292
+ const pass = this.shader.getDefaultColorShader();
25293
+ if (!pass.getUniform("modelMatrix")) {
25294
+ const identityMatrix = new Matrix4();
25295
+ pass.setUniform("modelMatrix", identityMatrix.rawData);
25296
+ }
25297
+ pass.setTexture("pointColor", pointColor);
25298
+ pass.setTexture("pointPosition", pointPosition);
25299
+ this._texParams[0] = texParams[0];
25300
+ this._texParams[1] = texParams[1];
25301
+ this._texParams[2] = texParams[2];
25302
+ this._texParams[3] = texParams[3];
25303
+ pass.setUniformArray("tex_params", this._texParams);
25304
+ pass.setUniformArray("pointParams", this._pointParamsArray);
25305
+ if (pointOrder) {
25306
+ pass.setTexture("pointOrder", pointOrder);
25307
+ }
25308
+ pass.shaderState.depthCompare = GPUCompareFunction.less;
25309
+ }
25310
+ /**
25311
+ * Set the model matrix for transforming points to world space
25312
+ * @param matrix Model transformation matrix
25313
+ */
25314
+ setTransformMatrix(matrix) {
25315
+ const pass = this.shader.getDefaultColorShader();
25316
+ pass.setUniform("modelMatrix", matrix.rawData);
25317
+ }
25318
+ /**
25319
+ * Set point size in pixels
25320
+ * @param size Point size in pixels (default: 4.0)
25321
+ */
25322
+ setPointSize(size) {
25323
+ this._texParams[3] = Math.max(0.1, size);
25324
+ const pass = this.shader.getDefaultColorShader();
25325
+ pass.setUniformArray("tex_params", this._texParams);
25326
+ }
25327
+ /**
25328
+ * Set point shape
25329
+ * @param shape Point shape: 'square' or 'circle'
25330
+ */
25331
+ setPointShape(shape) {
25332
+ this._pointParamsArray[0] = shape === "circle" ? 1 : 0;
25333
+ const pass = this.shader.getDefaultColorShader();
25334
+ pass.setUniformArray("pointParams", this._pointParamsArray);
25335
+ }
25336
+ enableDebugFullScreen(enabled) {
25337
+ this._pointParamsArray[1] = enabled ? 1 : 0;
25338
+ const pass = this.shader.getDefaultColorShader();
25339
+ pass.setUniformArray("pointParams", this._pointParamsArray);
25340
+ }
25341
+ /**
25342
+ * Set batch size for instanced rendering
25343
+ * @param batchSize Number of points per draw call (default: 128)
25344
+ */
25345
+ setBatchSize(batchSize) {
25346
+ this._pointParamsArray[3] = Math.max(1, batchSize | 0);
25347
+ const pass = this.shader.getDefaultColorShader();
25348
+ pass.setUniformArray("pointParams", this._pointParamsArray);
25349
+ }
25350
+ }
25351
+
25352
+ class PointCloudGeometry extends GeometryBase {
25353
+ batchSize;
25354
+ constructor(batchSize = 128) {
25355
+ super();
25356
+ this.batchSize = batchSize;
25357
+ const meshPositions = new Float32Array(12 * batchSize);
25358
+ for (let i = 0; i < batchSize; ++i) {
25359
+ const baseIdx = i * 12;
25360
+ meshPositions.set([
25361
+ -1,
25362
+ -1,
25363
+ i,
25364
+ 1,
25365
+ -1,
25366
+ i,
25367
+ 1,
25368
+ 1,
25369
+ i,
25370
+ -1,
25371
+ 1,
25372
+ i
25373
+ ], baseIdx);
25374
+ }
25375
+ const meshIndices = new Uint32Array(6 * batchSize);
25376
+ for (let i = 0; i < batchSize; ++i) {
25377
+ const baseVertex = i * 4;
25378
+ const baseIdx = i * 6;
25379
+ meshIndices.set([
25380
+ 0 + baseVertex,
25381
+ 1 + baseVertex,
25382
+ 2 + baseVertex,
25383
+ 0 + baseVertex,
25384
+ 2 + baseVertex,
25385
+ 3 + baseVertex
25386
+ ], baseIdx);
25387
+ }
25388
+ this.setAttribute(VertexAttributeName.position, meshPositions);
25389
+ this.setIndices(meshIndices);
25390
+ this.addSubGeometry({
25391
+ indexStart: 0,
25392
+ indexCount: meshIndices.length,
25393
+ vertexStart: 0,
25394
+ vertexCount: meshPositions.length / 3,
25395
+ firstStart: 0,
25396
+ index: 0,
25397
+ topology: 0
25398
+ });
25399
+ }
25400
+ }
25401
+
25402
+ class Float32ArrayTexture extends Texture {
25403
+ create(width, height, data, filtering = true) {
25404
+ let device = webGPUContext.device;
25405
+ const bytesPerRow = width * 4 * 4;
25406
+ this.format = GPUTextureFormat.rgba32float;
25407
+ let mipmapCount = 1;
25408
+ this.createTextureDescriptor(width, height, mipmapCount, this.format);
25409
+ const textureDataBuffer = device.createBuffer({
25410
+ size: data.byteLength,
25411
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
25412
+ });
25413
+ device.queue.writeBuffer(textureDataBuffer, 0, data.buffer);
25414
+ const commandEncoder = GPUContext.beginCommandEncoder();
25415
+ commandEncoder.copyBufferToTexture(
25416
+ {
25417
+ buffer: textureDataBuffer,
25418
+ bytesPerRow
25419
+ },
25420
+ {
25421
+ texture: this.getGPUTexture()
25422
+ },
25423
+ {
25424
+ width,
25425
+ height,
25426
+ depthOrArrayLayers: 1
25427
+ }
25428
+ );
25429
+ GPUContext.endCommandEncoder(commandEncoder);
25430
+ if (filtering) {
25431
+ this.samplerBindingLayout.type = `non-filtering`;
25432
+ this.textureBindingLayout.sampleType = `unfilterable-float`;
25433
+ }
25434
+ this.gpuSampler = device.createSampler({});
25435
+ return this;
25436
+ }
25437
+ fromBuffer(width, height, textureDataBuffer) {
25438
+ let device = webGPUContext.device;
25439
+ const bytesPerRow = width * 4 * 4;
25440
+ this.format = GPUTextureFormat.rgba32float;
25441
+ this.mipmapCount = 1;
25442
+ this.createTextureDescriptor(width, height, this.mipmapCount, this.format);
25443
+ const commandEncoder = GPUContext.beginCommandEncoder();
25444
+ commandEncoder.copyBufferToTexture(
25445
+ {
25446
+ buffer: textureDataBuffer,
25447
+ bytesPerRow
25448
+ },
25449
+ {
25450
+ texture: this.getGPUTexture()
25451
+ },
25452
+ {
25453
+ width,
25454
+ height,
25455
+ depthOrArrayLayers: 1
25456
+ }
25457
+ );
25458
+ GPUContext.endCommandEncoder(commandEncoder);
25459
+ this.samplerBindingLayout.type = `non-filtering`;
25460
+ this.textureBindingLayout.sampleType = `unfilterable-float`;
25461
+ this.gpuSampler = device.createSampler({});
25462
+ return this;
25463
+ }
25464
+ }
25465
+
25466
+ var __getOwnPropDesc$j = Object.getOwnPropertyDescriptor;
25467
+ var __decorateClass$j = (decorators, target, key, kind) => {
25468
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$j(target, key) : target;
25469
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
25470
+ if (decorator = decorators[i])
25471
+ result = (decorator(result)) || result;
25472
+ return result;
25473
+ };
25474
+ exports.PointCloudRenderer = class PointCloudRenderer extends RenderNode {
25475
+ count = 0;
25476
+ size = new Vector2();
25477
+ pointColor;
25478
+ pointPosition;
25479
+ pointOrder;
25480
+ texParams;
25481
+ // [numPoints, texWidth, validCount, pointSize]
25482
+ pointCloudMaterial;
25483
+ _positions;
25484
+ get positions() {
25485
+ return this._positions;
25486
+ }
25487
+ _colors;
25488
+ _orderData;
25489
+ _fullCount = 0;
25490
+ get fullCount() {
25491
+ return this._fullCount;
25492
+ }
25493
+ _batchSize = 128;
25494
+ instanceCount = 0;
25495
+ _texturesInitialized = false;
25496
+ _debugFullScreen = false;
25497
+ _centerOffset = new Vector3();
25498
+ get centerOffset() {
25499
+ return this._centerOffset;
25500
+ }
25501
+ constructor() {
25502
+ super();
25503
+ }
25504
+ /**
25505
+ * Initialize point cloud from raw data
25506
+ * @param positions Point positions (xyz per point, Float32Array)
25507
+ * @param colors Point colors (rgba per point, Uint8Array)
25508
+ * @param count Number of points
25509
+ */
25510
+ initFromData(positions, colors, count) {
25511
+ if (!positions || !colors || count <= 0) {
25512
+ console.error("PointCloudRenderer: Invalid input data");
25513
+ return;
25514
+ }
25515
+ if (positions.length < count * 3) {
25516
+ console.error("PointCloudRenderer: Positions array too small");
25517
+ return;
25518
+ }
25519
+ if (colors.length < count * 4) {
25520
+ console.error("PointCloudRenderer: Colors array too small");
25521
+ return;
25522
+ }
25523
+ this.count = count;
25524
+ this._fullCount = count;
25525
+ this.size = this.evalTextureSize(count);
25526
+ this._positions = positions;
25527
+ this._colors = colors;
25528
+ this.centerizePositions();
25529
+ this.buildPositionTexture();
25530
+ this.buildColorTexture();
25531
+ this.texParams = new Float32Array([
25532
+ this.count,
25533
+ this.size.x,
25534
+ this.count,
25535
+ 4
25536
+ ]);
25537
+ this.buildOrderTexture();
25538
+ this.pointCloudMaterial = new PointCloudMaterial();
25539
+ this.geometry = new PointCloudGeometry(this._batchSize);
25540
+ this.materials = [this.pointCloudMaterial];
25541
+ this.instanceCount = Math.ceil(this.count / this._batchSize);
25542
+ }
25543
+ /**
25544
+ * Calculate texture size for given point count
25545
+ * @param count Number of points
25546
+ * @returns Texture dimensions (width, height)
25547
+ */
25548
+ evalTextureSize(count) {
25549
+ let w = Math.ceil(Math.sqrt(count));
25550
+ const align = 64;
25551
+ w = Math.ceil(w / align) * align;
25552
+ const h = Math.ceil(count / w);
25553
+ return new Vector2(w, h);
25554
+ }
25555
+ /**
25556
+ * Centerize positions to improve precision for large values
25557
+ * Subtracts the center point from all positions to keep values near zero
25558
+ */
25559
+ centerizePositions() {
25560
+ if (this.count === 0) return;
25561
+ let sumX = 0, sumY = 0, sumZ = 0;
25562
+ for (let i = 0; i < this.count; i++) {
25563
+ const idx = i * 3;
25564
+ sumX += this._positions[idx + 0];
25565
+ sumY += this._positions[idx + 1];
25566
+ sumZ += this._positions[idx + 2];
25567
+ }
25568
+ const centerX = sumX / this.count;
25569
+ const centerY = sumY / this.count;
25570
+ const centerZ = sumZ / this.count;
25571
+ this._centerOffset.set(centerX, centerY, centerZ);
25572
+ for (let i = 0; i < this.count; i++) {
25573
+ const idx = i * 3;
25574
+ this._positions[idx + 0] -= centerX;
25575
+ this._positions[idx + 1] -= centerY;
25576
+ this._positions[idx + 2] -= centerZ;
25577
+ }
25578
+ this.object3D.localPosition = this._centerOffset;
25579
+ }
25580
+ buildPositionTexture() {
25581
+ const w = this.size.x | 0;
25582
+ const h = this.size.y | 0;
25583
+ const count = this.count;
25584
+ const data = new Float32Array(w * h * 4);
25585
+ for (let i = 0; i < count; i++) {
25586
+ const idx = i * 4;
25587
+ const posIdx = i * 3;
25588
+ data[idx + 0] = this._positions[posIdx + 0];
25589
+ data[idx + 1] = this._positions[posIdx + 1];
25590
+ data[idx + 2] = this._positions[posIdx + 2];
25591
+ data[idx + 3] = 0;
25592
+ }
25593
+ if (count < w * h) {
25594
+ const lastIdx = (count - 1) * 4;
25595
+ for (let i = count; i < w * h; i++) {
25596
+ const idx = i * 4;
25597
+ data[idx + 0] = data[lastIdx + 0];
25598
+ data[idx + 1] = data[lastIdx + 1];
25599
+ data[idx + 2] = data[lastIdx + 2];
25600
+ data[idx + 3] = 0;
25601
+ }
25602
+ }
25603
+ this.pointPosition = new Float32ArrayTexture().create(w, h, data);
25604
+ this.pointPosition.name = "pointPosition";
25605
+ this.pointPosition.minFilter = "nearest";
25606
+ this.pointPosition.magFilter = "nearest";
25607
+ this.pointPosition.addressModeU = "clamp-to-edge";
25608
+ this.pointPosition.addressModeV = "clamp-to-edge";
25609
+ }
25610
+ buildColorTexture() {
25611
+ const w = this.size.x | 0;
25612
+ const h = this.size.y | 0;
25613
+ const count = this.count;
25614
+ const data = new Uint8Array(w * h * 4);
25615
+ for (let i = 0; i < count; i++) {
25616
+ const idx = i * 4;
25617
+ const colorIdx = i * 4;
25618
+ data[idx + 0] = this._colors[colorIdx + 0];
25619
+ data[idx + 1] = this._colors[colorIdx + 1];
25620
+ data[idx + 2] = this._colors[colorIdx + 2];
25621
+ data[idx + 3] = this._colors[colorIdx + 3];
25622
+ }
25623
+ if (count < w * h) {
25624
+ const lastIdx = (count - 1) * 4;
25625
+ for (let i = count; i < w * h; i++) {
25626
+ const idx = i * 4;
25627
+ data[idx + 0] = data[lastIdx + 0];
25628
+ data[idx + 1] = data[lastIdx + 1];
25629
+ data[idx + 2] = data[lastIdx + 2];
25630
+ data[idx + 3] = data[lastIdx + 3];
25631
+ }
25632
+ }
25633
+ this.pointColor = new Uint8ArrayTexture().create(w, h, data, false);
25634
+ this.pointColor.name = "pointColor";
25635
+ this.pointColor.minFilter = "nearest";
25636
+ this.pointColor.magFilter = "nearest";
25637
+ this.pointColor.mipmapFilter = "nearest";
25638
+ this.pointColor.addressModeU = "clamp-to-edge";
25639
+ this.pointColor.addressModeV = "clamp-to-edge";
25640
+ }
25641
+ buildOrderTexture() {
25642
+ const total = this.size.x * this.size.y;
25643
+ this._orderData = new Uint32Array(total);
25644
+ for (let i = 0; i < total; i++) {
25645
+ this._orderData[i] = i < this.count ? i : this.count > 0 ? this.count - 1 : 0;
25646
+ }
25647
+ this.pointOrder = new R32UintTexture().create(this.size.x, this.size.y, this._orderData);
25648
+ this.pointOrder.name = "pointOrder";
25649
+ this.pointOrder.minFilter = "nearest";
25650
+ this.pointOrder.magFilter = "nearest";
25651
+ this.pointOrder.addressModeU = "clamp-to-edge";
25652
+ this.pointOrder.addressModeV = "clamp-to-edge";
25653
+ }
25654
+ /**
25655
+ * Update node before rendering
25656
+ */
25657
+ nodeUpdate(view, passType, renderPassState, clusterLightingBuffer) {
25658
+ const worldMatrix = this.object3D.transform.worldMatrix;
25659
+ this.pointCloudMaterial.setTransformMatrix(worldMatrix);
25660
+ if (!this._texturesInitialized) {
25661
+ this.pointCloudMaterial.setPointTextures(
25662
+ this.pointPosition,
25663
+ this.pointColor,
25664
+ this.texParams,
25665
+ this.pointOrder
25666
+ );
25667
+ this.pointCloudMaterial.setBatchSize(this._batchSize);
25668
+ this.pointCloudMaterial.setPointSize(this.texParams[3]);
25669
+ this.pointCloudMaterial.enableDebugFullScreen(this._debugFullScreen);
25670
+ this._texturesInitialized = true;
25671
+ }
25672
+ super.nodeUpdate(view, passType, renderPassState, clusterLightingBuffer);
25673
+ }
25674
+ /**
25675
+ * Render pass
25676
+ */
25677
+ renderPass(view, passType, renderContext) {
25678
+ const encoder = renderContext.encoder;
25679
+ for (let mat of this.materials) {
25680
+ const passes = mat.getPass(passType);
25681
+ if (!passes || passes.length === 0) continue;
25682
+ for (const pass of passes) {
25683
+ if (!pass.pipeline) continue;
25684
+ pass.apply(this.geometry, renderContext.rendererPassState || renderContext);
25685
+ GPUContext.bindPipeline(encoder, pass);
25686
+ GPUContext.bindGeometryBuffer(encoder, this.geometry);
25687
+ const subGeometry = this.geometry.subGeometries[0];
25688
+ const lodInfo = subGeometry.lodLevels[0];
25689
+ if (this.instanceCount > 0) {
25690
+ GPUContext.drawIndexed(
25691
+ encoder,
25692
+ lodInfo.indexCount,
25693
+ this.instanceCount,
25694
+ lodInfo.indexStart,
25695
+ 0,
25696
+ 0
25697
+ );
25698
+ } else {
25699
+ GPUContext.drawIndexed(
25700
+ encoder,
25701
+ lodInfo.indexCount,
25702
+ 1,
25703
+ lodInfo.indexStart,
25704
+ 0,
25705
+ 0
25706
+ );
25707
+ }
25708
+ }
25709
+ }
25710
+ }
25711
+ /**
25712
+ * Set point size in pixels
25713
+ * @param size Point size in pixels
25714
+ */
25715
+ setPointSize(size) {
25716
+ this.texParams[3] = Math.max(0.1, size);
25717
+ if (this.pointCloudMaterial) {
25718
+ this.pointCloudMaterial.setPointSize(size);
25719
+ }
25720
+ }
25721
+ /**
25722
+ * Set point shape
25723
+ * @param shape 'square' or 'circle'
25724
+ */
25725
+ setPointShape(shape) {
25726
+ if (this.pointCloudMaterial) {
25727
+ this.pointCloudMaterial.setPointShape(shape);
25728
+ }
25729
+ }
25730
+ /**
25731
+ * Enable a fullscreen debug quad to validate the render pipeline.
25732
+ */
25733
+ enableDebugFullScreen(enabled) {
25734
+ this._debugFullScreen = enabled;
25735
+ if (this.pointCloudMaterial) {
25736
+ this.pointCloudMaterial.enableDebugFullScreen(enabled);
25737
+ }
25738
+ }
25739
+ /**
25740
+ * Set batch size for instanced rendering
25741
+ * @param batchSize Number of points per draw call
25742
+ */
25743
+ setBatchSize(batchSize) {
25744
+ this._batchSize = Math.max(1, batchSize | 0);
25745
+ if (this.geometry) {
25746
+ const oldGeometry = this.geometry;
25747
+ Reference.getInstance().detached(oldGeometry, this);
25748
+ if (!Reference.getInstance().hasReference(oldGeometry)) {
25749
+ oldGeometry.destroy();
25750
+ }
25751
+ this.geometry = new PointCloudGeometry(this._batchSize);
25752
+ }
25753
+ if (this.pointCloudMaterial) {
25754
+ this.pointCloudMaterial.setBatchSize(this._batchSize);
25755
+ this.pointCloudMaterial.enableDebugFullScreen(this._debugFullScreen);
25756
+ }
25757
+ this.instanceCount = Math.ceil(this.count / this._batchSize);
25758
+ }
25759
+ destroy(force) {
25760
+ if (this.pointColor) {
25761
+ this.pointColor.destroy(force);
25762
+ this.pointColor = null;
25763
+ }
25764
+ if (this.pointPosition) {
25765
+ this.pointPosition.destroy(force);
25766
+ this.pointPosition = null;
25767
+ }
25768
+ if (this.pointOrder) {
25769
+ this.pointOrder.destroy(force);
25770
+ this.pointOrder = null;
25771
+ }
25772
+ this._positions = null;
25773
+ this._colors = null;
25774
+ this._orderData = null;
25775
+ this.texParams = null;
25776
+ super.destroy(force);
25777
+ }
25778
+ };
25779
+ exports.PointCloudRenderer = __decorateClass$j([
25780
+ RegisterComponent(exports.PointCloudRenderer, "PointCloudRenderer")
25781
+ ], exports.PointCloudRenderer);
25782
+
25095
25783
  class BoundUtil {
25096
25784
  static maxVector = new Vector3(
25097
25785
  Number.MAX_VALUE * 0.1,
@@ -25111,6 +25799,36 @@ struct InstanceData {
25111
25799
  new Vector3(),
25112
25800
  new Vector3()
25113
25801
  ];
25802
+ static genPointCloudBounds(obj, bound) {
25803
+ bound ||= new BoundingBox(Vector3.ZERO, Vector3.ZERO);
25804
+ bound.setFromMinMax(this.maxVector, this.minVector);
25805
+ let pointCloudRenderers = obj.getComponents(exports.PointCloudRenderer);
25806
+ if (!pointCloudRenderers) {
25807
+ console.warn("genPointCloudBounds: No PointCloudRenderer found on object");
25808
+ return bound;
25809
+ }
25810
+ for (const pointCloudRenderer of pointCloudRenderers) {
25811
+ const positions = pointCloudRenderer.positions;
25812
+ const count = pointCloudRenderer.fullCount;
25813
+ if (!positions || count === 0) {
25814
+ console.warn("genPointCloudBounds: No position data available");
25815
+ continue;
25816
+ }
25817
+ const matrix = pointCloudRenderer.object3D.transform.worldMatrix;
25818
+ const point = new Vector3();
25819
+ for (let i = 0; i < count; i++) {
25820
+ const idx = i * 3;
25821
+ point.set(
25822
+ positions[idx + 0],
25823
+ positions[idx + 1],
25824
+ positions[idx + 2]
25825
+ );
25826
+ matrix.transformPoint(point, point);
25827
+ bound.expandByPoint(point);
25828
+ }
25829
+ }
25830
+ return bound;
25831
+ }
25114
25832
  static genGSplatBounds(obj, bound) {
25115
25833
  bound ||= new BoundingBox(Vector3.ZERO, Vector3.ZERO);
25116
25834
  bound.setFromMinMax(this.maxVector, this.minVector);
@@ -41432,7 +42150,7 @@ else if (typeof exports === 'object')
41432
42150
  }
41433
42151
  }
41434
42152
 
41435
- const version = "1.0.26";
42153
+ const version = "1.0.27";
41436
42154
 
41437
42155
  class Engine3D {
41438
42156
  /**
@@ -59925,30 +60643,372 @@ fn frag(){
59925
60643
  }
59926
60644
  };
59927
60645
  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 = [];
60646
+ const hasNormalData = has("nx") && has("ny") && has("nz");
60647
+ const normal = hasNormalData ? new Float32Array(vertexCount * 3) : new Float32Array(vertexCount * 3);
60648
+ const color = (has("red") || has("r")) && (has("green") || has("g")) && (has("blue") || has("b")) ? new Float32Array(vertexCount * 3) : void 0;
60649
+ const hasVertexUV = (has("u") || has("s")) && (has("v") || has("t"));
60650
+ const hasTexcoord = faceProperties?.some((p) => p.name === "texcoord") || false;
60651
+ const uv = hasVertexUV || hasTexcoord ? new Float32Array(vertexCount * 2) : void 0;
60652
+ const faceTexcoords = /* @__PURE__ */ new Map();
60653
+ const hasTexnumber = faceProperties?.some((p) => p.name === "texnumber") || false;
60654
+ const faceTexnumbers = hasTexnumber ? new Array(faceCount) : [];
60655
+ const indices = [];
60656
+ const triangleTexnumbers = [];
60657
+ const faceVertexUvs = [];
60658
+ const propIndex = (n) => properties.findIndex((p) => p.name === n);
60659
+ const xIdx = propIndex("x");
60660
+ const yIdx = propIndex("y");
60661
+ const zIdx = propIndex("z");
60662
+ const nxIdx = hasNormalData ? propIndex("nx") : -1;
60663
+ const nyIdx = hasNormalData ? propIndex("ny") : -1;
60664
+ const nzIdx = hasNormalData ? propIndex("nz") : -1;
60665
+ const rIdx = color ? propIndex("red") >= 0 ? propIndex("red") : propIndex("r") : -1;
60666
+ const gIdx = color ? propIndex("green") >= 0 ? propIndex("green") : propIndex("g") : -1;
60667
+ const bIdx = color ? propIndex("blue") >= 0 ? propIndex("blue") : propIndex("b") : -1;
60668
+ const uIdx = uv && hasVertexUV ? propIndex("u") >= 0 ? propIndex("u") : propIndex("s") : -1;
60669
+ const vIdx = uv && hasVertexUV ? propIndex("v") >= 0 ? propIndex("v") : propIndex("t") : -1;
60670
+ for (let v = 0; v < vertexCount; v++) {
60671
+ for (let pIdx = 0; pIdx < properties.length; pIdx++) {
60672
+ const prop = properties[pIdx];
60673
+ const value = parseASCIINumber(prop.type);
60674
+ if (pIdx === xIdx) {
60675
+ position[v * 3 + 0] = value;
60676
+ } else if (pIdx === yIdx) {
60677
+ position[v * 3 + 1] = value;
60678
+ } else if (pIdx === zIdx) {
60679
+ position[v * 3 + 2] = value;
60680
+ } else if (pIdx === nxIdx) {
60681
+ normal[v * 3 + 0] = value;
60682
+ } else if (pIdx === nyIdx) {
60683
+ normal[v * 3 + 1] = value;
60684
+ } else if (pIdx === nzIdx) {
60685
+ normal[v * 3 + 2] = value;
60686
+ } else if (pIdx === rIdx && color) {
60687
+ color[v * 3 + 0] = prop.type === "uchar" || prop.type === "uint8" ? value / 255 : value;
60688
+ } else if (pIdx === gIdx && color) {
60689
+ color[v * 3 + 1] = prop.type === "uchar" || prop.type === "uint8" ? value / 255 : value;
60690
+ } else if (pIdx === bIdx && color) {
60691
+ color[v * 3 + 2] = prop.type === "uchar" || prop.type === "uint8" ? value / 255 : value;
60692
+ } else if (pIdx === uIdx && uv) {
60693
+ uv[v * 2 + 0] = value;
60694
+ } else if (pIdx === vIdx && uv) {
60695
+ uv[v * 2 + 1] = value;
60696
+ }
60697
+ }
60698
+ }
60699
+ for (let f = 0; f < faceCount; f++) {
60700
+ let faceIndices = [];
60701
+ let faceTexcoordArray = void 0;
60702
+ let faceTexnum = 0;
60703
+ for (const prop of faceProperties || []) {
60704
+ if (prop.name === "vertex_indices") {
60705
+ const parts = prop.type.split(" ");
60706
+ const countType = parts[1];
60707
+ const itemType = parts[2];
60708
+ const vertexCountInFace2 = parseASCIINumber(countType);
60709
+ faceIndices = [];
60710
+ for (let i = 0; i < vertexCountInFace2; i++) {
60711
+ faceIndices.push(parseASCIINumber(itemType));
60712
+ }
60713
+ } else if (prop.name === "texcoord") {
60714
+ const parts = prop.type.split(" ");
60715
+ const countType = parts[1];
60716
+ const itemType = parts[2];
60717
+ const texcoordCount = parseASCIINumber(countType);
60718
+ faceTexcoordArray = new Float32Array(texcoordCount);
60719
+ for (let i = 0; i < texcoordCount; i++) {
60720
+ faceTexcoordArray[i] = parseASCIINumber(itemType);
60721
+ }
60722
+ faceTexcoords.set(f, faceTexcoordArray);
60723
+ } else if (prop.name === "texnumber") {
60724
+ faceTexnum = parseASCIINumber(prop.type);
60725
+ faceTexnumbers[f] = faceTexnum;
60726
+ }
60727
+ }
60728
+ const vertexCountInFace = faceIndices.length;
60729
+ const texnum = hasTexnumber ? faceTexnumbers[f] ?? 0 : 0;
60730
+ if (vertexCountInFace === 3) {
60731
+ indices.push(faceIndices[0], faceIndices[1], faceIndices[2]);
60732
+ if (hasTexnumber) {
60733
+ triangleTexnumbers.push(texnum);
60734
+ }
60735
+ if (hasTexcoord && faceTexcoordArray && faceTexcoordArray.length >= 6) {
60736
+ faceVertexUvs.push(
60737
+ faceTexcoordArray[0],
60738
+ 1 - faceTexcoordArray[1],
60739
+ faceTexcoordArray[2],
60740
+ 1 - faceTexcoordArray[3],
60741
+ faceTexcoordArray[4],
60742
+ 1 - faceTexcoordArray[5]
60743
+ );
60744
+ }
60745
+ } else {
60746
+ for (let i = 1; i < vertexCountInFace - 1; i++) {
60747
+ indices.push(faceIndices[0], faceIndices[i], faceIndices[i + 1]);
60748
+ if (hasTexnumber) {
60749
+ triangleTexnumbers.push(texnum);
60750
+ }
60751
+ if (hasTexcoord && faceTexcoordArray && faceTexcoordArray.length >= vertexCountInFace * 2) {
60752
+ faceVertexUvs.push(
60753
+ faceTexcoordArray[0],
60754
+ 1 - faceTexcoordArray[1],
60755
+ faceTexcoordArray[i * 2 + 0],
60756
+ 1 - faceTexcoordArray[i * 2 + 1],
60757
+ faceTexcoordArray[(i + 1) * 2 + 0],
60758
+ 1 - faceTexcoordArray[(i + 1) * 2 + 1]
60759
+ );
60760
+ }
60761
+ }
60762
+ }
60763
+ }
60764
+ if (!hasNormalData) {
60765
+ for (let i = 0; i < vertexCount * 3; i++) {
60766
+ normal[i] = 0;
60767
+ }
60768
+ for (let i = 0; i < indices.length; i += 3) {
60769
+ const i0 = indices[i];
60770
+ const i1 = indices[i + 1];
60771
+ const i2 = indices[i + 2];
60772
+ const v0x = position[i0 * 3 + 0];
60773
+ const v0y = position[i0 * 3 + 1];
60774
+ const v0z = position[i0 * 3 + 2];
60775
+ const v1x = position[i1 * 3 + 0];
60776
+ const v1y = position[i1 * 3 + 1];
60777
+ const v1z = position[i1 * 3 + 2];
60778
+ const v2x = position[i2 * 3 + 0];
60779
+ const v2y = position[i2 * 3 + 1];
60780
+ const v2z = position[i2 * 3 + 2];
60781
+ const edge1x = v1x - v0x;
60782
+ const edge1y = v1y - v0y;
60783
+ const edge1z = v1z - v0z;
60784
+ const edge2x = v2x - v0x;
60785
+ const edge2y = v2y - v0y;
60786
+ const edge2z = v2z - v0z;
60787
+ const nx = edge1y * edge2z - edge1z * edge2y;
60788
+ const ny = edge1z * edge2x - edge1x * edge2z;
60789
+ const nz = edge1x * edge2y - edge1y * edge2x;
60790
+ normal[i0 * 3 + 0] += nx;
60791
+ normal[i0 * 3 + 1] += ny;
60792
+ normal[i0 * 3 + 2] += nz;
60793
+ normal[i1 * 3 + 0] += nx;
60794
+ normal[i1 * 3 + 1] += ny;
60795
+ normal[i1 * 3 + 2] += nz;
60796
+ normal[i2 * 3 + 0] += nx;
60797
+ normal[i2 * 3 + 1] += ny;
60798
+ normal[i2 * 3 + 2] += nz;
60799
+ }
60800
+ for (let v = 0; v < vertexCount; v++) {
60801
+ const nx = normal[v * 3 + 0];
60802
+ const ny = normal[v * 3 + 1];
60803
+ const nz = normal[v * 3 + 2];
60804
+ const length = Math.sqrt(nx * nx + ny * ny + nz * nz);
60805
+ if (length > 1e-5) {
60806
+ normal[v * 3 + 0] = nx / length;
60807
+ normal[v * 3 + 1] = ny / length;
60808
+ normal[v * 3 + 2] = nz / length;
60809
+ } else {
60810
+ normal[v * 3 + 0] = 0;
60811
+ normal[v * 3 + 1] = 1;
60812
+ normal[v * 3 + 2] = 0;
60813
+ }
60814
+ }
60815
+ }
60816
+ let finalPosition = position;
60817
+ let finalNormal = normal;
60818
+ let finalColor = color;
60819
+ let finalUv = void 0;
60820
+ let finalIndices = void 0;
60821
+ if (hasTexcoord && faceVertexUvs.length > 0) {
60822
+ const triangleCount = indices.length / 3;
60823
+ const expandedPosition = new Float32Array(triangleCount * 3 * 3);
60824
+ const expandedNormal = new Float32Array(triangleCount * 3 * 3);
60825
+ const expandedColor = color ? new Float32Array(triangleCount * 3 * 3) : void 0;
60826
+ finalUv = new Float32Array(faceVertexUvs);
60827
+ for (let i = 0; i < triangleCount; i++) {
60828
+ const baseIdx = i * 3;
60829
+ const i0 = indices[baseIdx + 0];
60830
+ const i1 = indices[baseIdx + 1];
60831
+ const i2 = indices[baseIdx + 2];
60832
+ expandedPosition[i * 9 + 0] = position[i0 * 3 + 0];
60833
+ expandedPosition[i * 9 + 1] = position[i0 * 3 + 1];
60834
+ expandedPosition[i * 9 + 2] = position[i0 * 3 + 2];
60835
+ expandedPosition[i * 9 + 3] = position[i1 * 3 + 0];
60836
+ expandedPosition[i * 9 + 4] = position[i1 * 3 + 1];
60837
+ expandedPosition[i * 9 + 5] = position[i1 * 3 + 2];
60838
+ expandedPosition[i * 9 + 6] = position[i2 * 3 + 0];
60839
+ expandedPosition[i * 9 + 7] = position[i2 * 3 + 1];
60840
+ expandedPosition[i * 9 + 8] = position[i2 * 3 + 2];
60841
+ expandedNormal[i * 9 + 0] = normal[i0 * 3 + 0];
60842
+ expandedNormal[i * 9 + 1] = normal[i0 * 3 + 1];
60843
+ expandedNormal[i * 9 + 2] = normal[i0 * 3 + 2];
60844
+ expandedNormal[i * 9 + 3] = normal[i1 * 3 + 0];
60845
+ expandedNormal[i * 9 + 4] = normal[i1 * 3 + 1];
60846
+ expandedNormal[i * 9 + 5] = normal[i1 * 3 + 2];
60847
+ expandedNormal[i * 9 + 6] = normal[i2 * 3 + 0];
60848
+ expandedNormal[i * 9 + 7] = normal[i2 * 3 + 1];
60849
+ expandedNormal[i * 9 + 8] = normal[i2 * 3 + 2];
60850
+ if (expandedColor && color) {
60851
+ expandedColor[i * 9 + 0] = color[i0 * 3 + 0];
60852
+ expandedColor[i * 9 + 1] = color[i0 * 3 + 1];
60853
+ expandedColor[i * 9 + 2] = color[i0 * 3 + 2];
60854
+ expandedColor[i * 9 + 3] = color[i1 * 3 + 0];
60855
+ expandedColor[i * 9 + 4] = color[i1 * 3 + 1];
60856
+ expandedColor[i * 9 + 5] = color[i1 * 3 + 2];
60857
+ expandedColor[i * 9 + 6] = color[i2 * 3 + 0];
60858
+ expandedColor[i * 9 + 7] = color[i2 * 3 + 1];
60859
+ expandedColor[i * 9 + 8] = color[i2 * 3 + 2];
60860
+ }
60861
+ }
60862
+ finalPosition = expandedPosition;
60863
+ finalNormal = expandedNormal;
60864
+ finalColor = expandedColor;
60865
+ const sequentialIndices = new Uint32Array(triangleCount * 3);
60866
+ for (let i = 0; i < triangleCount * 3; i++) {
60867
+ sequentialIndices[i] = i;
60868
+ }
60869
+ finalIndices = sequentialIndices;
60870
+ } else {
60871
+ finalIndices = new Uint32Array(indices);
60872
+ finalUv = uv;
60873
+ }
60874
+ return {
60875
+ vertexCount: hasTexcoord && faceVertexUvs.length > 0 ? finalPosition.length / 3 : vertexCount,
60876
+ faceCount,
60877
+ position: finalPosition,
60878
+ normal: finalNormal,
60879
+ color: finalColor,
60880
+ uv: finalUv,
60881
+ indices: finalIndices,
60882
+ textureFiles: textureFiles.length > 0 ? textureFiles : void 0,
60883
+ triangleTexnumbers: triangleTexnumbers.length > 0 ? triangleTexnumbers : void 0
60884
+ };
60885
+ }
60886
+ function parsePlyPointCloud(buffer) {
60887
+ const header = parsePlyHeader(buffer);
60888
+ const { format } = header;
60889
+ if (format === "ascii") {
60890
+ return parsePlyPointCloudASCII(buffer, header);
60891
+ } else {
60892
+ return parsePlyPointCloudBinary(buffer, header);
60893
+ }
60894
+ }
60895
+ function parsePlyPointCloudBinary(buffer, header) {
60896
+ const { vertexCount, properties, headerByteLength } = header;
60897
+ const payload = new DataView(buffer, headerByteLength);
60898
+ const has = (n) => properties.find((p) => p.name === n) != null;
60899
+ const propIndex = (n) => properties.findIndex((p) => p.name === n);
60900
+ const position = new Float32Array(vertexCount * 3);
60901
+ const hasColor = (has("red") || has("r")) && (has("green") || has("g")) && (has("blue") || has("b"));
60902
+ const hasAlpha = has("alpha") || has("a");
60903
+ const color = hasColor ? new Uint8Array(vertexCount * 4) : void 0;
60904
+ const propOffsets = [];
60905
+ let stride = 0;
60906
+ for (const p of properties) {
60907
+ propOffsets.push(stride);
60908
+ stride += byteSizeOfType(p.type);
60909
+ }
60910
+ let base = 0;
60911
+ for (let v = 0; v < vertexCount; v++) {
60912
+ const vOffset = base;
60913
+ const ix = propIndex("x");
60914
+ const iy = propIndex("y");
60915
+ const iz = propIndex("z");
60916
+ if (ix < 0 || iy < 0 || iz < 0) {
60917
+ throw new Error("PLY: Missing x/y/z for vertex");
60918
+ }
60919
+ position[v * 3 + 0] = readByType(payload, vOffset + propOffsets[ix], properties[ix].type);
60920
+ position[v * 3 + 1] = readByType(payload, vOffset + propOffsets[iy], properties[iy].type);
60921
+ position[v * 3 + 2] = readByType(payload, vOffset + propOffsets[iz], properties[iz].type);
60922
+ if (color) {
60923
+ const rIdx = propIndex("red") >= 0 ? propIndex("red") : propIndex("r");
60924
+ const gIdx = propIndex("green") >= 0 ? propIndex("green") : propIndex("g");
60925
+ const bIdx = propIndex("blue") >= 0 ? propIndex("blue") : propIndex("b");
60926
+ const aIdx = hasAlpha ? propIndex("alpha") >= 0 ? propIndex("alpha") : propIndex("a") : -1;
60927
+ if (rIdx >= 0 && gIdx >= 0 && bIdx >= 0) {
60928
+ let r = readByType(payload, vOffset + propOffsets[rIdx], properties[rIdx].type);
60929
+ let g = readByType(payload, vOffset + propOffsets[gIdx], properties[gIdx].type);
60930
+ let b = readByType(payload, vOffset + propOffsets[bIdx], properties[bIdx].type);
60931
+ let a = 255;
60932
+ if (properties[rIdx].type === "float" || properties[rIdx].type === "float32" || properties[rIdx].type === "double" || properties[rIdx].type === "float64") {
60933
+ r = Math.round(r * 255);
60934
+ g = Math.round(g * 255);
60935
+ b = Math.round(b * 255);
60936
+ }
60937
+ if (aIdx >= 0) {
60938
+ a = readByType(payload, vOffset + propOffsets[aIdx], properties[aIdx].type);
60939
+ if (properties[aIdx].type === "float" || properties[aIdx].type === "float32" || properties[aIdx].type === "double" || properties[aIdx].type === "float64") {
60940
+ a = Math.round(a * 255);
60941
+ }
60942
+ }
60943
+ color[v * 4 + 0] = Math.max(0, Math.min(255, r));
60944
+ color[v * 4 + 1] = Math.max(0, Math.min(255, g));
60945
+ color[v * 4 + 2] = Math.max(0, Math.min(255, b));
60946
+ color[v * 4 + 3] = Math.max(0, Math.min(255, a));
60947
+ }
60948
+ }
60949
+ base += stride;
60950
+ }
60951
+ return {
60952
+ vertexCount,
60953
+ position,
60954
+ color
60955
+ };
60956
+ }
60957
+ function parsePlyPointCloudASCII(buffer, header) {
60958
+ const { vertexCount, properties } = header;
60959
+ const text = new TextDecoder("utf-8").decode(buffer);
60960
+ const headerEnd = text.indexOf("end_header");
60961
+ if (headerEnd < 0) {
60962
+ throw new Error("PLY: Invalid PLY header");
60963
+ }
60964
+ let bodyStart = headerEnd + "end_header".length;
60965
+ while (bodyStart < text.length && (text[bodyStart] === " " || text[bodyStart] === "\n" || text[bodyStart] === "\r")) {
60966
+ bodyStart++;
60967
+ }
60968
+ const bodyText = text.substring(bodyStart);
60969
+ const tokens = bodyText.split(/\s+/).filter((token) => token.length > 0);
60970
+ let tokenIndex = 0;
60971
+ const has = (n) => properties.find((p) => p.name === n) != null;
60972
+ const parseASCIINumber = (type) => {
60973
+ if (tokenIndex >= tokens.length) {
60974
+ throw new Error("PLY: Unexpected end of file");
60975
+ }
60976
+ const value = tokens[tokenIndex++];
60977
+ switch (type) {
60978
+ case "char":
60979
+ case "uchar":
60980
+ case "short":
60981
+ case "ushort":
60982
+ case "int":
60983
+ case "uint":
60984
+ case "int8":
60985
+ case "uint8":
60986
+ case "int16":
60987
+ case "uint16":
60988
+ case "int32":
60989
+ case "uint32":
60990
+ return parseInt(value);
60991
+ case "float":
60992
+ case "double":
60993
+ case "float32":
60994
+ case "float64":
60995
+ return parseFloat(value);
60996
+ default:
60997
+ return parseFloat(value);
60998
+ }
60999
+ };
61000
+ const position = new Float32Array(vertexCount * 3);
61001
+ const hasColor = (has("red") || has("r")) && (has("green") || has("g")) && (has("blue") || has("b"));
61002
+ const hasAlpha = has("alpha") || has("a");
61003
+ const color = hasColor ? new Uint8Array(vertexCount * 4) : void 0;
59940
61004
  const propIndex = (n) => properties.findIndex((p) => p.name === n);
59941
61005
  const xIdx = propIndex("x");
59942
61006
  const yIdx = propIndex("y");
59943
61007
  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;
61008
+ const rIdx = hasColor ? propIndex("red") >= 0 ? propIndex("red") : propIndex("r") : -1;
61009
+ const gIdx = hasColor ? propIndex("green") >= 0 ? propIndex("green") : propIndex("g") : -1;
61010
+ const bIdx = hasColor ? propIndex("blue") >= 0 ? propIndex("blue") : propIndex("b") : -1;
61011
+ const aIdx = hasAlpha ? propIndex("alpha") >= 0 ? propIndex("alpha") : propIndex("a") : -1;
59952
61012
  for (let v = 0; v < vertexCount; v++) {
59953
61013
  for (let pIdx = 0; pIdx < properties.length; pIdx++) {
59954
61014
  const prop = properties[pIdx];
@@ -59959,210 +61019,28 @@ fn frag(){
59959
61019
  position[v * 3 + 1] = value;
59960
61020
  } else if (pIdx === zIdx) {
59961
61021
  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
61022
  } else if (pIdx === rIdx && color) {
59969
- color[v * 3 + 0] = prop.type === "uchar" || prop.type === "uint8" ? value / 255 : value;
61023
+ const r = prop.type === "uchar" || prop.type === "uint8" ? value : Math.round(value * 255);
61024
+ color[v * 4 + 0] = Math.max(0, Math.min(255, r));
59970
61025
  } else if (pIdx === gIdx && color) {
59971
- color[v * 3 + 1] = prop.type === "uchar" || prop.type === "uint8" ? value / 255 : value;
61026
+ const g = prop.type === "uchar" || prop.type === "uint8" ? value : Math.round(value * 255);
61027
+ color[v * 4 + 1] = Math.max(0, Math.min(255, g));
59972
61028
  } 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;
61029
+ const b = prop.type === "uchar" || prop.type === "uint8" ? value : Math.round(value * 255);
61030
+ color[v * 4 + 2] = Math.max(0, Math.min(255, b));
61031
+ } else if (pIdx === aIdx && color) {
61032
+ const a = prop.type === "uchar" || prop.type === "uint8" ? value : Math.round(value * 255);
61033
+ color[v * 4 + 3] = Math.max(0, Math.min(255, a));
60095
61034
  }
60096
61035
  }
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
- }
61036
+ if (color && aIdx < 0) {
61037
+ color[v * 4 + 3] = 255;
60143
61038
  }
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
61039
  }
60156
61040
  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
61041
+ vertexCount,
61042
+ position,
61043
+ color
60166
61044
  };
60167
61045
  }
60168
61046
 
@@ -60297,6 +61175,23 @@ fn frag(){
60297
61175
  break;
60298
61176
  }
60299
61177
  case PlyMode.PointCloud: {
61178
+ const plyData = parsePlyPointCloud(buffer);
61179
+ const pointCloudObj = new exports.Object3D();
61180
+ pointCloudObj.name = "PLYPointCloud";
61181
+ const pointCloudObjRoot = new exports.Object3D();
61182
+ pointCloudObjRoot.name = "PLYPointCloudRoot";
61183
+ pointCloudObj.addChild(pointCloudObjRoot);
61184
+ const renderer = pointCloudObjRoot.addComponent(exports.PointCloudRenderer);
61185
+ if (plyData.color) {
61186
+ renderer.initFromData(plyData.position, plyData.color, plyData.vertexCount);
61187
+ } else {
61188
+ const defaultColors = new Uint8Array(plyData.vertexCount * 4);
61189
+ defaultColors.fill(255);
61190
+ renderer.initFromData(plyData.position, defaultColors, plyData.vertexCount);
61191
+ }
61192
+ renderer.setPointShape("circle");
61193
+ renderer.setPointSize(4);
61194
+ this.data = pointCloudObj;
60300
61195
  break;
60301
61196
  }
60302
61197
  case PlyMode.Mesh: {
@@ -68536,69 +69431,6 @@ fn frag(){
68536
69431
  }
68537
69432
  }
68538
69433
 
68539
- class Float32ArrayTexture extends Texture {
68540
- create(width, height, data, filtering = true) {
68541
- let device = webGPUContext.device;
68542
- const bytesPerRow = width * 4 * 4;
68543
- this.format = GPUTextureFormat.rgba32float;
68544
- let mipmapCount = 1;
68545
- this.createTextureDescriptor(width, height, mipmapCount, this.format);
68546
- const textureDataBuffer = device.createBuffer({
68547
- size: data.byteLength,
68548
- usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
68549
- });
68550
- device.queue.writeBuffer(textureDataBuffer, 0, data);
68551
- const commandEncoder = GPUContext.beginCommandEncoder();
68552
- commandEncoder.copyBufferToTexture(
68553
- {
68554
- buffer: textureDataBuffer,
68555
- bytesPerRow
68556
- },
68557
- {
68558
- texture: this.getGPUTexture()
68559
- },
68560
- {
68561
- width,
68562
- height,
68563
- depthOrArrayLayers: 1
68564
- }
68565
- );
68566
- GPUContext.endCommandEncoder(commandEncoder);
68567
- if (filtering) {
68568
- this.samplerBindingLayout.type = `non-filtering`;
68569
- this.textureBindingLayout.sampleType = `unfilterable-float`;
68570
- }
68571
- this.gpuSampler = device.createSampler({});
68572
- }
68573
- fromBuffer(width, height, textureDataBuffer) {
68574
- let device = webGPUContext.device;
68575
- const bytesPerRow = width * 4 * 4;
68576
- this.format = GPUTextureFormat.rgba32float;
68577
- this.mipmapCount = 1;
68578
- this.createTextureDescriptor(width, height, this.mipmapCount, this.format);
68579
- const commandEncoder = GPUContext.beginCommandEncoder();
68580
- commandEncoder.copyBufferToTexture(
68581
- {
68582
- buffer: textureDataBuffer,
68583
- bytesPerRow
68584
- },
68585
- {
68586
- texture: this.getGPUTexture()
68587
- },
68588
- {
68589
- width,
68590
- height,
68591
- depthOrArrayLayers: 1
68592
- }
68593
- );
68594
- GPUContext.endCommandEncoder(commandEncoder);
68595
- this.samplerBindingLayout.type = `non-filtering`;
68596
- this.textureBindingLayout.sampleType = `unfilterable-float`;
68597
- this.gpuSampler = device.createSampler({});
68598
- return this;
68599
- }
68600
- }
68601
-
68602
69434
  class SolidColorSky extends LDRTextureCube {
68603
69435
  _internalTexture;
68604
69436
  _minSize = 32;
@@ -70386,6 +71218,10 @@ fn frag(){
70386
71218
  exports.PlyMode = PlyMode;
70387
71219
  exports.PlyParser = PlyParser;
70388
71220
  exports.PointClassification = PointClassification;
71221
+ exports.PointCloudGeometry = PointCloudGeometry;
71222
+ exports.PointCloudMaterial = PointCloudMaterial;
71223
+ exports.PointCloud_FS = PointCloud_FS;
71224
+ exports.PointCloud_VS = PointCloud_VS;
70389
71225
  exports.PointLightShadowRenderer = PointLightShadowRenderer;
70390
71226
  exports.PointShadowCubeCamera = PointShadowCubeCamera;
70391
71227
  exports.PointerEvent3D = PointerEvent3D;
@@ -70726,6 +71562,7 @@ fn frag(){
70726
71562
  exports.parsePlyGaussianSplat = parsePlyGaussianSplat;
70727
71563
  exports.parsePlyHeader = parsePlyHeader;
70728
71564
  exports.parsePlyMesh = parsePlyMesh;
71565
+ exports.parsePlyPointCloud = parsePlyPointCloud;
70729
71566
  exports.perm = perm;
70730
71567
  exports.post = post;
70731
71568
  exports.priorityCallback = priorityCallback;