@thatopen/components 3.4.1 → 3.4.3
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 +3728 -843
- package/dist/index.d.ts +520 -91
- package/dist/index.min.cjs +2 -2
- package/dist/index.min.mjs +2 -2
- package/dist/index.mjs +3730 -845
- 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
|
-
*
|
|
2894
|
-
*/
|
|
2895
|
-
private colorToModelId;
|
|
2896
|
-
/**
|
|
2897
|
-
* Map from model ID to color.
|
|
2898
|
-
*/
|
|
2899
|
-
private modelIdToColor;
|
|
2900
|
-
/**
|
|
2901
|
-
* Render target for the color-coded scene.
|
|
2952
|
+
* Maximum models the picker can disambiguate in a single pick. Capped
|
|
2953
|
+
* by the 8-bit `modelByte`. In practice we never approach this.
|
|
2902
2954
|
*/
|
|
2903
|
-
|
|
2955
|
+
static readonly MAX_MODELS = 254;
|
|
2956
|
+
private _renderTarget?;
|
|
2957
|
+
private _renderTargetSize;
|
|
2958
|
+
private _debugCanvas?;
|
|
2959
|
+
private _debugContainer?;
|
|
2904
2960
|
/**
|
|
2905
|
-
*
|
|
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.
|
|
2906
2965
|
*/
|
|
2907
|
-
private
|
|
2966
|
+
private _idMaterial;
|
|
2908
2967
|
/**
|
|
2909
|
-
*
|
|
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.
|
|
2910
2973
|
*/
|
|
2911
|
-
private
|
|
2974
|
+
private _depthMaterial;
|
|
2912
2975
|
/**
|
|
2913
|
-
*
|
|
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.
|
|
2914
2983
|
*/
|
|
2915
|
-
private
|
|
2984
|
+
private _normalMaterial;
|
|
2916
2985
|
/**
|
|
2917
|
-
*
|
|
2986
|
+
* Cached original materials for the swap-render-restore pass.
|
|
2987
|
+
* Populated in {@link applyIdMaterial}, drained in
|
|
2988
|
+
* {@link restoreOriginalMaterials} after the render.
|
|
2918
2989
|
*/
|
|
2919
|
-
private
|
|
2990
|
+
private _originalMaterials;
|
|
2920
2991
|
/**
|
|
2921
|
-
*
|
|
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.
|
|
2922
2996
|
*/
|
|
2923
|
-
private
|
|
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
|
/**
|
|
@@ -3125,9 +3340,21 @@ export declare class FirstPersonMode implements NavigationMode {
|
|
|
3125
3340
|
export declare function formatSlope(slope: number, format: SlopeFormat): string;
|
|
3126
3341
|
|
|
3127
3342
|
/**
|
|
3128
|
-
* Component to load, delete and manage [fragments](https://github.com/ThatOpen/engine_fragment) efficiently. 📕 [Tutorial](https://docs.thatopen.com/Tutorials/Components/Core/FragmentsManager). 📘 [API](https://docs.thatopen.com/api/@thatopen/components/classes/FragmentsManager).
|
|
3343
|
+
* Component to load, delete and manage [fragments](https://github.com/ThatOpen/engine_fragment) efficiently. 📕 [Tutorial](https://docs.thatopen.com/Tutorials/Components/Core/FragmentsManager). 📘 [API](https://docs.thatopen.com/api/@thatopen/components/classes/FragmentsManager). Before calling {@link FragmentsManager.init}, you need a URL for the fragments worker. The recommended way to get it is {@link FragmentsManager.getWorker}, which fetches the version-matched worker from unpkg.
|
|
3129
3344
|
*/
|
|
3130
3345
|
export declare class FragmentsManager extends Component implements Disposable_2 {
|
|
3346
|
+
/**
|
|
3347
|
+
* Returns a blob URL for the fragments worker matching the installed
|
|
3348
|
+
* `@thatopen/fragments` version. Delegates to {@link FRAGS.FragmentsModels.getWorker}.
|
|
3349
|
+
* This is the recommended way to obtain the URL passed to {@link FragmentsManager.init}.
|
|
3350
|
+
*
|
|
3351
|
+
* @example
|
|
3352
|
+
* ```ts
|
|
3353
|
+
* const fragments = components.get(OBC.FragmentsManager);
|
|
3354
|
+
* fragments.init(await OBC.FragmentsManager.getWorker());
|
|
3355
|
+
* ```
|
|
3356
|
+
*/
|
|
3357
|
+
static getWorker(): Promise<string>;
|
|
3131
3358
|
/**
|
|
3132
3359
|
* A unique identifier for the component.
|
|
3133
3360
|
* This UUID is used to register the component within the Components system.
|
|
@@ -3156,6 +3383,13 @@ export declare class FragmentsManager extends Component implements Disposable_2
|
|
|
3156
3383
|
constructor(components: Components);
|
|
3157
3384
|
/** {@link Disposable.dispose} */
|
|
3158
3385
|
dispose(): void;
|
|
3386
|
+
/**
|
|
3387
|
+
* Initializes the fragments core with the given worker URL.
|
|
3388
|
+
* The recommended way to obtain the URL is {@link FragmentsManager.getWorker}:
|
|
3389
|
+
* ```ts
|
|
3390
|
+
* fragments.init(await OBC.FragmentsManager.getWorker());
|
|
3391
|
+
* ```
|
|
3392
|
+
*/
|
|
3159
3393
|
init(workerURL: string, options?: {
|
|
3160
3394
|
classicWorker?: boolean;
|
|
3161
3395
|
}): void;
|
|
@@ -5136,13 +5370,6 @@ export declare class SimpleRaycaster implements Disposable_2 {
|
|
|
5136
5370
|
* This is used to access the camera and meshes.
|
|
5137
5371
|
*/
|
|
5138
5372
|
world: World;
|
|
5139
|
-
/**
|
|
5140
|
-
* Whether to use fast model picking to optimize raycasting.
|
|
5141
|
-
* When enabled, the raycaster will first use FastModelPicker to identify
|
|
5142
|
-
* which model is under the mouse, then only raycast that specific model.
|
|
5143
|
-
* This can significantly improve performance when there are many models.
|
|
5144
|
-
*/
|
|
5145
|
-
useFastModelPicking: boolean;
|
|
5146
5373
|
constructor(components: Components, world: World);
|
|
5147
5374
|
/** {@link Disposable.dispose} */
|
|
5148
5375
|
dispose(): void;
|
|
@@ -5172,7 +5399,7 @@ export declare class SimpleRaycaster implements Disposable_2 {
|
|
|
5172
5399
|
* @param items - The meshes to query. If not provided, it will query all the meshes stored in {@link World.meshes}.
|
|
5173
5400
|
* @returns The first intersection found or `null` if no intersection was found.
|
|
5174
5401
|
*/
|
|
5175
|
-
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;
|
|
5176
5403
|
private intersect;
|
|
5177
5404
|
private filterClippingPlanes;
|
|
5178
5405
|
}
|
|
@@ -5207,6 +5434,48 @@ export declare class SimpleRenderer extends BaseRenderer {
|
|
|
5207
5434
|
protected _resizeObserver: ResizeObserver | null;
|
|
5208
5435
|
protected onContainerUpdated: Event_2<unknown>;
|
|
5209
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;
|
|
5210
5479
|
/**
|
|
5211
5480
|
* Constructor for the SimpleRenderer class.
|
|
5212
5481
|
*
|
|
@@ -5233,6 +5502,7 @@ export declare class SimpleRenderer extends BaseRenderer {
|
|
|
5233
5502
|
setupEvents(active: boolean): void;
|
|
5234
5503
|
private resizeEvent;
|
|
5235
5504
|
private setupRenderer;
|
|
5505
|
+
private setupLogo;
|
|
5236
5506
|
private onContextLost;
|
|
5237
5507
|
private onContextBack;
|
|
5238
5508
|
}
|
|
@@ -5308,7 +5578,7 @@ export declare class SimpleWorld<T extends BaseScene = BaseScene, U extends Base
|
|
|
5308
5578
|
/**
|
|
5309
5579
|
* All the loaded [meshes](https://threejs.org/docs/#api/en/objects/Mesh). These meshes will be taken into account in operations like raycasting.
|
|
5310
5580
|
*/
|
|
5311
|
-
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>>;
|
|
5312
5582
|
/** {@link Updateable.onAfterUpdate} */
|
|
5313
5583
|
readonly onAfterUpdate: Event_2<unknown>;
|
|
5314
5584
|
/** {@link Updateable.onBeforeUpdate} */
|
|
@@ -5451,6 +5721,146 @@ declare interface SlopeAnnotationSystem {
|
|
|
5451
5721
|
/** How the slope value is displayed in the text label. */
|
|
5452
5722
|
export declare type SlopeFormat = "percentage" | "ratio" | "degrees";
|
|
5453
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
|
+
|
|
5454
5864
|
/** A single technical drawing — the core spatial aggregate. */
|
|
5455
5865
|
export declare class TechnicalDrawing {
|
|
5456
5866
|
/** Unique identifier for this drawing instance. */
|
|
@@ -6796,6 +7206,17 @@ export declare class Views extends Component {
|
|
|
6796
7206
|
*/
|
|
6797
7207
|
world: World | null;
|
|
6798
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;
|
|
6799
7220
|
/**
|
|
6800
7221
|
* Determines whether there are any open views in this component's list.
|
|
6801
7222
|
*/
|
|
@@ -6866,6 +7287,14 @@ export declare class Views extends Component {
|
|
|
6866
7287
|
* @remarks This method resets the world to use its default camera.
|
|
6867
7288
|
*/
|
|
6868
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;
|
|
6869
7298
|
}
|
|
6870
7299
|
|
|
6871
7300
|
/**
|