three-cad-viewer 5.0.5 → 5.0.7
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/three-cad-viewer.js
CHANGED
|
@@ -84005,7 +84005,10 @@ void main() {
|
|
|
84005
84005
|
* `Uint32BufferAttribute` under this name; the pick pass reads it as an **integer**
|
|
84006
84006
|
* attribute (`gpuType = THREE.IntType`, GLSL3 `in uint`) so ids stay exact past
|
|
84007
84007
|
* 2^24. The geometry side must set `gpuType = THREE.IntType` on the attribute for
|
|
84008
|
-
* the pick shader to read it.
|
|
84008
|
+
* the pick shader to read it. Between the stages the id travels as two float
|
|
84009
|
+
* varyings (16-bit halves), deliberately NOT as a `flat uint` — see the note in
|
|
84010
|
+
* highlight.ts: a `flat` varying costs ~25x the scene's buffer bytes in graphics
|
|
84011
|
+
* memory under WebKit's ANGLE-on-Metal backend.
|
|
84009
84012
|
*/
|
|
84010
84013
|
const COMPONENT_ID_ATTRIBUTE = "componentId";
|
|
84011
84014
|
/**
|
|
@@ -84303,8 +84306,9 @@ void main() {
|
|
|
84303
84306
|
*/
|
|
84304
84307
|
const PICK_POINT_SIZE = 3;
|
|
84305
84308
|
/**
|
|
84306
|
-
* Shared GLSL3 MRT fragment shader for all pick materials (face/vertex/edge):
|
|
84307
|
-
* the
|
|
84309
|
+
* Shared GLSL3 MRT fragment shader for all pick materials (face/vertex/edge):
|
|
84310
|
+
* reassembles the id from its two interpolated halves and packs it into attachment 0
|
|
84311
|
+
* (byte order MUST match `packId()`: low byte in R)
|
|
84308
84312
|
* and writes the interpolated world position into attachment 1 (RGBA32F; `w=1` marks
|
|
84309
84313
|
* "has position"). The fragment clip chunk only `discard`s (non-ALPHA_TO_COVERAGE),
|
|
84310
84314
|
* so no `diffuseColor` symbol is required.
|
|
@@ -84312,13 +84316,15 @@ void main() {
|
|
|
84312
84316
|
const PICK_FRAGMENT_SHADER = /* glsl */ `
|
|
84313
84317
|
#include <clipping_planes_pars_fragment>
|
|
84314
84318
|
|
|
84315
|
-
|
|
84319
|
+
in float vIdLo;
|
|
84320
|
+
in float vIdHi;
|
|
84316
84321
|
in vec3 vWorldPos;
|
|
84317
84322
|
layout(location = 0) out vec4 fragId;
|
|
84318
84323
|
layout(location = 1) out vec4 fragPos;
|
|
84319
84324
|
|
|
84320
84325
|
void main() {
|
|
84321
84326
|
#include <clipping_planes_fragment>
|
|
84327
|
+
uint vId = ( uint( vIdHi + 0.5 ) << 16 ) | uint( vIdLo + 0.5 );
|
|
84322
84328
|
fragId = vec4(
|
|
84323
84329
|
float( vId & 0xFFu ) / 255.0,
|
|
84324
84330
|
float( ( vId >> 8 ) & 0xFFu ) / 255.0,
|
|
@@ -84336,19 +84342,24 @@ void main() {
|
|
|
84336
84342
|
function createFacePickMaterial(options = {}) {
|
|
84337
84343
|
// GLSL3 (WebGL2). For a (non-Raw) ShaderMaterial three.js auto-injects
|
|
84338
84344
|
// `in vec3 position;`, `uniform mat4 modelMatrix/modelViewMatrix/projectionMatrix`,
|
|
84339
|
-
// so we declare ONLY the custom integer attribute +
|
|
84340
|
-
//
|
|
84345
|
+
// so we declare ONLY the custom integer attribute + the two id-half varyings
|
|
84346
|
+
// (float, interpolated — an integer varying would have to be `flat`, which is
|
|
84347
|
+
// the ANGLE-on-Metal memory trap described in highlight.ts; all vertices of a
|
|
84348
|
+
// primitive carry the same id, so interpolation + rounding is exact). Clip
|
|
84349
|
+
// chunks use legacy `varying`/`attribute` keywords
|
|
84341
84350
|
// which three remaps via `#define` under GLSL3; the vertex chunk reads a local
|
|
84342
84351
|
// `vec4 mvPosition`, which we compute before the include.
|
|
84343
84352
|
const vertexShader = /* glsl */ `
|
|
84344
84353
|
#include <clipping_planes_pars_vertex>
|
|
84345
84354
|
|
|
84346
84355
|
in uint componentId;
|
|
84347
|
-
|
|
84356
|
+
out float vIdLo;
|
|
84357
|
+
out float vIdHi;
|
|
84348
84358
|
out vec3 vWorldPos;
|
|
84349
84359
|
|
|
84350
84360
|
void main() {
|
|
84351
|
-
|
|
84361
|
+
vIdLo = float( componentId & 0xFFFFu );
|
|
84362
|
+
vIdHi = float( componentId >> 16 );
|
|
84352
84363
|
vec4 worldPos = modelMatrix * vec4( position, 1.0 );
|
|
84353
84364
|
vWorldPos = worldPos.xyz;
|
|
84354
84365
|
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
@@ -84387,13 +84398,15 @@ void main() {
|
|
|
84387
84398
|
#include <clipping_planes_pars_vertex>
|
|
84388
84399
|
|
|
84389
84400
|
in uint componentId;
|
|
84390
|
-
|
|
84401
|
+
out float vIdLo;
|
|
84402
|
+
out float vIdHi;
|
|
84391
84403
|
out vec3 vWorldPos;
|
|
84392
84404
|
uniform float uPickSize;
|
|
84393
84405
|
uniform float uDepthBias;
|
|
84394
84406
|
|
|
84395
84407
|
void main() {
|
|
84396
|
-
|
|
84408
|
+
vIdLo = float( componentId & 0xFFFFu );
|
|
84409
|
+
vIdHi = float( componentId >> 16 );
|
|
84397
84410
|
vec4 worldPos = modelMatrix * vec4( position, 1.0 );
|
|
84398
84411
|
vWorldPos = worldPos.xyz;
|
|
84399
84412
|
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
@@ -84453,7 +84466,8 @@ void main() {
|
|
|
84453
84466
|
in vec3 instanceEnd;
|
|
84454
84467
|
in uint componentId;
|
|
84455
84468
|
|
|
84456
|
-
|
|
84469
|
+
out float vIdLo;
|
|
84470
|
+
out float vIdHi;
|
|
84457
84471
|
out vec3 vWorldPos;
|
|
84458
84472
|
|
|
84459
84473
|
void trimSegment( const in vec4 start, inout vec4 end ) {
|
|
@@ -84465,7 +84479,8 @@ void main() {
|
|
|
84465
84479
|
}
|
|
84466
84480
|
|
|
84467
84481
|
void main() {
|
|
84468
|
-
|
|
84482
|
+
vIdLo = float( componentId & 0xFFFFu );
|
|
84483
|
+
vIdHi = float( componentId >> 16 );
|
|
84469
84484
|
|
|
84470
84485
|
// World-space segment endpoints → approximate hit point along the edge.
|
|
84471
84486
|
vWorldPos = ( position.y < 0.5 )
|
|
@@ -85003,20 +85018,41 @@ void main() {
|
|
|
85003
85018
|
//
|
|
85004
85019
|
// three upgrades stock materials to GLSL ES 3.00 on WebGL2 via `#define attribute
|
|
85005
85020
|
// in` / `#define varying out|in` macros (WebGLProgram.js), so writing `attribute` /
|
|
85006
|
-
// `
|
|
85021
|
+
// `varying` here is converted automatically; `usampler2D` / `texelFetch` /
|
|
85007
85022
|
// integer attributes are then available.
|
|
85023
|
+
//
|
|
85024
|
+
// The component id crosses to the fragment stage as TWO ordinary (interpolated)
|
|
85025
|
+
// float varyings holding its 16-bit halves — NOT as a `flat uint`. A `flat`
|
|
85026
|
+
// varying is what an integer varying would require, and it is exactly what must
|
|
85027
|
+
// be avoided here: under WebKit's ANGLE-on-Metal backend, every draw whose
|
|
85028
|
+
// program has a `flat` varying makes ANGLE allocate a converted copy of the
|
|
85029
|
+
// draw's index data (>= 64 KB each, pooled, never returned to the GL on
|
|
85030
|
+
// deleteBuffer). With this varying on every visible material that was ~25x the
|
|
85031
|
+
// scene's vertex/index bytes in graphics memory (26 MB of buffers -> 812 MB;
|
|
85032
|
+
// 100 MB -> 2.3 GB) and it is charged to the page's WebContent process in the
|
|
85033
|
+
// system WebKit, which killed build123d Studio at 16 GB after a few large
|
|
85034
|
+
// shows. Without `flat` the same scene takes 63 MB / 160 MB. Measured 2026-09-17
|
|
85035
|
+
// (working-docs/leak-harness.html + probe2.html, Playwright WebKit and Safari).
|
|
85036
|
+
//
|
|
85037
|
+
// Interpolating floats is exact for the id's purpose: every vertex of a face,
|
|
85038
|
+
// every vertex of an instanced segment and a point carry the SAME id, so the
|
|
85039
|
+
// interpolated value equals it up to rounding, and `uint(x + 0.5)` recovers it.
|
|
85040
|
+
// Two 16-bit halves (both < 65536, exactly representable in float32) keep the
|
|
85041
|
+
// full 32-bit id range that `applyComponentIds` promises.
|
|
85008
85042
|
// ---------------------------------------------------------------------------
|
|
85009
85043
|
/**
|
|
85010
85044
|
* Shared state-fetch GLSL, injected into BOTH stages: the vertex stage needs it for
|
|
85011
85045
|
* widening / point size, the fragment for color. Declares the sampler + texWidth +
|
|
85012
|
-
* the
|
|
85013
|
-
* (0 for background / nothing).
|
|
85046
|
+
* the two id-half varyings and a helper returning the component's
|
|
85047
|
+
* {@link HighlightFlag} bits (0 for background / nothing).
|
|
85014
85048
|
*/
|
|
85015
85049
|
const HL_STATE_GLSL = `
|
|
85016
|
-
|
|
85050
|
+
varying float vHighlightIdLo;
|
|
85051
|
+
varying float vHighlightIdHi;
|
|
85017
85052
|
uniform highp usampler2D ${U_HIGHLIGHT_STATE};
|
|
85018
85053
|
uniform int ${U_HIGHLIGHT_TEX_WIDTH};
|
|
85019
85054
|
uint highlightState() {
|
|
85055
|
+
uint vHighlightId = (uint(vHighlightIdHi + 0.5) << 16) | uint(vHighlightIdLo + 0.5);
|
|
85020
85056
|
if (vHighlightId == 0u) return 0u;
|
|
85021
85057
|
ivec2 hlUv = ivec2(
|
|
85022
85058
|
int(vHighlightId) % ${U_HIGHLIGHT_TEX_WIDTH},
|
|
@@ -85031,8 +85067,8 @@ uint highlightState() {
|
|
|
85031
85067
|
const HL_VERTEX_HEADER = `
|
|
85032
85068
|
attribute uint ${COMPONENT_ID_ATTRIBUTE};
|
|
85033
85069
|
${HL_STATE_GLSL}`;
|
|
85034
|
-
/** Vertex main: forward the id. Injected right after `void main() {`. */
|
|
85035
|
-
const HL_VERTEX_ASSIGN = `
|
|
85070
|
+
/** Vertex main: forward the id as two 16-bit halves. Injected right after `void main() {`. */
|
|
85071
|
+
const HL_VERTEX_ASSIGN = `vHighlightIdLo = float(${COMPONENT_ID_ATTRIBUTE} & 0xFFFFu); vHighlightIdHi = float(${COMPONENT_ID_ATTRIBUTE} >> 16);`;
|
|
85036
85072
|
/** Fragment header: the shared state fetch + the two highlight colors. */
|
|
85037
85073
|
const HL_FRAGMENT_HEADER = `
|
|
85038
85074
|
${HL_STATE_GLSL}
|
|
@@ -85282,7 +85318,7 @@ uniform vec3 ${U_HIGHLIGHT_HOVER_COLOR};`;
|
|
|
85282
85318
|
this.uniforms.uHighlightSelectedColor;
|
|
85283
85319
|
shader.uniforms[U_HIGHLIGHT_HOVER_COLOR] =
|
|
85284
85320
|
this.uniforms.uHighlightHoverColor;
|
|
85285
|
-
// Common: forward the component id as
|
|
85321
|
+
// Common: forward the component id (as two interpolated float halves).
|
|
85286
85322
|
shader.vertexShader =
|
|
85287
85323
|
HL_VERTEX_HEADER +
|
|
85288
85324
|
"\n" +
|
|
@@ -88814,7 +88850,14 @@ float metalnessFactor = metalness;
|
|
|
88814
88850
|
group.name = `GridHelper-${i}`;
|
|
88815
88851
|
group.add(new GridHelper(this.size, 2 * this.ticks, this.colors[this.theme][i === 0 ? 1 : i === 1 ? 0 : 2], this.colors[this.theme][i === 0 ? 0 : i === 1 ? 2 : 1], this.theme == "dark" ? 0x7777777 : 0xbbbbbb));
|
|
88816
88852
|
let label;
|
|
88817
|
-
|
|
88853
|
+
// A grid of no size has no labels, and asking for them hangs the tab:
|
|
88854
|
+
// `niceBounds` answers [0, 0, 0] for a bounding box whose largest extent
|
|
88855
|
+
// is zero - which is what an empty model gives it - so `delta` is zero
|
|
88856
|
+
// and the loop below steps by zero, never advancing and never throwing.
|
|
88857
|
+
// Guarded here rather than in `niceBounds`, whose answer is right: there
|
|
88858
|
+
// is nothing to place ticks on.
|
|
88859
|
+
const step = this.delta / 2;
|
|
88860
|
+
for (let x = -this.size / 2; step > 0 && x <= this.size / 2; x += step) {
|
|
88818
88861
|
if (Math.abs(x) < 1e-6) {
|
|
88819
88862
|
continue;
|
|
88820
88863
|
} // skip center label
|
|
@@ -97356,7 +97399,7 @@ float metalnessFactor = metalness;
|
|
|
97356
97399
|
}
|
|
97357
97400
|
}
|
|
97358
97401
|
|
|
97359
|
-
const version = "5.0.
|
|
97402
|
+
const version = "5.0.7";
|
|
97360
97403
|
|
|
97361
97404
|
/**
|
|
97362
97405
|
* `PickedComponent` over a GPU id-pick result. Drives the shader
|
|
@@ -110826,6 +110869,11 @@ void mainImage(const in vec4 inputColor, const in vec2 uv, const in float depth,
|
|
|
110826
110869
|
deepDispose(this._rendered.camera);
|
|
110827
110870
|
deepDispose(this._rendered.controls);
|
|
110828
110871
|
deepDispose(this._rendered.treeview);
|
|
110872
|
+
// The orientation marker owns its own THREE.Scene (cones, labels, sphere,
|
|
110873
|
+
// axes), not part of the main scene above, so it needs its own dispose —
|
|
110874
|
+
// without it every clear()/render() cycle left 8 geometries and 3 programs
|
|
110875
|
+
// behind on the GL (measured 2026-09-17, working-docs/leak-harness.html).
|
|
110876
|
+
this._rendered.orientationMarker.dispose();
|
|
110829
110877
|
// clear tree view
|
|
110830
110878
|
this.display.clearCadTree();
|
|
110831
110879
|
// clear info
|
|
@@ -112532,12 +112580,21 @@ void mainImage(const in vec4 inputColor, const in vec2 uv, const in float depth,
|
|
|
112532
112580
|
this.renderer.setSize(cadWidth, height);
|
|
112533
112581
|
// Resize the id pick target to match the canvas
|
|
112534
112582
|
this.idPicker?.setSize(cadWidth, height);
|
|
112535
|
-
// Adapt display dimensions
|
|
112583
|
+
// Adapt display dimensions. `glass` and `tools` are part of the sizes:
|
|
112584
|
+
// setSizes widens the toolbar and the body by the tree only when the tree
|
|
112585
|
+
// sits beside the canvas (`tools && !glass`), and updates the tree and
|
|
112586
|
+
// info heights only outside glass mode. Leaving them out meant neither
|
|
112587
|
+
// branch could ever be taken from a resize, so a non-glass viewer got a
|
|
112588
|
+
// toolbar and a body of `cadWidth + 2` with a `treeWidth + cadWidth` row
|
|
112589
|
+
// inside them - measured as a 550px toolbar over 802px of content - and a
|
|
112590
|
+
// tree that kept its old height. `glassMode` passes both and was right.
|
|
112536
112591
|
this.display.setSizes({
|
|
112537
112592
|
treeWidth: treeWidth,
|
|
112538
112593
|
treeHeight: this.state.get("treeHeight"),
|
|
112539
112594
|
cadWidth: cadWidth,
|
|
112540
112595
|
height: height,
|
|
112596
|
+
glass: glass,
|
|
112597
|
+
tools: this.state.get("tools"),
|
|
112541
112598
|
});
|
|
112542
112599
|
// Set glass state - subscription will update UI
|
|
112543
112600
|
this.state.set("glass", glass);
|