@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.cjs +119 -85
- package/dist/3dgs-lib.cjs.map +1 -1
- package/dist/3dgs-lib.js +119 -85
- package/dist/3dgs-lib.js.map +1 -1
- package/dist/editor/SelectionVolumeRenderer.d.ts +9 -3
- package/package.json +1 -1
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 = "
|
|
17617
|
-
input.step = "
|
|
17618
|
-
input.value = this._radius
|
|
17616
|
+
input.min = "1";
|
|
17617
|
+
input.step = "1";
|
|
17618
|
+
input.value = String(this._radius);
|
|
17619
17619
|
input.style.cssText = `
|
|
17620
|
-
width:
|
|
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(
|
|
17628
|
-
input.value = v
|
|
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 =
|
|
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 = "
|
|
17706
|
-
input.step = "
|
|
17707
|
-
input.value =
|
|
17705
|
+
input.min = "1";
|
|
17706
|
+
input.step = "1";
|
|
17707
|
+
input.value = String(Math.round(initial));
|
|
17708
17708
|
input.style.cssText = `
|
|
17709
|
-
width:
|
|
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(
|
|
17717
|
-
input.value = v
|
|
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 =
|
|
17764
|
-
this.inputY.value =
|
|
17765
|
-
this.inputZ.value =
|
|
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, "
|
|
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, "
|
|
17893
|
+
__publicField(this, "frontColor", [0.4, 0.9, 1]);
|
|
17893
17894
|
this.renderer = renderer;
|
|
17894
17895
|
this.camera = camera;
|
|
17895
|
-
this.
|
|
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
|
-
|
|
17916
|
+
createPipelines() {
|
|
17916
17917
|
const device = this.renderer.device;
|
|
17917
17918
|
const shaderCode = (
|
|
17918
17919
|
/* wgsl */
|
|
17919
17920
|
`
|
|
17920
|
-
struct Uniforms {
|
|
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
|
-
|
|
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.
|
|
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:
|
|
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
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
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: "
|
|
17948
|
-
|
|
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: "
|
|
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: "
|
|
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] =
|
|
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 =
|
|
17982
|
-
const y0 =
|
|
17983
|
-
const z0 =
|
|
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] =
|
|
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
|
-
|
|
18038
|
-
|
|
18039
|
-
|
|
18056
|
+
Math.cos(a0) * ringRadius,
|
|
18057
|
+
centerY,
|
|
18058
|
+
Math.sin(a0) * ringRadius,
|
|
18040
18059
|
r,
|
|
18041
18060
|
g,
|
|
18042
18061
|
b,
|
|
18043
|
-
|
|
18044
|
-
|
|
18045
|
-
|
|
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
|
-
|
|
18066
|
-
|
|
18067
|
-
|
|
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
|
-
|
|
18072
|
-
|
|
18073
|
-
|
|
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.
|
|
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
|
|
18086
|
-
|
|
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,
|
|
18094
|
-
|
|
18095
|
-
pass.
|
|
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.
|
|
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
|
|
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.
|
|
18197
|
-
this.volumeRenderer.setVolume("box",
|
|
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 =
|
|
18200
|
-
this.
|
|
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 {
|