@weasel-js/kernel3d 1.13.0 → 1.14.0

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/README.md CHANGED
@@ -10,10 +10,13 @@ here touches WebGL.
10
10
  ```ts
11
11
  import { createScene } from '@weasel-js/core';
12
12
  import {
13
- createCamera, createNodeAtPoint, createPoseDescriptor, pose3, type Pose3,
13
+ POSE3_COMPOSITION, createCamera, createNodeAtPoint, createPoseDescriptor, pose3, type Pose3,
14
14
  } from '@weasel-js/kernel3d';
15
15
 
16
- const scene = createScene<MyData, 'solids', Pose3>({ systemLayers: [{ id: 'solids' }] });
16
+ const scene = createScene<MyData, 'solids', Pose3>({
17
+ composition: POSE3_COMPOSITION,
18
+ systemLayers: [{ id: 'solids' }],
19
+ });
17
20
  const world = { scene, viewport: () => ({ camera, width, height }) };
18
21
 
19
22
  // Every dep takes its camera from a thunk. That is the whole trick: the
@@ -66,12 +69,33 @@ depth. Two consequences:
66
69
  is the mean of the two the rectangle gives it, and it reads `scale` as world
67
70
  extents — the unit-primitive assumption `aabbOfPose` makes by default.
68
71
 
72
+ ## Containers
73
+
74
+ `POSE3_COMPOSITION` stores a child's pose in its container's frame: moving,
75
+ turning or scaling a container carries everything under it. It is exact when a
76
+ container's scale is uniform; under a non-uniform one a turned child keeps its
77
+ own axes rather than shearing, which a `Pose3` cannot hold.
78
+
79
+ Every world read folds a node's pose up through its containers first: picking,
80
+ the marquee, snap targets and what a move drags. A renderer does the same with
81
+ `worldPoseOf(scene, id)`, which also honors a gesture's in-flight pose; drawing
82
+ `node.pose` draws a nested node at its container-relative position.
83
+
84
+ A `kind: 'group'` container selects as it does in 2D: a click on a nested node
85
+ selects its outermost container, a double-click enters it, and a click inside
86
+ then selects the next level in. `createNodeAtPoint` answers the solid the ray
87
+ hits and core's select tool walks up from it, so this needs nothing from the
88
+ host but `<SceneCanvas>`'s own select tool.
89
+
69
90
  ## The bounds seam
70
91
 
71
- `World3d.bounds` is how a consumer says how big a node is. The kernel's default
72
- carries a unit cube by the pose; override it when a primitive knows better. A
73
- sphere is the case that forces the seam to be shaped this way — its box is the
74
- same under every rotation, and no transform of a local box reproduces that.
92
+ `World3d.bounds` is how a consumer says how big a node is. It is handed the node
93
+ at its world pose and answers a world box, or `null` for a node that occupies
94
+ nothing, which is then never picked or snapped to. The kernel's default carries
95
+ a unit cube by a mark's pose and gives a group no box; override it when a
96
+ primitive knows better, or when a container draws. A sphere is the case that
97
+ forces the seam to be shaped this way — its box is the same under every
98
+ rotation, and no transform of a local box reproduces that.
75
99
 
76
100
  ## Aims
77
101
 
@@ -79,9 +103,12 @@ A kernel3d viewport answers core's `ViewAim` contract, so a 2D view and a 3D
79
103
  pane can mark each other. `aimOf3d(viewport, viewId)` is the `Aim3d` its camera
80
104
  sees, whose extent is a `Frustum3d`: the eye and the near and far rectangles.
81
105
  Outlined in a 3D space it draws its far rectangle; in a 2D one, its footprint on
82
- z = 0, or nothing when any corner ray misses that plane. `aimSpace3d` makes a
83
- pane a target, unprojecting onto z = 0, and `cameraOfAim3d` gives back the camera
84
- a dragged aim stands for — what an `AimSource`'s `setAim` writes.
106
+ the ground, the plane through the origin at right angles to the `up` option
107
+ (default +y, as `createInsert` reads it), cut off at the far plane. The 2D x and
108
+ y lie along the two axes `up` is not: x and z for a y-up world. `aimSpace3d`
109
+ makes a pane a target, unprojecting onto the same ground, and `cameraOfAim3d`
110
+ gives back the camera a dragged aim stands for — what an `AimSource`'s `setAim`
111
+ writes.
85
112
 
86
113
  ## Math
87
114
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Vec3, Mat4, Quat, Aabb, Ray } from '@weasel-js/geom/3d';
2
- import { SceneNode, Scene, NodeId, SnapSource, SnapOutcomeStore, AreaSelectDep, NodeAtPointDep, PoseDescriptor, SnapDep, InsertExtras, InsertDep, ViewAim, AimSpace, SnapMark, OngoingHandle, Action, Tool } from '@weasel-js/core';
2
+ import { PoseComposition, SceneNode, Scene, NodeId, SnapSource, SnapOutcomeStore, AreaSelectDep, NodeAtPointDep, PoseDescriptor, SnapDep, InsertExtras, InsertDep, ViewAim, AimSpace, SnapMark, OngoingHandle, Action, Tool } from '@weasel-js/core';
3
3
  import { KitSettingsStore } from '@weasel-js/react';
4
4
  import * as _weasel_js_prefs from '@weasel-js/prefs';
5
5
 
@@ -110,6 +110,22 @@ declare function poseMatrix(pose: Pose3): Mat4;
110
110
  */
111
111
  declare function aabbOfPose(pose: Pose3, local?: Aabb): Aabb;
112
112
 
113
+ /** Container composition for `Pose3`: a child's pose is stored in its
114
+ * container's frame, and folds up to world through every frame above it. */
115
+
116
+ /**
117
+ * Container composition for a 3D scene: a container's position, rotation and
118
+ * scale all reach its children, so moving, turning or growing a container
119
+ * carries everything under it.
120
+ *
121
+ * Exact whenever the container's scale is uniform. Under a non-uniform one a
122
+ * turned child would come out sheared, which no `Pose3` holds; it keeps its
123
+ * own axes instead and takes the container's scale axis by axis. Either way
124
+ * `decompose` undoes `compose`, so a node rebased into a frame and read back
125
+ * lands where it was.
126
+ */
127
+ declare const POSE3_COMPOSITION: PoseComposition<Pose3>;
128
+
113
129
  /**
114
130
  * The screen side of the kernel: where a pointer points, and what rectangle a
115
131
  * world box covers. This is the seam weasel's 2D chrome meets — everything
@@ -209,12 +225,18 @@ type Node3d<TData, TLayer extends string> = SceneNode<TData, TLayer, Pose3>;
209
225
  * sphere's box is the same under every rotation, and no transform of a local
210
226
  * box reproduces that — rotate a cube and it widens.
211
227
  *
212
- * Omitted, a node is a unit cube carried by its pose.
228
+ * The node it is handed carries its world pose: under container composition,
229
+ * or mid-gesture, that is not the pose the scene stores. `null` means the node
230
+ * occupies nothing, so nothing picks it or snaps to it; a container that only
231
+ * groups its children answers that.
232
+ *
233
+ * Omitted, a mark is a unit cube carried by its pose and a group occupies
234
+ * nothing.
213
235
  *
214
236
  * A function of the node alone; a result that depends on anything else must
215
237
  * come with a scene change, or picks go stale.
216
238
  */
217
- type NodeBounds<TData, TLayer extends string> = (node: Node3d<TData, TLayer>) => Aabb;
239
+ type NodeBounds<TData, TLayer extends string> = (node: Node3d<TData, TLayer>) => Aabb | null;
218
240
  /** What every 3D dep is built from: the scene, the viewport, and optionally
219
241
  * each node's world box. */
220
242
  interface World3d<TData, TLayer extends string> {
@@ -224,12 +246,19 @@ interface World3d<TData, TLayer extends string> {
224
246
  /** The axis gestures resolve against. Default `+y`. */
225
247
  up?: Vec3;
226
248
  }
249
+ /**
250
+ * Where `id` is in world, as it is shown: folded up through every container
251
+ * frame above it under the scene's composition, at the pose an in-flight
252
+ * gesture published where there is one. What a renderer draws the node at.
253
+ */
254
+ declare function worldPoseOf<TData, TLayer extends string>(scene: Scene3d<TData, TLayer>, id: NodeId): Pose3 | undefined;
227
255
 
228
256
  /**
229
- * The 3D world's pick index: one BVH over every node's world box, rebuilt
230
- * whole on the first pick after the scene, its overrides or the world's
231
- * `bounds` function can have changed. A node whose box the tree refuses
232
- * (non-finite or inverted) is tested on every pick, the way the scan did.
257
+ * The 3D world's pick index: one BVH over every node's world box as shown,
258
+ * rebuilt whole on the first pick after the scene, its overrides or the
259
+ * world's `bounds` function can have changed. A node whose box the tree
260
+ * refuses (non-finite or inverted) is tested on every pick, the way the scan
261
+ * did; one that occupies nothing is never picked.
233
262
  */
234
263
 
235
264
  /** The screen box a node covers, or null when it projects to nothing visible. */
@@ -337,10 +366,21 @@ type Aim3d = ViewAim<Frustum3d> & {
337
366
  readonly kind: 'frustum';
338
367
  readonly viewport: Viewport3d;
339
368
  };
340
- /** The aim of view `viewId` (`null`: a surface's root): the frustum `viewport`'s camera sees. */
341
- declare function aimOf3d(viewport: Viewport3d, viewId: string | null): Aim3d;
342
- /** A 3D pane as a target. It projects through `projectPoint` and unprojects onto the plane z = 0, where 2D worlds lie. */
343
- declare function aimSpace3d(viewport: Viewport3d, viewId: string | null): AimSpace;
369
+ /** How a kernel3d view meets a 2D one. */
370
+ interface Aim3dOptions {
371
+ /** The axis the ground, where a 2D world lies, is at right angles to: `createInsert`'s `up`. Default `+y`. */
372
+ up?: Vec3;
373
+ }
374
+ /**
375
+ * The aim of view `viewId` (`null`: a surface's root): the frustum `viewport`'s camera sees. Drawn into a 2D view, it
376
+ * outlines its footprint on the ground, the ground's two axes carrying the 2D world's x and y.
377
+ */
378
+ declare function aimOf3d(viewport: Viewport3d, viewId: string | null, opts?: Aim3dOptions): Aim3d;
379
+ /**
380
+ * A 3D pane as a target. Its points are aim points: x and y along the ground's two axes and z, height, along `up`,
381
+ * so a 2D world's points lie on the ground. It projects through `projectPoint` and unprojects onto the ground.
382
+ */
383
+ declare function aimSpace3d(viewport: Viewport3d, viewId: string | null, opts?: Aim3dOptions): AimSpace;
344
384
  /** The camera an aim was read from, which is what a by-value source's writer sets. */
345
385
  declare function cameraOfAim3d(aim: Aim3d): Camera3d;
346
386
 
@@ -516,4 +556,4 @@ declare const kernel3dKitSettingsSchema: Omit<_weasel_js_prefs.PrefGroup, "child
516
556
  };
517
557
  };
518
558
 
519
- export { type Aim3d, type Camera3d, type Camera3dDep, type ChromeBox, DEFAULT_ORBIT_LIMITS, type Footprint, type Frustum3d, type GroundGridSourceOptions, MAX_PITCH, type Node3d, type NodeBounds, type Orbit3dKitSettings, type OrbitLimits, type Pose3, type Scene3d, type ScreenBox, type ScreenLine, type ScreenPoint, type Snap3dOptions, UNIT_CUBE, type Viewport3d, type ViewportSource, type World3d, aabbOfPose, aimOf3d, aimSpace3d, alignPlaneSource, boxSnapSource, cameraEye, cameraOfAim3d, cameraView, cameraViewProjection, clampCamera, collectOverlayBoxes, createAreaSelect, createCamera, createInsert, createNodeAtPoint, createPoseDescriptor, createSnap, dollyAction, dollyBy, dollyToward, groundGridSource, homeAction, kernel3dKitSettingsSchema, ndcToScreen, orbitAction, orbitBy, panAction, panBy, pinchDollyAction, pose3, poseMatrix, projectAabbToScreen, projectPoint, projectSnapMarks, rayThroughScreenPoint, screenBoxOf, screenToNdc, useOrbitTool };
559
+ export { type Aim3d, type Aim3dOptions, type Camera3d, type Camera3dDep, type ChromeBox, DEFAULT_ORBIT_LIMITS, type Footprint, type Frustum3d, type GroundGridSourceOptions, MAX_PITCH, type Node3d, type NodeBounds, type Orbit3dKitSettings, type OrbitLimits, POSE3_COMPOSITION, type Pose3, type Scene3d, type ScreenBox, type ScreenLine, type ScreenPoint, type Snap3dOptions, UNIT_CUBE, type Viewport3d, type ViewportSource, type World3d, aabbOfPose, aimOf3d, aimSpace3d, alignPlaneSource, boxSnapSource, cameraEye, cameraOfAim3d, cameraView, cameraViewProjection, clampCamera, collectOverlayBoxes, createAreaSelect, createCamera, createInsert, createNodeAtPoint, createPoseDescriptor, createSnap, dollyAction, dollyBy, dollyToward, groundGridSource, homeAction, kernel3dKitSettingsSchema, ndcToScreen, orbitAction, orbitBy, panAction, panBy, pinchDollyAction, pose3, poseMatrix, projectAabbToScreen, projectPoint, projectSnapMarks, rayThroughScreenPoint, screenBoxOf, screenToNdc, useOrbitTool, worldPoseOf };