@d5techs/3dgs-lib 1.4.12 → 1.4.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/3dgs-lib.js CHANGED
@@ -2474,10 +2474,16 @@ class MeshRenderer {
2474
2474
  this.lightDir[2],
2475
2475
  this.ambientIntensity
2476
2476
  ]);
2477
- this.renderItems(pass, this.items, device, vpMatrix, lightData, false);
2478
- this.renderItems(pass, this.overlayItems, device, vpMatrix, lightData, true);
2477
+ const unlitLightData = new Float32Array([
2478
+ this.lightDir[0],
2479
+ this.lightDir[1],
2480
+ this.lightDir[2],
2481
+ 1
2482
+ ]);
2483
+ this.renderItems(pass, this.items, device, vpMatrix, lightData, unlitLightData, false);
2484
+ this.renderItems(pass, this.overlayItems, device, vpMatrix, lightData, unlitLightData, true);
2479
2485
  }
2480
- renderItems(pass, items, device, vpMatrix, lightData, overlay) {
2486
+ renderItems(pass, items, device, vpMatrix, lightData, unlitLightData, overlay) {
2481
2487
  if (items.length === 0) return;
2482
2488
  for (const item of items) {
2483
2489
  const { mesh, material, uniformBuffer, bindGroup } = item;
@@ -2485,7 +2491,11 @@ class MeshRenderer {
2485
2491
  device.queue.writeBuffer(uniformBuffer, 64, mesh.modelMatrix.buffer);
2486
2492
  const colorData = new Float32Array(material.baseColorFactor);
2487
2493
  device.queue.writeBuffer(uniformBuffer, 128, colorData.buffer);
2488
- device.queue.writeBuffer(uniformBuffer, 144, lightData.buffer);
2494
+ if (material.unlit) {
2495
+ device.queue.writeBuffer(uniformBuffer, 144, unlitLightData.buffer);
2496
+ } else {
2497
+ device.queue.writeBuffer(uniformBuffer, 144, lightData.buffer);
2498
+ }
2489
2499
  let pipeline;
2490
2500
  if (overlay) {
2491
2501
  if (mesh.hasUV) {
@@ -13591,7 +13601,16 @@ class HotspotManager {
13591
13601
  let closestIdx = -1;
13592
13602
  for (let i = 0; i < this.hotspots.length; i++) {
13593
13603
  const h = this.hotspots[i];
13594
- const [px, py, pz] = h.position;
13604
+ let px, py, pz;
13605
+ const firstMesh = this.meshRenderer.getOverlayMeshByIndex(h.meshStartIndex);
13606
+ if (firstMesh) {
13607
+ const m = firstMesh.modelMatrix;
13608
+ px = m[12];
13609
+ py = m[13];
13610
+ pz = m[14];
13611
+ } else {
13612
+ [px, py, pz] = h.position;
13613
+ }
13595
13614
  const clipW = vp[3] * px + vp[7] * py + vp[11] * pz + vp[15];
13596
13615
  if (clipW <= 0) continue;
13597
13616
  const clipX = (vp[0] * px + vp[4] * py + vp[8] * pz + vp[12]) / clipW;
@@ -13999,6 +14018,77 @@ class HotspotManager {
13999
14018
  this.indicatorMesh.hasUV = false;
14000
14019
  this.indicatorMesh.indexFormat = "uint16";
14001
14020
  }
14021
+ /**
14022
+ * 在 OBJ 本地坐标系中创建背景圆盘 Mesh,
14023
+ * 使其与 OBJ 图标共享同一 model matrix,billboard/缩放自动生效。
14024
+ */
14025
+ createBackgroundDisk(objBbox) {
14026
+ const device = this.renderer.device;
14027
+ const segments = 48;
14028
+ const cx = (objBbox.min[0] + objBbox.max[0]) / 2;
14029
+ const cy = (objBbox.min[1] + objBbox.max[1]) / 2;
14030
+ const cz = Math.min(objBbox.min[2], objBbox.max[2]) - 5e-4;
14031
+ const dx = objBbox.max[0] - objBbox.min[0];
14032
+ const dy = objBbox.max[1] - objBbox.min[1];
14033
+ const maxDim2D = Math.max(dx, dy, 1e-6);
14034
+ const radius = maxDim2D * 0.85;
14035
+ const vertexCount = segments + 1;
14036
+ const stride = 6;
14037
+ const vertexData = new Float32Array(vertexCount * stride);
14038
+ vertexData[0] = cx;
14039
+ vertexData[1] = cy;
14040
+ vertexData[2] = cz;
14041
+ vertexData[3] = 0;
14042
+ vertexData[4] = 0;
14043
+ vertexData[5] = 1;
14044
+ for (let i = 0; i < segments; i++) {
14045
+ const angle = i / segments * Math.PI * 2;
14046
+ const off = (i + 1) * stride;
14047
+ vertexData[off + 0] = cx + Math.cos(angle) * radius;
14048
+ vertexData[off + 1] = cy + Math.sin(angle) * radius;
14049
+ vertexData[off + 2] = cz;
14050
+ vertexData[off + 3] = 0;
14051
+ vertexData[off + 4] = 0;
14052
+ vertexData[off + 5] = 1;
14053
+ }
14054
+ const indices = [];
14055
+ for (let i = 0; i < segments; i++) {
14056
+ indices.push(0, i + 1, (i + 1) % segments + 1);
14057
+ }
14058
+ const vertexBuffer = device.createBuffer({
14059
+ size: vertexData.byteLength,
14060
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
14061
+ });
14062
+ device.queue.writeBuffer(vertexBuffer, 0, vertexData);
14063
+ const indexData = new Uint16Array(indices);
14064
+ const alignedSize = Math.ceil(indexData.byteLength / 4) * 4;
14065
+ const alignedBuf = new Uint8Array(alignedSize);
14066
+ alignedBuf.set(
14067
+ new Uint8Array(indexData.buffer, indexData.byteOffset, indexData.byteLength)
14068
+ );
14069
+ const indexBuffer = device.createBuffer({
14070
+ size: alignedSize,
14071
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST
14072
+ });
14073
+ device.queue.writeBuffer(indexBuffer, 0, alignedBuf);
14074
+ const bbox = {
14075
+ min: [cx - radius, cy - radius, cz],
14076
+ max: [cx + radius, cy + radius, cz],
14077
+ center: [cx, cy, cz],
14078
+ radius
14079
+ };
14080
+ const mesh = new Mesh(vertexBuffer, vertexCount, indexBuffer, indices.length, bbox);
14081
+ mesh.hasUV = false;
14082
+ mesh.indexFormat = "uint16";
14083
+ const material = {
14084
+ baseColorFactor: [0.13, 0.59, 0.95, 1],
14085
+ baseColorTexture: null,
14086
+ metallicFactor: 0,
14087
+ roughnessFactor: 0.5,
14088
+ doubleSided: true
14089
+ };
14090
+ return { mesh, material };
14091
+ }
14002
14092
  showIndicator() {
14003
14093
  if (!this.indicatorMesh || this.indicatorAdded) return;
14004
14094
  const material = {
@@ -14119,15 +14209,27 @@ class HotspotManager {
14119
14209
  (firstBbox.min[2] + firstBbox.max[2]) / 2
14120
14210
  ];
14121
14211
  }
14122
- for (const { mesh, material } of loadedMeshes) {
14212
+ for (const { mesh } of loadedMeshes) {
14123
14213
  this.applyIndicatorTransform(mesh, snap);
14214
+ }
14215
+ let bgDiskMeshCount = 0;
14216
+ if (firstBbox) {
14217
+ const disk = this.createBackgroundDisk(firstBbox);
14218
+ disk.mesh.modelMatrix.set(loadedMeshes[0].mesh.modelMatrix);
14219
+ this.decomposeModelMatrix(disk.mesh);
14220
+ this.meshRenderer.addOverlayMesh(disk.mesh, disk.material);
14221
+ bgDiskMeshCount = 1;
14222
+ }
14223
+ for (const { mesh, material } of loadedMeshes) {
14224
+ material.unlit = true;
14124
14225
  this.meshRenderer.addOverlayMesh(mesh, material);
14125
14226
  }
14126
14227
  const info = {
14127
14228
  position: [...snap.point],
14128
14229
  normal: [...snap.normal],
14129
14230
  meshStartIndex,
14130
- meshCount: loadedMeshes.length,
14231
+ meshCount: bgDiskMeshCount + loadedMeshes.length,
14232
+ bgDiskMeshCount,
14131
14233
  billboard: false,
14132
14234
  placedScale,
14133
14235
  placedNormalOffset: snap.normalOffset,
@@ -14326,7 +14428,7 @@ class HotspotManager {
14326
14428
  (firstBbox.min[2] + firstBbox.max[2]) / 2
14327
14429
  ];
14328
14430
  }
14329
- for (const { mesh, material } of loadedMeshes) {
14431
+ for (const { mesh } of loadedMeshes) {
14330
14432
  const bbox = mesh.getLocalBoundingBox();
14331
14433
  let s = placedScale;
14332
14434
  let lcx = 0, lcy = 0, lcz = 0;
@@ -14362,13 +14464,25 @@ class HotspotManager {
14362
14464
  m[14] = position[2] + nz * normalOffset - owz;
14363
14465
  m[15] = 1;
14364
14466
  this.decomposeModelMatrix(mesh);
14467
+ }
14468
+ let bgDiskMeshCount = 0;
14469
+ if (firstBbox) {
14470
+ const disk = this.createBackgroundDisk(firstBbox);
14471
+ disk.mesh.modelMatrix.set(loadedMeshes[0].mesh.modelMatrix);
14472
+ this.decomposeModelMatrix(disk.mesh);
14473
+ this.meshRenderer.addOverlayMesh(disk.mesh, disk.material);
14474
+ bgDiskMeshCount = 1;
14475
+ }
14476
+ for (const { mesh, material } of loadedMeshes) {
14477
+ material.unlit = true;
14365
14478
  this.meshRenderer.addOverlayMesh(mesh, material);
14366
14479
  }
14367
14480
  const info = {
14368
14481
  position: [...position],
14369
14482
  normal: [...normal],
14370
14483
  meshStartIndex,
14371
- meshCount: loadedMeshes.length,
14484
+ meshCount: bgDiskMeshCount + loadedMeshes.length,
14485
+ bgDiskMeshCount,
14372
14486
  billboard: false,
14373
14487
  placedScale,
14374
14488
  placedNormalOffset: normalOffset,