@thatopen/components 3.4.2 → 3.4.4
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/index.cjs +3723 -853
- package/dist/index.d.ts +500 -90
- package/dist/index.min.cjs +2 -2
- package/dist/index.min.mjs +2 -2
- package/dist/index.mjs +3725 -855
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1417,6 +1417,28 @@ export declare class Clipper extends Component implements Createable, Disposable
|
|
|
1417
1417
|
* to the arrow gizmo as you zoom in/out. Default is true.
|
|
1418
1418
|
*/
|
|
1419
1419
|
autoScalePlanes: boolean;
|
|
1420
|
+
/**
|
|
1421
|
+
* When true, planes created by this Clipper are flagged
|
|
1422
|
+
* `isLocal: true` so they stay out of `renderer.three.clippingPlanes`
|
|
1423
|
+
* (the WebGL-level global list). All clipping happens via per-
|
|
1424
|
+
* material `material.clippingPlanes`, which `Clipper.updateMaterialsAndPlanes`
|
|
1425
|
+
* already populates from the renderer's component-side array. The
|
|
1426
|
+
* global list still works for non-Clipper code that pushes its own
|
|
1427
|
+
* planes via `setPlane(active, plane, /*isLocal*\/ false)`.
|
|
1428
|
+
*
|
|
1429
|
+
* Why this matters: with planes only on materials (not global),
|
|
1430
|
+
* consumers like {@link ClipStyler} can give their section fill /
|
|
1431
|
+
* line meshes a *different* `material.clippingPlanes` list — one
|
|
1432
|
+
* that excludes the section's own plane — so the cut geometry
|
|
1433
|
+
* sits exactly on the cut without being discarded by it. The old
|
|
1434
|
+
* 1cm world-space offset workaround is no longer needed and the
|
|
1435
|
+
* fill stays aligned at every camera angle (issue #733).
|
|
1436
|
+
*
|
|
1437
|
+
* Default `false` to preserve existing behavior. Set this once
|
|
1438
|
+
* before creating planes; toggling at runtime won't reclassify
|
|
1439
|
+
* planes already on the renderer.
|
|
1440
|
+
*/
|
|
1441
|
+
localClippingPlanes: boolean;
|
|
1420
1442
|
/**
|
|
1421
1443
|
* The type of clipping plane to be created.
|
|
1422
1444
|
* Default is {@link SimplePlane}.
|
|
@@ -1434,7 +1456,7 @@ export declare class Clipper extends Component implements Createable, Disposable
|
|
|
1434
1456
|
private _size;
|
|
1435
1457
|
private _enabled;
|
|
1436
1458
|
private _visible;
|
|
1437
|
-
readonly onStateChanged: Event_2<("
|
|
1459
|
+
readonly onStateChanged: Event_2<("enabled" | "size" | "visibility" | "material")[]>;
|
|
1438
1460
|
/** {@link Component.enabled} */
|
|
1439
1461
|
get enabled(): boolean;
|
|
1440
1462
|
/** {@link Component.enabled} */
|
|
@@ -1453,6 +1475,21 @@ export declare class Clipper extends Component implements Createable, Disposable
|
|
|
1453
1475
|
set size(size: number);
|
|
1454
1476
|
constructor(components: Components);
|
|
1455
1477
|
private setEvents;
|
|
1478
|
+
private subscribeToFragmentMaterials;
|
|
1479
|
+
/**
|
|
1480
|
+
* Assign `material.clippingPlanes` to the renderer's component-
|
|
1481
|
+
* side `clippingPlanes` array — the only place local planes live
|
|
1482
|
+
* once `localClippingPlanes = true`. In legacy global-clipping
|
|
1483
|
+
* mode this is a no-op: the renderer's global list handles
|
|
1484
|
+
* fragments clipping and assigning per-material would just be
|
|
1485
|
+
* redundant.
|
|
1486
|
+
*
|
|
1487
|
+
* Applied to every fragment material, including LOD line
|
|
1488
|
+
* materials — they need the planes too, otherwise far-LOD line
|
|
1489
|
+
* geometry stays visible past the cut while the shell geometry
|
|
1490
|
+
* clips correctly.
|
|
1491
|
+
*/
|
|
1492
|
+
private applyClippingToFragmentMaterial;
|
|
1456
1493
|
/** {@link Disposable.dispose} */
|
|
1457
1494
|
dispose(): void;
|
|
1458
1495
|
/** {@link Createable.create} */
|
|
@@ -1598,7 +1635,7 @@ export declare class Components implements Disposable_2 {
|
|
|
1598
1635
|
* Default value is false.
|
|
1599
1636
|
*/
|
|
1600
1637
|
enabled: boolean;
|
|
1601
|
-
private
|
|
1638
|
+
private _timer;
|
|
1602
1639
|
/**
|
|
1603
1640
|
* Event that triggers the Components instance is initialized.
|
|
1604
1641
|
*
|
|
@@ -2074,7 +2111,7 @@ declare class DistanceRenderer {
|
|
|
2074
2111
|
/**
|
|
2075
2112
|
* The scene where the distance is computed.
|
|
2076
2113
|
*/
|
|
2077
|
-
scene: THREE.Scene
|
|
2114
|
+
scene: THREE.Scene<THREE.Object3DEventMap>;
|
|
2078
2115
|
/**
|
|
2079
2116
|
* The camera used to compute the distance.
|
|
2080
2117
|
*/
|
|
@@ -2868,125 +2905,303 @@ export declare interface ExternalDocumentReference extends DocumentReference {
|
|
|
2868
2905
|
}
|
|
2869
2906
|
|
|
2870
2907
|
/**
|
|
2871
|
-
*
|
|
2908
|
+
* GPU-readback picker that identifies what's under a screen position
|
|
2909
|
+
* without going through the worker raycast. Two granularities, same
|
|
2910
|
+
* render pass:
|
|
2911
|
+
*
|
|
2912
|
+
* - {@link getModelAt} returns the model id under the cursor.
|
|
2913
|
+
* - {@link getItemAt} returns the item itself (`modelId` + `localId`).
|
|
2914
|
+
*
|
|
2915
|
+
* The fragments tile geometry already carries a per-vertex `id`
|
|
2916
|
+
* attribute (the internal item id). We render the BIM scene to an
|
|
2917
|
+
* offscreen target with a shader that packs `(modelByte, itemId)` into
|
|
2918
|
+
* RGBA, then `readPixels` at the cursor and decode. One render plus
|
|
2919
|
+
* one 4-byte readback per call. No worker round-trip for the model
|
|
2920
|
+
* lookup; the first time we resolve a given `itemId` to a `localId`
|
|
2921
|
+
* we ask the worker, and afterwards that lookup is cached.
|
|
2922
|
+
*
|
|
2923
|
+
* Encoding (one pixel):
|
|
2924
|
+
* R = modelByte (1..254, 0 = void / unwritten)
|
|
2925
|
+
* G = (itemId >> 16) & 0xff
|
|
2926
|
+
* B = (itemId >> 8) & 0xff
|
|
2927
|
+
* A = (itemId) & 0xff
|
|
2928
|
+
*
|
|
2929
|
+
* `modelByte` is assigned per-pick from a `byteToModelId` map; the
|
|
2930
|
+
* picker re-allocates bytes each call so the assignment is stable for
|
|
2931
|
+
* the duration of the pick but doesn't grow over the session.
|
|
2872
2932
|
*/
|
|
2873
2933
|
export declare class FastModelPicker implements Disposable_2 {
|
|
2874
2934
|
/** {@link Component.enabled} */
|
|
2875
2935
|
enabled: boolean;
|
|
2876
|
-
/**
|
|
2936
|
+
/** Components instance this picker belongs to. */
|
|
2877
2937
|
components: Components;
|
|
2878
2938
|
/** {@link Disposable.onDisposed} */
|
|
2879
2939
|
readonly onDisposed: Event_2<unknown>;
|
|
2880
|
-
/**
|
|
2940
|
+
/** Position helper bound to the world's canvas. */
|
|
2881
2941
|
readonly mouse: Mouse;
|
|
2882
|
-
/**
|
|
2883
|
-
* A reference to the world instance to which this FastModelPicker belongs.
|
|
2884
|
-
* This is used to access the camera and scene.
|
|
2885
|
-
*/
|
|
2942
|
+
/** World this picker renders against. */
|
|
2886
2943
|
world: World;
|
|
2887
2944
|
/**
|
|
2888
|
-
*
|
|
2945
|
+
* When `true`, mirrors the id render to a debug canvas pinned in the
|
|
2946
|
+
* top-right corner. Each model shows up as a near-uniform red band
|
|
2947
|
+
* (the model byte) modulated by varying greens / blues from the
|
|
2948
|
+
* per-item id encoding.
|
|
2889
2949
|
*/
|
|
2890
2950
|
debugMode: boolean;
|
|
2891
2951
|
/**
|
|
2892
|
-
*
|
|
2893
|
-
*
|
|
2952
|
+
* Maximum models the picker can disambiguate in a single pick. Capped
|
|
2953
|
+
* by the 8-bit `modelByte`. In practice we never approach this.
|
|
2894
2954
|
*/
|
|
2895
|
-
|
|
2955
|
+
static readonly MAX_MODELS = 254;
|
|
2956
|
+
private _renderTarget?;
|
|
2957
|
+
private _renderTargetSize;
|
|
2958
|
+
private _debugCanvas?;
|
|
2959
|
+
private _debugContainer?;
|
|
2896
2960
|
/**
|
|
2897
|
-
*
|
|
2961
|
+
* Single shared shader for the id pass. The same program runs across
|
|
2962
|
+
* every model; we flip the `modelByte` uniform between per-model
|
|
2963
|
+
* render passes inside one pick to disambiguate which model owns a
|
|
2964
|
+
* pixel.
|
|
2898
2965
|
*/
|
|
2899
|
-
private
|
|
2966
|
+
private _idMaterial;
|
|
2900
2967
|
/**
|
|
2901
|
-
*
|
|
2968
|
+
* Depth-encoding shader used by {@link getPointAt}. Written via
|
|
2969
|
+
* `scene.overrideMaterial` for one render of the BIM scene, packs
|
|
2970
|
+
* `gl_FragCoord.z` into the four bytes of the color attachment using
|
|
2971
|
+
* three's `packing` chunk. The packed value is robust to round-trip
|
|
2972
|
+
* through an `UNSIGNED_BYTE` target.
|
|
2902
2973
|
*/
|
|
2903
|
-
private
|
|
2974
|
+
private _depthMaterial;
|
|
2904
2975
|
/**
|
|
2905
|
-
*
|
|
2976
|
+
* World-space normal-encoding shader used by {@link getNormalAt}.
|
|
2977
|
+
* Writes `(normal * 0.5 + 0.5)` into RGB, alpha = 1. Decode side maps
|
|
2978
|
+
* `(rgb * 2 - 1)` and renormalizes. Naive packing wastes alpha and
|
|
2979
|
+
* gives ~1° precision per axis, which is plenty for surface
|
|
2980
|
+
* alignment, orbit-around-clicked-point, and snapping. Octahedral
|
|
2981
|
+
* packing would buy us another bit per axis but isn't worth the
|
|
2982
|
+
* complexity until a consumer actually needs sub-degree accuracy.
|
|
2906
2983
|
*/
|
|
2907
|
-
private
|
|
2984
|
+
private _normalMaterial;
|
|
2908
2985
|
/**
|
|
2909
|
-
*
|
|
2986
|
+
* Cached original materials for the swap-render-restore pass.
|
|
2987
|
+
* Populated in {@link applyIdMaterial}, drained in
|
|
2988
|
+
* {@link restoreOriginalMaterials} after the render.
|
|
2910
2989
|
*/
|
|
2911
|
-
private
|
|
2990
|
+
private _originalMaterials;
|
|
2912
2991
|
/**
|
|
2913
|
-
*
|
|
2992
|
+
* LOD line meshes don't carry the per-vertex `id` attribute and would
|
|
2993
|
+
* write whatever color their normal shader produces into the id
|
|
2994
|
+
* buffer, faking hits. Hidden for the duration of the id render and
|
|
2995
|
+
* restored after.
|
|
2914
2996
|
*/
|
|
2915
|
-
private
|
|
2916
|
-
/**
|
|
2917
|
-
* Material used for color-coding models.
|
|
2918
|
-
*/
|
|
2919
|
-
private colorMaterials;
|
|
2920
|
-
/**
|
|
2921
|
-
* Original materials cache (to restore after picking).
|
|
2922
|
-
*/
|
|
2923
|
-
private originalMaterials;
|
|
2924
|
-
private originalLodColors;
|
|
2925
|
-
/**
|
|
2926
|
-
* Whether colors need to be reassigned (when models change).
|
|
2927
|
-
*/
|
|
2928
|
-
private colorsNeedUpdate;
|
|
2997
|
+
private _hiddenLods;
|
|
2929
2998
|
constructor(components: Components, world: World);
|
|
2930
2999
|
/**
|
|
2931
|
-
*
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
*
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
* Sets up the debug canvas for visualization.
|
|
2940
|
-
*/
|
|
2941
|
-
private setupDebugCanvas;
|
|
2942
|
-
/**
|
|
2943
|
-
* Generates a deterministic color for a model based on its ID.
|
|
2944
|
-
* This ensures the same model always gets the same color.
|
|
2945
|
-
*/
|
|
2946
|
-
private generateColorForModel;
|
|
2947
|
-
/**
|
|
2948
|
-
* Converts a color to a numeric ID.
|
|
2949
|
-
*/
|
|
2950
|
-
private colorToId;
|
|
2951
|
-
/**
|
|
2952
|
-
* Assigns unique colors to all fragment models.
|
|
2953
|
-
* Colors are deterministic based on model ID, so the same model always gets the same color.
|
|
2954
|
-
*/
|
|
2955
|
-
private assignColors;
|
|
2956
|
-
/**
|
|
2957
|
-
* Applies color materials to fragment models.
|
|
3000
|
+
* Returns the model id under the given screen position, or `null` if
|
|
3001
|
+
* the cursor is over empty space.
|
|
3002
|
+
*
|
|
3003
|
+
* Cheaper than {@link getItemAt} because we don't resolve the
|
|
3004
|
+
* `localId`; we just read the model byte from the same render.
|
|
3005
|
+
*
|
|
3006
|
+
* @param position - Normalized device coords. Defaults to the
|
|
3007
|
+
* picker's last known mouse position.
|
|
2958
3008
|
*/
|
|
2959
|
-
|
|
3009
|
+
getModelAt(position?: THREE.Vector2): Promise<string | null>;
|
|
2960
3010
|
/**
|
|
2961
|
-
*
|
|
3011
|
+
* Returns `{ modelId, localId }` for the item under the given screen
|
|
3012
|
+
* position, or `null` if the cursor is over empty space.
|
|
3013
|
+
*
|
|
3014
|
+
* Pure main-thread resolution: fragments now stores the user-facing
|
|
3015
|
+
* `localId` directly in each tile's per-vertex `id` attribute, so
|
|
3016
|
+
* the encoded RGBA pixel decodes straight to the localId. No worker
|
|
3017
|
+
* round-trip, no cache.
|
|
3018
|
+
*
|
|
3019
|
+
* @param position - Normalized device coords. Defaults to the
|
|
3020
|
+
* picker's last known mouse position.
|
|
2962
3021
|
*/
|
|
2963
|
-
|
|
3022
|
+
getItemAt(position?: THREE.Vector2): Promise<{
|
|
3023
|
+
modelId: string;
|
|
3024
|
+
localId: number;
|
|
3025
|
+
itemId: number;
|
|
3026
|
+
} | null>;
|
|
2964
3027
|
/**
|
|
2965
|
-
*
|
|
3028
|
+
* Returns the world-space point under the given screen position, or
|
|
3029
|
+
* `null` if the cursor is over empty space.
|
|
3030
|
+
*
|
|
3031
|
+
* Renders the BIM scene with a depth-encoding override material that
|
|
3032
|
+
* packs `gl_FragCoord.z` into the color buffer, reads four bytes at
|
|
3033
|
+
* the cursor pixel, and unprojects through the camera matrices to a
|
|
3034
|
+
* world point. One render pass, one 4-byte readback, no worker
|
|
3035
|
+
* round-trip. Useful for things like "set camera orbit center to
|
|
3036
|
+
* what the user just clicked on".
|
|
3037
|
+
*
|
|
3038
|
+
* Cheaper than {@link getItemAt} because we don't differentiate
|
|
3039
|
+
* models — one render covers the whole BIM scene at once. We don't
|
|
3040
|
+
* resolve any item id either.
|
|
3041
|
+
*
|
|
3042
|
+
* @param position - Normalized device coords. Defaults to the
|
|
3043
|
+
* picker's last known mouse position.
|
|
2966
3044
|
*/
|
|
2967
|
-
|
|
3045
|
+
getPointAt(position?: THREE.Vector2): Promise<THREE.Vector3 | null>;
|
|
2968
3046
|
/**
|
|
2969
|
-
*
|
|
3047
|
+
* Returns the world-space surface normal under the cursor, or `null`
|
|
3048
|
+
* if the cursor is over empty space.
|
|
3049
|
+
*
|
|
3050
|
+
* Mirrors {@link getPointAt}'s structure: one `scene.overrideMaterial`
|
|
3051
|
+
* render with the normal-encoding shader, one 4-byte readback,
|
|
3052
|
+
* decode and renormalize.
|
|
2970
3053
|
*/
|
|
2971
|
-
|
|
3054
|
+
getNormalAt(position?: THREE.Vector2): Promise<THREE.Vector3 | null>;
|
|
2972
3055
|
/**
|
|
2973
|
-
*
|
|
3056
|
+
* One-shot pick that produces the full result shape consumers need:
|
|
3057
|
+
* `{ modelId, localId, point, normal, distance }`. Routes through the
|
|
3058
|
+
* three GPU passes (id, depth, normal) and composes the output. No
|
|
3059
|
+
* worker round-trip.
|
|
2974
3060
|
*
|
|
2975
|
-
*
|
|
2976
|
-
*
|
|
3061
|
+
* Returns `null` if the cursor is over empty space, the id pass
|
|
3062
|
+
* decodes to the void sentinel, or the depth round-trip yields the
|
|
3063
|
+
* far plane.
|
|
2977
3064
|
*/
|
|
2978
|
-
|
|
3065
|
+
getFullPick(position?: THREE.Vector2): Promise<{
|
|
3066
|
+
modelId: string;
|
|
3067
|
+
localId: number;
|
|
3068
|
+
/**
|
|
3069
|
+
* Internal item index (FlatBuffer `sample.item()`). Exposed so
|
|
3070
|
+
* SnapResolver and other internal consumers can hit fragments'
|
|
3071
|
+
* itemId-keyed fast paths (`boxes.sampleOf`) without paying a
|
|
3072
|
+
* second worker round-trip to translate back from localId.
|
|
3073
|
+
*/
|
|
3074
|
+
itemId: number;
|
|
3075
|
+
point: THREE.Vector3;
|
|
3076
|
+
normal: THREE.Vector3 | null;
|
|
3077
|
+
distance: number;
|
|
3078
|
+
} | null>;
|
|
2979
3079
|
/**
|
|
2980
|
-
*
|
|
2981
|
-
*
|
|
3080
|
+
* Toggle the debug overlay. When enabled the picker mirrors its id
|
|
3081
|
+
* render to a small canvas pinned in the top-right corner so you can
|
|
3082
|
+
* see what the readback sees.
|
|
2982
3083
|
*/
|
|
2983
3084
|
setDebugMode(enabled: boolean): void;
|
|
2984
|
-
/**
|
|
2985
|
-
* Removes the debug canvas.
|
|
2986
|
-
*/
|
|
2987
|
-
private removeDebugCanvas;
|
|
2988
3085
|
/** {@link Disposable.dispose} */
|
|
2989
3086
|
dispose(): void;
|
|
3087
|
+
/**
|
|
3088
|
+
* Runs the id renders and returns the raw decoded
|
|
3089
|
+
* `(modelId, itemId)` for the cursor pixel. Two render passes:
|
|
3090
|
+
*
|
|
3091
|
+
* - Pass 1 (`_renderTarget`): writes the model byte into R via
|
|
3092
|
+
* the `_idMaterial`. Used solely to disambiguate which model
|
|
3093
|
+
* owns the picked pixel.
|
|
3094
|
+
* - Pass 2 (`_localIdRenderTarget`): writes the full 32-bit
|
|
3095
|
+
* localId across all four bytes via the same `_idMaterial`
|
|
3096
|
+
* with `mode = 1`.
|
|
3097
|
+
*
|
|
3098
|
+
* Two single-attachment targets instead of MRT keeps the code
|
|
3099
|
+
* portable and the diff small. Both passes use the same scene,
|
|
3100
|
+
* camera and visibility toggling so depth tests resolve to the
|
|
3101
|
+
* same front-most fragment per pixel.
|
|
3102
|
+
*
|
|
3103
|
+
* Both public entry points lean on this.
|
|
3104
|
+
*/
|
|
3105
|
+
private runIdPass;
|
|
3106
|
+
/**
|
|
3107
|
+
* Walks every fragments model. For each shell mesh that carries the
|
|
3108
|
+
* per-vertex `id` attribute, stashes the original material and swaps
|
|
3109
|
+
* in the shared id-encoding shader. Hides LOD line meshes (which
|
|
3110
|
+
* lack `id`) so they don't pollute the id buffer. Returns the
|
|
3111
|
+
* temporary `byte → modelId` map the render pass uses to
|
|
3112
|
+
* disambiguate models.
|
|
3113
|
+
*/
|
|
3114
|
+
private applyIdMaterial;
|
|
3115
|
+
/**
|
|
3116
|
+
* Renders the world scene to the id target one model at a time,
|
|
3117
|
+
* flipping the `modelByte` uniform between renders. The depth buffer
|
|
3118
|
+
* is shared across the per-model passes so the front-most item still
|
|
3119
|
+
* wins each pixel regardless of which model it belongs to.
|
|
3120
|
+
*
|
|
3121
|
+
* Non-BIM meshes in the world scene (the user's own helpers, ground
|
|
3122
|
+
* planes, hover proxies, anything else) are hidden for the duration
|
|
3123
|
+
* of the render. Without this, their normal materials write whatever
|
|
3124
|
+
* colour they happen to produce into the id target, which decodes as
|
|
3125
|
+
* a bogus `(modelByte, itemId)` pair when the cursor lands on one.
|
|
3126
|
+
*/
|
|
3127
|
+
/**
|
|
3128
|
+
* Single id render. Iterates models in byte order, flipping the
|
|
3129
|
+
* `modelByte` uniform between renders so each model's pixels carry
|
|
3130
|
+
* its assigned byte in R while the lower 3 bytes of GBA carry
|
|
3131
|
+
* `itemId + 1`. Depth buffer shared across the per-model passes so
|
|
3132
|
+
* the front-most item still wins each pixel regardless of which
|
|
3133
|
+
* model it belongs to.
|
|
3134
|
+
*/
|
|
3135
|
+
private renderIdPass;
|
|
3136
|
+
/**
|
|
3137
|
+
* Renders the BIM scene model-by-model into `target` with `material`,
|
|
3138
|
+
* scissor-clipped to a small box around the cursor. Iterates models
|
|
3139
|
+
* in byte order so depth tests resolve to the same front-most
|
|
3140
|
+
* fragment per pixel. Per-model loop sets `material.uniforms.modelByte`
|
|
3141
|
+
* before each render so the picked pixel carries the model byte.
|
|
3142
|
+
*/
|
|
3143
|
+
private renderPickPass;
|
|
3144
|
+
/**
|
|
3145
|
+
* Renders the picker's color target with the BIM tile shells using
|
|
3146
|
+
* the given override-style material, swapped in **per-mesh** rather
|
|
3147
|
+
* than via `scene.overrideMaterial`.
|
|
3148
|
+
*
|
|
3149
|
+
* Why per-mesh swap and not `scene.overrideMaterial`: fragments runs
|
|
3150
|
+
* its own LOD/visibility logic on tile shells (`mesh.visible`
|
|
3151
|
+
* toggled internally based on current LOD stage and frustum). At
|
|
3152
|
+
* the moment we render, most tile shells are flagged invisible —
|
|
3153
|
+
* `overrideMaterial` then renders nothing and we read back a
|
|
3154
|
+
* cleared pixel. Per-mesh swap mirrors what {@link renderIdPass}
|
|
3155
|
+
* does; we also force each shell visible for the duration of the
|
|
3156
|
+
* render so fragments' culling decisions don't blank our output.
|
|
3157
|
+
*
|
|
3158
|
+
* Honours the renderer's clipping planes so picked depth/normal
|
|
3159
|
+
* match what's actually rendered on screen.
|
|
3160
|
+
*/
|
|
3161
|
+
private renderWithTileMaterial;
|
|
3162
|
+
private renderDepthPass;
|
|
3163
|
+
private renderNormalPass;
|
|
3164
|
+
private restoreOriginalMaterials;
|
|
3165
|
+
private readPixelAt;
|
|
3166
|
+
/**
|
|
3167
|
+
* Single id shader, single render pass. Reads:
|
|
3168
|
+
* - `id`: per-vertex `vec4` — the four bytes of `itemId + 1`
|
|
3169
|
+
* (big-endian) supplied as a non-normalised `Uint8Array`
|
|
3170
|
+
* attribute by fragments. Each component is 0–255 as a float.
|
|
3171
|
+
* - `modelByte` uniform — the byte assigned to the currently-
|
|
3172
|
+
* rendered model.
|
|
3173
|
+
*
|
|
3174
|
+
* Output packs `(modelByte, idMid, idLo1, idLo0)` into one RGBA8
|
|
3175
|
+
* pixel: model byte in R, the lower three bytes of `itemId + 1` in
|
|
3176
|
+
* GBA. Capping the encoded id at 24 bits is fine because `itemId`
|
|
3177
|
+
* is the FlatBuffer item index — bounded by item count per model
|
|
3178
|
+
* (16M is plenty for any practical BIM model). The high byte of
|
|
3179
|
+
* the vertex attribute (`vId.x`) is therefore always 0 and we
|
|
3180
|
+
* discard it; that frees R for the model byte. One render → one
|
|
3181
|
+
* readback per pick (the previous two-target layout cost two
|
|
3182
|
+
* sync-stalling readPixels calls).
|
|
3183
|
+
*/
|
|
3184
|
+
private buildIdMaterial;
|
|
3185
|
+
/**
|
|
3186
|
+
* Builds the depth-encoding override material used by
|
|
3187
|
+
* {@link renderDepthPass}. Includes three's `packing` chunk to reuse
|
|
3188
|
+
* the standard `packDepthToRGBA` helper, which is robust to the
|
|
3189
|
+
* round-trip through an `UNSIGNED_BYTE` color attachment (the chunk
|
|
3190
|
+
* pre-multiplies by `256/255` so `depth = 1.0` decodes back exactly
|
|
3191
|
+
* to `1.0`). Decode side mirrors this with the same scaling factors;
|
|
3192
|
+
* see {@link unpackDepthFromRGBA} below.
|
|
3193
|
+
*/
|
|
3194
|
+
private buildDepthMaterial;
|
|
3195
|
+
/**
|
|
3196
|
+
* World-space normal in RGB. Handles backfaces by flipping the
|
|
3197
|
+
* encoded normal so consumers always get the surface they're looking
|
|
3198
|
+
* at. Decode side: `(rgb * 2 - 1)` → renormalize.
|
|
3199
|
+
*/
|
|
3200
|
+
private buildNormalMaterial;
|
|
3201
|
+
private setupRenderTarget;
|
|
3202
|
+
private setupDebugCanvas;
|
|
3203
|
+
private removeDebugCanvas;
|
|
3204
|
+
private updateDebugCanvas;
|
|
2990
3205
|
}
|
|
2991
3206
|
|
|
2992
3207
|
/**
|
|
@@ -5155,13 +5370,6 @@ export declare class SimpleRaycaster implements Disposable_2 {
|
|
|
5155
5370
|
* This is used to access the camera and meshes.
|
|
5156
5371
|
*/
|
|
5157
5372
|
world: World;
|
|
5158
|
-
/**
|
|
5159
|
-
* Whether to use fast model picking to optimize raycasting.
|
|
5160
|
-
* When enabled, the raycaster will first use FastModelPicker to identify
|
|
5161
|
-
* which model is under the mouse, then only raycast that specific model.
|
|
5162
|
-
* This can significantly improve performance when there are many models.
|
|
5163
|
-
*/
|
|
5164
|
-
useFastModelPicking: boolean;
|
|
5165
5373
|
constructor(components: Components, world: World);
|
|
5166
5374
|
/** {@link Disposable.dispose} */
|
|
5167
5375
|
dispose(): void;
|
|
@@ -5191,7 +5399,7 @@ export declare class SimpleRaycaster implements Disposable_2 {
|
|
|
5191
5399
|
* @param items - The meshes to query. If not provided, it will query all the meshes stored in {@link World.meshes}.
|
|
5192
5400
|
* @returns The first intersection found or `null` if no intersection was found.
|
|
5193
5401
|
*/
|
|
5194
|
-
castRayFromVector(origin: THREE.Vector3, direction: THREE.Vector3, items?: THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material | THREE.Material[], THREE.Object3DEventMap>[]): THREE.Intersection<THREE.Object3D<THREE.Object3DEventMap>> | null;
|
|
5402
|
+
castRayFromVector(origin: THREE.Vector3, direction: THREE.Vector3, items?: THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material<THREE.MaterialEventMap> | THREE.Material<THREE.MaterialEventMap>[], THREE.Object3DEventMap>[]): THREE.Intersection<THREE.Object3D<THREE.Object3DEventMap>> | null;
|
|
5195
5403
|
private intersect;
|
|
5196
5404
|
private filterClippingPlanes;
|
|
5197
5405
|
}
|
|
@@ -5226,6 +5434,48 @@ export declare class SimpleRenderer extends BaseRenderer {
|
|
|
5226
5434
|
protected _resizeObserver: ResizeObserver | null;
|
|
5227
5435
|
protected onContainerUpdated: Event_2<unknown>;
|
|
5228
5436
|
private _resizing;
|
|
5437
|
+
private _logo;
|
|
5438
|
+
private _showLogo;
|
|
5439
|
+
/**
|
|
5440
|
+
* Whether the That Open Company logo is shown as a small overlay in the
|
|
5441
|
+
* bottom-left corner of the renderer container. Defaults to `true`.
|
|
5442
|
+
*
|
|
5443
|
+
* The logo is how people discover that the libraries powering this app
|
|
5444
|
+
* come from That Open Company, the team that keeps
|
|
5445
|
+
* `@thatopen/components`, `@thatopen/fragments`, and the rest of the stack
|
|
5446
|
+
* free and open source. If the logo fits your design, please consider
|
|
5447
|
+
* leaving it on; every visible mark helps us reach more developers and
|
|
5448
|
+
* keep investing in the libraries you're building on. Thank you.
|
|
5449
|
+
*
|
|
5450
|
+
* If your app needs a clean viewport (full-bleed print view, white-label
|
|
5451
|
+
* embed, customer-branded surface), set it to `false`:
|
|
5452
|
+
* ```ts
|
|
5453
|
+
* world.renderer.showLogo = false;
|
|
5454
|
+
* ```
|
|
5455
|
+
*/
|
|
5456
|
+
get showLogo(): boolean;
|
|
5457
|
+
set showLogo(value: boolean);
|
|
5458
|
+
/**
|
|
5459
|
+
* The DOM element rendering the That Open Company wordmark, or `null`
|
|
5460
|
+
* before the renderer is set up. Mutate its `style` to restyle or move
|
|
5461
|
+
* the overlay without forking the source. Common adjustments:
|
|
5462
|
+
*
|
|
5463
|
+
* ```ts
|
|
5464
|
+
* const logo = world.renderer.logo;
|
|
5465
|
+
* if (logo) {
|
|
5466
|
+
* logo.style.left = "auto";
|
|
5467
|
+
* logo.style.right = "0.75rem"; // move to bottom-right
|
|
5468
|
+
* logo.style.bottom = "auto";
|
|
5469
|
+
* logo.style.top = "0.75rem"; // or to the top edge
|
|
5470
|
+
* }
|
|
5471
|
+
* ```
|
|
5472
|
+
*
|
|
5473
|
+
* The element also carries a `data-thatopen-logo` attribute, so app-wide
|
|
5474
|
+
* CSS can target it (`[data-thatopen-logo] { ... }`). External rules
|
|
5475
|
+
* need `!important` (or higher specificity) to win against the inline
|
|
5476
|
+
* defaults.
|
|
5477
|
+
*/
|
|
5478
|
+
get logo(): HTMLElement | null;
|
|
5229
5479
|
/**
|
|
5230
5480
|
* Constructor for the SimpleRenderer class.
|
|
5231
5481
|
*
|
|
@@ -5252,6 +5502,7 @@ export declare class SimpleRenderer extends BaseRenderer {
|
|
|
5252
5502
|
setupEvents(active: boolean): void;
|
|
5253
5503
|
private resizeEvent;
|
|
5254
5504
|
private setupRenderer;
|
|
5505
|
+
private setupLogo;
|
|
5255
5506
|
private onContextLost;
|
|
5256
5507
|
private onContextBack;
|
|
5257
5508
|
}
|
|
@@ -5327,7 +5578,7 @@ export declare class SimpleWorld<T extends BaseScene = BaseScene, U extends Base
|
|
|
5327
5578
|
/**
|
|
5328
5579
|
* All the loaded [meshes](https://threejs.org/docs/#api/en/objects/Mesh). These meshes will be taken into account in operations like raycasting.
|
|
5329
5580
|
*/
|
|
5330
|
-
readonly meshes: Set<THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material | THREE.Material[], THREE.Object3DEventMap>>;
|
|
5581
|
+
readonly meshes: Set<THREE.Mesh<THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>, THREE.Material<THREE.MaterialEventMap> | THREE.Material<THREE.MaterialEventMap>[], THREE.Object3DEventMap>>;
|
|
5331
5582
|
/** {@link Updateable.onAfterUpdate} */
|
|
5332
5583
|
readonly onAfterUpdate: Event_2<unknown>;
|
|
5333
5584
|
/** {@link Updateable.onBeforeUpdate} */
|
|
@@ -5470,6 +5721,146 @@ declare interface SlopeAnnotationSystem {
|
|
|
5470
5721
|
/** How the slope value is displayed in the text label. */
|
|
5471
5722
|
export declare type SlopeFormat = "percentage" | "ratio" | "degrees";
|
|
5472
5723
|
|
|
5724
|
+
/**
|
|
5725
|
+
* Snap classes the resolver supports. Mirrors fragments' `SnappingClass`.
|
|
5726
|
+
*/
|
|
5727
|
+
export declare enum SnapClass {
|
|
5728
|
+
POINT = 0,
|
|
5729
|
+
LINE = 1,
|
|
5730
|
+
FACE = 2
|
|
5731
|
+
}
|
|
5732
|
+
|
|
5733
|
+
/**
|
|
5734
|
+
* Main-thread snap resolver: takes a world-space pick point + the
|
|
5735
|
+
* picked item, returns the closest face / line / point of that item
|
|
5736
|
+
* for any requested snap classes. The heavy work (fetching the item's
|
|
5737
|
+
* shell geometry through the fragments edit API and composing
|
|
5738
|
+
* world-space polygons) runs once per item; subsequent calls for the
|
|
5739
|
+
* same item are pure CPU geometry against the LRU-bounded cache.
|
|
5740
|
+
* Call {@link invalidate} when an item changes (e.g. via the
|
|
5741
|
+
* fragments edit API) so the cached snap data gets refreshed on the
|
|
5742
|
+
* next request.
|
|
5743
|
+
*/
|
|
5744
|
+
export declare class SnapResolver implements Disposable_2 {
|
|
5745
|
+
/** {@link Disposable.onDisposed} */
|
|
5746
|
+
readonly onDisposed: Event_2<unknown>;
|
|
5747
|
+
/**
|
|
5748
|
+
* Maximum world-space distance for a snap candidate to be
|
|
5749
|
+
* considered valid. Vertices, edges or face planes beyond this
|
|
5750
|
+
* range are rejected. Set this in the same units as your model
|
|
5751
|
+
* (typical BIM scenes are metres, so the default of 1 means
|
|
5752
|
+
* "snap only when within 1 m of the cursor"). Tools that want a
|
|
5753
|
+
* different feel can override per-instance.
|
|
5754
|
+
*/
|
|
5755
|
+
maxDistance: number;
|
|
5756
|
+
/**
|
|
5757
|
+
* Maximum number of items to keep in the snap cache. Beyond this,
|
|
5758
|
+
* the least-recently-used item is dropped on the next insertion.
|
|
5759
|
+
* Each cached item is on the order of a few KB (per-shell faces +
|
|
5760
|
+
* deduped edges + deduped vertices), so the default of 1000 caps
|
|
5761
|
+
* memory at a few MB even on huge models. Bump it for workflows
|
|
5762
|
+
* that revisit thousands of distinct items in a single session.
|
|
5763
|
+
*/
|
|
5764
|
+
maxCacheSize: number;
|
|
5765
|
+
private readonly components;
|
|
5766
|
+
private readonly cache;
|
|
5767
|
+
constructor(components: Components);
|
|
5768
|
+
/** {@link Disposable.dispose} */
|
|
5769
|
+
dispose(): void;
|
|
5770
|
+
/**
|
|
5771
|
+
* Returns the best snap candidate among the requested classes for a
|
|
5772
|
+
* pre-picked surface point on a known item, or `null` if the item
|
|
5773
|
+
* has no shell geometry. When multiple classes are requested, the
|
|
5774
|
+
* winner is whichever produces the smallest distance to the input
|
|
5775
|
+
* `point`.
|
|
5776
|
+
*
|
|
5777
|
+
* @param point - Pick point in world space (typically from the GPU
|
|
5778
|
+
* picker's `getFullPick`).
|
|
5779
|
+
* @param modelId - Model the picked item belongs to.
|
|
5780
|
+
* @param localId - The picked item's localId.
|
|
5781
|
+
* @param classes - Subset of {@link SnapClass} the caller cares about.
|
|
5782
|
+
*/
|
|
5783
|
+
resolve(point: THREE.Vector3, modelId: string,
|
|
5784
|
+
/**
|
|
5785
|
+
* Internal **itemId** (the FlatBuffer `sample.item()` index, key
|
|
5786
|
+
* for `boxes.sampleOf`), not the user-facing localId. The picker
|
|
5787
|
+
* exposes this on its full-pick result; passing it through here
|
|
5788
|
+
* lets us hit the O(1) item→samples reverse index on the worker
|
|
5789
|
+
* via `_getItemSnapData(itemId)`. Keying by localId would force a
|
|
5790
|
+
* full sample-table scan (~1 s on big models).
|
|
5791
|
+
*/
|
|
5792
|
+
itemId: number, classes: Iterable<SnapClass>): Promise<SnapResult | null>;
|
|
5793
|
+
/**
|
|
5794
|
+
* Fire-and-forget prefetch of an item's snap geometry. Hoverer calls
|
|
5795
|
+
* this on lock-onto-new-item so by the time the user clicks, the
|
|
5796
|
+
* worker round-trip is already paid and `resolve` resolves
|
|
5797
|
+
* synchronously off the cache.
|
|
5798
|
+
*
|
|
5799
|
+
* Returns a Promise so callers who *do* want to await can; most
|
|
5800
|
+
* won't.
|
|
5801
|
+
*/
|
|
5802
|
+
prefetch(modelId: string, itemId: number): Promise<void>;
|
|
5803
|
+
/** Drop a specific item from the cache (e.g. after an edit). */
|
|
5804
|
+
invalidate(modelId: string, itemId: number): void;
|
|
5805
|
+
/** Drop the entire cache. Useful when many items have changed. */
|
|
5806
|
+
clear(): void;
|
|
5807
|
+
private static keyOf;
|
|
5808
|
+
private storeWithLRU;
|
|
5809
|
+
private fetchItemSnapData;
|
|
5810
|
+
private collectPolygonsFromShell;
|
|
5811
|
+
private snap;
|
|
5812
|
+
private snapToPoint;
|
|
5813
|
+
private snapToLine;
|
|
5814
|
+
private snapToFace;
|
|
5815
|
+
}
|
|
5816
|
+
|
|
5817
|
+
/**
|
|
5818
|
+
* Singleton component that owns one shared {@link SnapResolver} for
|
|
5819
|
+
* the {@link Components} instance. Snap caches are keyed by
|
|
5820
|
+
* `(modelId, localId)` so a single resolver across all worlds is
|
|
5821
|
+
* fine — there's no per-world state.
|
|
5822
|
+
*/
|
|
5823
|
+
export declare class SnapResolvers extends Component implements Disposable_2 {
|
|
5824
|
+
/** Components-system UUID. */
|
|
5825
|
+
static readonly uuid: "be9b8e6c-7f5b-4a36-8e7e-3a1f5e2a6c9d";
|
|
5826
|
+
/** {@link Component.enabled} */
|
|
5827
|
+
enabled: boolean;
|
|
5828
|
+
/** {@link Disposable.onDisposed} */
|
|
5829
|
+
readonly onDisposed: Event_2<unknown>;
|
|
5830
|
+
private readonly _resolver;
|
|
5831
|
+
constructor(components: Components);
|
|
5832
|
+
/** The shared {@link SnapResolver}. */
|
|
5833
|
+
get(): SnapResolver;
|
|
5834
|
+
/** {@link Disposable.dispose} */
|
|
5835
|
+
dispose(): void;
|
|
5836
|
+
}
|
|
5837
|
+
|
|
5838
|
+
/**
|
|
5839
|
+
* One result of a {@link SnapResolver.resolve} call. Fields match what
|
|
5840
|
+
* the worker raycast snap path historically produces, so consumers
|
|
5841
|
+
* (length / area measurements, drawing tools) keep working unchanged
|
|
5842
|
+
* when their input switches from worker raycast to GPU pick + this.
|
|
5843
|
+
*/
|
|
5844
|
+
export declare type SnapResult = {
|
|
5845
|
+
/** Snapped world-space position (vertex / segment closest point /
|
|
5846
|
+
* point projected onto the snapped face). */
|
|
5847
|
+
point: THREE.Vector3;
|
|
5848
|
+
/** World-space surface normal where applicable (always set for FACE,
|
|
5849
|
+
* unset for POINT, derived from the picked surface for LINE). */
|
|
5850
|
+
normal?: THREE.Vector3;
|
|
5851
|
+
/** Which snap class this result represents. */
|
|
5852
|
+
snappingClass: SnapClass;
|
|
5853
|
+
/** Polygon vertices of the snapped face (FACE only). Flat array of
|
|
5854
|
+
* `[x, y, z, x, y, z, ...]`. */
|
|
5855
|
+
facePoints?: Float32Array;
|
|
5856
|
+
/** Triangulation indices into `facePoints` (FACE only). For convex
|
|
5857
|
+
* polygons we emit a fan; for concave the consumer can re-tessellate. */
|
|
5858
|
+
faceIndices?: Uint32Array;
|
|
5859
|
+
/** Endpoints of the snapped edge (LINE only). */
|
|
5860
|
+
snappedEdgeP1?: THREE.Vector3;
|
|
5861
|
+
snappedEdgeP2?: THREE.Vector3;
|
|
5862
|
+
};
|
|
5863
|
+
|
|
5473
5864
|
/** A single technical drawing — the core spatial aggregate. */
|
|
5474
5865
|
export declare class TechnicalDrawing {
|
|
5475
5866
|
/** Unique identifier for this drawing instance. */
|
|
@@ -6815,6 +7206,17 @@ export declare class Views extends Component {
|
|
|
6815
7206
|
*/
|
|
6816
7207
|
world: World | null;
|
|
6817
7208
|
private _fragmentsUpdateEvent;
|
|
7209
|
+
/**
|
|
7210
|
+
* When true, opening a view snapshots the active camera's controls state
|
|
7211
|
+
* (via `controls.toJSON()`) and closing the view restores that snapshot
|
|
7212
|
+
* (via `controls.fromJSON(json, true)`), so exiting a view returns the
|
|
7213
|
+
* camera to the same pose the user had before entering it. Default true.
|
|
7214
|
+
*
|
|
7215
|
+
* Set to `false` to keep the legacy behavior, where the default camera
|
|
7216
|
+
* lands at whatever pose its controls drifted to during the view session.
|
|
7217
|
+
*/
|
|
7218
|
+
restoreCameraOnClose: boolean;
|
|
7219
|
+
private _restoreState;
|
|
6818
7220
|
/**
|
|
6819
7221
|
* Determines whether there are any open views in this component's list.
|
|
6820
7222
|
*/
|
|
@@ -6885,6 +7287,14 @@ export declare class Views extends Component {
|
|
|
6885
7287
|
* @remarks This method resets the world to use its default camera.
|
|
6886
7288
|
*/
|
|
6887
7289
|
close(id?: string): void;
|
|
7290
|
+
/**
|
|
7291
|
+
* Routes input to a single camera by toggling `controls.enabled`. Every
|
|
7292
|
+
* camera in the world owns its own CameraControls instance bound to the
|
|
7293
|
+
* renderer's DOM element; without this, all of them would react to the
|
|
7294
|
+
* same wheel/pointer events in parallel, so navigating one view would
|
|
7295
|
+
* drift every other camera at the same time.
|
|
7296
|
+
*/
|
|
7297
|
+
private setOnlyEnabledControls;
|
|
6888
7298
|
}
|
|
6889
7299
|
|
|
6890
7300
|
/**
|