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