@d5techs/3dgs-lib 1.4.78 → 1.4.80

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
@@ -17613,19 +17613,19 @@ class SphereSelection {
17613
17613
  inputWrap.style.cssText = "display:inline-flex; align-items:center; gap:2px;";
17614
17614
  const input = document.createElement("input");
17615
17615
  input.type = "number";
17616
- input.min = "0.01";
17617
- input.step = "0.1";
17618
- input.value = this._radius.toFixed(2);
17616
+ input.min = "1";
17617
+ input.step = "1";
17618
+ input.value = String(this._radius);
17619
17619
  input.style.cssText = `
17620
- width:50px; padding:3px 4px; border:1px solid #555; border-radius:4px;
17620
+ width:40px; padding:3px 4px; border:1px solid #555; border-radius:4px;
17621
17621
  background:#222; color:#ddd; font-size:12px; text-align:center;
17622
17622
  `;
17623
17623
  const label = document.createElement("span");
17624
17624
  label.textContent = "Radius";
17625
17625
  label.style.cssText = "color:#888; font-size:11px;";
17626
17626
  input.addEventListener("change", () => {
17627
- const v = Math.max(0.01, parseFloat(input.value) || 0.01);
17628
- input.value = v.toFixed(2);
17627
+ const v = Math.max(1, Math.round(parseFloat(input.value) || 1));
17628
+ input.value = String(v);
17629
17629
  this._radius = v;
17630
17630
  this.callbacks.onRadiusChanged(v);
17631
17631
  });
@@ -17642,8 +17642,8 @@ class SphereSelection {
17642
17642
  return this._radius;
17643
17643
  }
17644
17644
  setRadius(radius) {
17645
- this._radius = radius;
17646
- this.radiusInput.value = radius.toFixed(2);
17645
+ this._radius = Math.round(radius);
17646
+ this.radiusInput.value = String(this._radius);
17647
17647
  }
17648
17648
  activate() {
17649
17649
  this.toolbar.style.display = "flex";
@@ -17702,19 +17702,19 @@ class BoxSelection {
17702
17702
  wrap.style.cssText = "display:inline-flex; align-items:center; gap:2px;";
17703
17703
  const input = document.createElement("input");
17704
17704
  input.type = "number";
17705
- input.min = "0.01";
17706
- input.step = "0.1";
17707
- input.value = initial.toFixed(2);
17705
+ input.min = "1";
17706
+ input.step = "1";
17707
+ input.value = String(Math.round(initial));
17708
17708
  input.style.cssText = `
17709
- width:50px; padding:3px 4px; border:1px solid #555; border-radius:4px;
17709
+ width:40px; padding:3px 4px; border:1px solid #555; border-radius:4px;
17710
17710
  background:#222; color:#ddd; font-size:12px; text-align:center;
17711
17711
  `;
17712
17712
  const label = document.createElement("span");
17713
17713
  label.textContent = placeholder;
17714
17714
  label.style.cssText = "color:#888; font-size:11px;";
17715
17715
  input.addEventListener("change", () => {
17716
- const v = Math.max(0.01, parseFloat(input.value) || 0.01);
17717
- input.value = v.toFixed(2);
17716
+ const v = Math.max(1, Math.round(parseFloat(input.value) || 1));
17717
+ input.value = String(v);
17718
17718
  onChange(v);
17719
17719
  });
17720
17720
  wrap.appendChild(input);
@@ -17757,12 +17757,12 @@ class BoxSelection {
17757
17757
  return this._lenZ;
17758
17758
  }
17759
17759
  setDimensions(lenX, lenY, lenZ) {
17760
- this._lenX = lenX;
17761
- this._lenY = lenY;
17762
- this._lenZ = lenZ;
17763
- this.inputX.value = lenX.toFixed(2);
17764
- this.inputY.value = lenY.toFixed(2);
17765
- this.inputZ.value = lenZ.toFixed(2);
17760
+ this._lenX = Math.round(lenX);
17761
+ this._lenY = Math.round(lenY);
17762
+ this._lenZ = Math.round(lenZ);
17763
+ this.inputX.value = String(this._lenX);
17764
+ this.inputY.value = String(this._lenY);
17765
+ this.inputZ.value = String(this._lenZ);
17766
17766
  }
17767
17767
  activate() {
17768
17768
  this.toolbar.style.display = "flex";
@@ -17883,16 +17883,17 @@ class SelectionVolumeRenderer {
17883
17883
  constructor(renderer, camera) {
17884
17884
  __publicField(this, "renderer");
17885
17885
  __publicField(this, "camera");
17886
- __publicField(this, "pipeline", null);
17886
+ __publicField(this, "frontPipeline", null);
17887
+ __publicField(this, "behindPipeline", null);
17887
17888
  __publicField(this, "uniformBuffer", null);
17888
17889
  __publicField(this, "bindGroup", null);
17889
17890
  __publicField(this, "vertexBuffer", null);
17890
17891
  __publicField(this, "_volume", { type: null, center: [0, 0, 0], dimensions: [2, 2, 2] });
17891
17892
  __publicField(this, "vertexCount", 0);
17892
- __publicField(this, "lineColor", [0.4, 0.9, 1]);
17893
+ __publicField(this, "frontColor", [0.4, 0.9, 1]);
17893
17894
  this.renderer = renderer;
17894
17895
  this.camera = camera;
17895
- this.createPipeline();
17896
+ this.createPipelines();
17896
17897
  this.vertexBuffer = this.renderer.device.createBuffer({
17897
17898
  size: 65536,
17898
17899
  usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
@@ -17912,12 +17913,16 @@ class SelectionVolumeRenderer {
17912
17913
  setDimensions(a, b, c) {
17913
17914
  this._volume.dimensions = [a, b, c];
17914
17915
  }
17915
- createPipeline() {
17916
+ createPipelines() {
17916
17917
  const device = this.renderer.device;
17917
17918
  const shaderCode = (
17918
17919
  /* wgsl */
17919
17920
  `
17920
- struct Uniforms { viewProjection: mat4x4<f32> }
17921
+ struct Uniforms {
17922
+ viewMatrix: mat4x4<f32>,
17923
+ projMatrix: mat4x4<f32>,
17924
+ modelMatrix: mat4x4<f32>,
17925
+ }
17921
17926
  @group(0) @binding(0) var<uniform> uniforms: Uniforms;
17922
17927
 
17923
17928
  struct VI { @location(0) position: vec3<f32>, @location(1) color: vec3<f32> }
@@ -17925,62 +17930,77 @@ class SelectionVolumeRenderer {
17925
17930
 
17926
17931
  @vertex fn vs(i: VI) -> VO {
17927
17932
  var o: VO;
17928
- o.position = uniforms.viewProjection * vec4(i.position, 1.0);
17933
+ let worldPos = uniforms.modelMatrix * vec4(i.position, 1.0);
17934
+ let viewPos = uniforms.viewMatrix * worldPos;
17935
+ o.position = uniforms.projMatrix * viewPos;
17929
17936
  o.color = i.color;
17930
17937
  return o;
17931
17938
  }
17932
17939
  @fragment fn fs(i: VO) -> @location(0) vec4<f32> {
17933
- return vec4(i.color, 0.6);
17940
+ return vec4(i.color, 0.7);
17941
+ }
17942
+ @fragment fn fsBehind(i: VO) -> @location(0) vec4<f32> {
17943
+ return vec4(i.color * 0.35, 0.2);
17934
17944
  }
17935
17945
  `
17936
17946
  );
17937
17947
  const sm = device.createShaderModule({ code: shaderCode });
17938
- this.uniformBuffer = device.createBuffer({ size: 64, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
17948
+ this.uniformBuffer = device.createBuffer({ size: 192, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
17939
17949
  const bgl = device.createBindGroupLayout({
17940
- entries: [{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: "uniform" } }]
17950
+ entries: [{ binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } }]
17941
17951
  });
17942
17952
  this.bindGroup = device.createBindGroup({ layout: bgl, entries: [{ binding: 0, resource: { buffer: this.uniformBuffer } }] });
17943
- this.pipeline = device.createRenderPipeline({
17944
- layout: device.createPipelineLayout({ bindGroupLayouts: [bgl] }),
17945
- vertex: {
17953
+ const layout = device.createPipelineLayout({ bindGroupLayouts: [bgl] });
17954
+ const vertexState = {
17955
+ module: sm,
17956
+ entryPoint: "vs",
17957
+ buffers: [{
17958
+ arrayStride: 24,
17959
+ attributes: [
17960
+ { shaderLocation: 0, offset: 0, format: "float32x3" },
17961
+ { shaderLocation: 1, offset: 12, format: "float32x3" }
17962
+ ]
17963
+ }]
17964
+ };
17965
+ const blendState = {
17966
+ color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha", operation: "add" },
17967
+ alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha", operation: "add" }
17968
+ };
17969
+ this.frontPipeline = device.createRenderPipeline({
17970
+ layout,
17971
+ vertex: vertexState,
17972
+ fragment: {
17946
17973
  module: sm,
17947
- entryPoint: "vs",
17948
- buffers: [{
17949
- arrayStride: 24,
17950
- attributes: [
17951
- { shaderLocation: 0, offset: 0, format: "float32x3" },
17952
- { shaderLocation: 1, offset: 12, format: "float32x3" }
17953
- ]
17954
- }]
17974
+ entryPoint: "fs",
17975
+ targets: [{ format: this.renderer.format, blend: blendState }]
17955
17976
  },
17977
+ primitive: { topology: "line-list", cullMode: "none" },
17978
+ depthStencil: { format: this.renderer.depthFormat, depthWriteEnabled: false, depthCompare: "less-equal" }
17979
+ });
17980
+ this.behindPipeline = device.createRenderPipeline({
17981
+ layout,
17982
+ vertex: vertexState,
17956
17983
  fragment: {
17957
17984
  module: sm,
17958
- entryPoint: "fs",
17959
- targets: [{
17960
- format: this.renderer.format,
17961
- blend: {
17962
- color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha", operation: "add" },
17963
- alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha", operation: "add" }
17964
- }
17965
- }]
17985
+ entryPoint: "fsBehind",
17986
+ targets: [{ format: this.renderer.format, blend: blendState }]
17966
17987
  },
17967
17988
  primitive: { topology: "line-list", cullMode: "none" },
17968
- depthStencil: { format: this.renderer.depthFormat, depthWriteEnabled: false, depthCompare: "always" }
17989
+ depthStencil: { format: this.renderer.depthFormat, depthWriteEnabled: false, depthCompare: "greater" }
17969
17990
  });
17970
17991
  }
17971
17992
  // ========== Box: 12 edges + grid lines on all 6 faces ==========
17972
- generateBoxVertices() {
17973
- const [cx, cy, cz] = this._volume.center;
17993
+ generateBoxVertices(color) {
17974
17994
  const [lx, ly, lz] = this._volume.dimensions;
17975
17995
  const hx = lx / 2, hy = ly / 2, hz = lz / 2;
17976
- const [r, g, b] = this.lineColor;
17996
+ const [r, g, b] = color;
17977
17997
  const v = [];
17978
17998
  const line = (x12, y12, z12, x2, y2, z2) => {
17979
17999
  v.push(x12, y12, z12, r, g, b, x2, y2, z2, r, g, b);
17980
18000
  };
17981
- const x0 = cx - hx, x1 = cx + hx;
17982
- const y0 = cy - hy, y1 = cy + hy;
17983
- const z0 = cz - hz, z1 = cz + hz;
18001
+ const x0 = -hx, x1 = hx;
18002
+ const y0 = -hy, y1 = hy;
18003
+ const z0 = -hz, z1 = hz;
17984
18004
  line(x0, y0, z0, x1, y0, z0);
17985
18005
  line(x1, y0, z0, x1, y0, z1);
17986
18006
  line(x1, y0, z1, x0, y0, z1);
@@ -18024,25 +18044,24 @@ class SelectionVolumeRenderer {
18024
18044
  return new Float32Array(v);
18025
18045
  }
18026
18046
  // ========== Sphere: latitude + longitude rings ==========
18027
- generateSphereVertices() {
18028
- const [cx, cy, cz] = this._volume.center;
18047
+ generateSphereVertices(color) {
18029
18048
  const radius = this._volume.dimensions[0];
18030
- const [r, g, b] = this.lineColor;
18049
+ const [r, g, b] = color;
18031
18050
  const v = [];
18032
18051
  const addRing = (centerY, ringRadius) => {
18033
18052
  for (let i = 0; i < SEG; i++) {
18034
18053
  const a0 = i / SEG * Math.PI * 2;
18035
18054
  const a1 = (i + 1) / SEG * Math.PI * 2;
18036
18055
  v.push(
18037
- cx + Math.cos(a0) * ringRadius,
18038
- cy + centerY,
18039
- cz + Math.sin(a0) * ringRadius,
18056
+ Math.cos(a0) * ringRadius,
18057
+ centerY,
18058
+ Math.sin(a0) * ringRadius,
18040
18059
  r,
18041
18060
  g,
18042
18061
  b,
18043
- cx + Math.cos(a1) * ringRadius,
18044
- cy + centerY,
18045
- cz + Math.sin(a1) * ringRadius,
18062
+ Math.cos(a1) * ringRadius,
18063
+ centerY,
18064
+ Math.sin(a1) * ringRadius,
18046
18065
  r,
18047
18066
  g,
18048
18067
  b
@@ -18062,15 +18081,15 @@ class SelectionVolumeRenderer {
18062
18081
  const phi0 = i / SEG * Math.PI * 2;
18063
18082
  const phi1 = (i + 1) / SEG * Math.PI * 2;
18064
18083
  v.push(
18065
- cx + Math.cos(phi0) * Math.sin(theta) * radius,
18066
- cy + Math.sin(phi0) * radius,
18067
- cz + Math.cos(phi0) * Math.cos(theta) * radius,
18084
+ Math.sin(phi0) * Math.sin(theta) * radius,
18085
+ Math.cos(phi0) * radius,
18086
+ Math.sin(phi0) * Math.cos(theta) * radius,
18068
18087
  r,
18069
18088
  g,
18070
18089
  b,
18071
- cx + Math.cos(phi1) * Math.sin(theta) * radius,
18072
- cy + Math.sin(phi1) * radius,
18073
- cz + Math.cos(phi1) * Math.cos(theta) * radius,
18090
+ Math.sin(phi1) * Math.sin(theta) * radius,
18091
+ Math.cos(phi1) * radius,
18092
+ Math.sin(phi1) * Math.cos(theta) * radius,
18074
18093
  r,
18075
18094
  g,
18076
18095
  b
@@ -18080,19 +18099,36 @@ class SelectionVolumeRenderer {
18080
18099
  return new Float32Array(v);
18081
18100
  }
18082
18101
  render(pass) {
18083
- if (!this._volume.type || !this.pipeline || !this.bindGroup || !this.vertexBuffer || !this.uniformBuffer) return;
18102
+ if (!this._volume.type || !this.frontPipeline || !this.behindPipeline || !this.bindGroup || !this.vertexBuffer || !this.uniformBuffer) return;
18084
18103
  const device = this.renderer.device;
18085
- const verts = this._volume.type === "box" ? this.generateBoxVertices() : this.generateSphereVertices();
18086
- this.vertexCount = verts.length / 6;
18104
+ const [cx, cy, cz] = this._volume.center;
18105
+ const modelMatrix = new Float32Array(16);
18106
+ modelMatrix[0] = 1;
18107
+ modelMatrix[5] = 1;
18108
+ modelMatrix[10] = 1;
18109
+ modelMatrix[15] = 1;
18110
+ modelMatrix[12] = cx;
18111
+ modelMatrix[13] = cy;
18112
+ modelMatrix[14] = cz;
18113
+ const uniforms = new Float32Array(48);
18114
+ uniforms.set(this.camera.viewMatrix, 0);
18115
+ uniforms.set(this.camera.projectionMatrix, 16);
18116
+ uniforms.set(modelMatrix, 32);
18117
+ device.queue.writeBuffer(this.uniformBuffer, 0, uniforms);
18118
+ const frontVerts = this._volume.type === "box" ? this.generateBoxVertices(this.frontColor) : this.generateSphereVertices(this.frontColor);
18119
+ this.vertexCount = frontVerts.length / 6;
18087
18120
  if (this.vertexCount === 0) return;
18088
18121
  const needed = this.vertexCount * 24;
18089
18122
  if (needed > this.vertexBuffer.size) {
18090
18123
  this.vertexBuffer.destroy();
18091
18124
  this.vertexBuffer = device.createBuffer({ size: needed, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST });
18092
18125
  }
18093
- device.queue.writeBuffer(this.vertexBuffer, 0, verts.buffer);
18094
- device.queue.writeBuffer(this.uniformBuffer, 0, new Float32Array(this.camera.viewProjectionMatrix));
18095
- pass.setPipeline(this.pipeline);
18126
+ device.queue.writeBuffer(this.vertexBuffer, 0, frontVerts.buffer);
18127
+ pass.setPipeline(this.frontPipeline);
18128
+ pass.setBindGroup(0, this.bindGroup);
18129
+ pass.setVertexBuffer(0, this.vertexBuffer);
18130
+ pass.draw(this.vertexCount);
18131
+ pass.setPipeline(this.behindPipeline);
18096
18132
  pass.setBindGroup(0, this.bindGroup);
18097
18133
  pass.setVertexBuffer(0, this.vertexBuffer);
18098
18134
  pass.draw(this.vertexCount);
@@ -18103,7 +18139,8 @@ class SelectionVolumeRenderer {
18103
18139
  (_b2 = this.uniformBuffer) == null ? void 0 : _b2.destroy();
18104
18140
  this.vertexBuffer = null;
18105
18141
  this.uniformBuffer = null;
18106
- this.pipeline = null;
18142
+ this.frontPipeline = null;
18143
+ this.behindPipeline = null;
18107
18144
  this.bindGroup = null;
18108
18145
  }
18109
18146
  }
@@ -18189,16 +18226,13 @@ class SplatEditor {
18189
18226
  this.toolOverlay.style.display = name && !isVolumeTool ? "block" : "none";
18190
18227
  if (isVolumeTool && this.volumeRenderer) {
18191
18228
  const volType = name;
18192
- const bounds = this.getModelBounds();
18193
- const defaultSize = Math.max(bounds.size[0], bounds.size[1], bounds.size[2]) * 0.3;
18194
- const safeSize = Math.max(defaultSize, 0.5);
18229
+ const center = this.getModelCenter();
18195
18230
  if (volType === "box") {
18196
- this.boxTool.setDimensions(safeSize, safeSize, safeSize);
18197
- this.volumeRenderer.setVolume("box", bounds.center, [safeSize, safeSize, safeSize]);
18231
+ const lx = this.boxTool.lenX, ly = this.boxTool.lenY, lz = this.boxTool.lenZ;
18232
+ this.volumeRenderer.setVolume("box", center, [lx, ly, lz]);
18198
18233
  } else {
18199
- const r = safeSize / 2;
18200
- this.sphereTool.setRadius(r);
18201
- this.volumeRenderer.setVolume("sphere", bounds.center, [r, 0, 0]);
18234
+ const r = this.sphereTool.radius;
18235
+ this.volumeRenderer.setVolume("sphere", center, [r, 0, 0]);
18202
18236
  }
18203
18237
  (_b2 = (_a2 = this.callbacks).onVolumeToolActivated) == null ? void 0 : _b2.call(_a2, this.volumeRenderer.volume);
18204
18238
  } else {