@forgeax/engine-picking 0.1.33 → 0.1.34
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 +51 -4
- package/dist/__tests__/display-picking.unit.test.d.ts +2 -0
- package/dist/__tests__/display-picking.unit.test.d.ts.map +1 -0
- package/dist/__tests__/voxel-display-consumer.test-d.d.ts +2 -0
- package/dist/__tests__/voxel-display-consumer.test-d.d.ts.map +1 -0
- package/dist/display-picking.d.ts +27 -0
- package/dist/display-picking.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +455 -273
- package/dist/index.mjs.map +1 -1
- package/dist/pick-core.d.ts +2 -0
- package/dist/pick-core.d.ts.map +1 -1
- package/dist/pick-triangle.d.ts +0 -3
- package/dist/pick-triangle.d.ts.map +1 -1
- package/dist/pick-vertex.d.ts +9 -0
- package/dist/pick-vertex.d.ts.map +1 -1
- package/dist/pick.d.ts +3 -0
- package/dist/pick.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/__tests__/display-picking.unit.test.ts +163 -0
- package/src/__tests__/pick-triangle.unit.test.ts +6 -9
- package/src/__tests__/voxel-display-consumer.test-d.ts +57 -0
- package/src/display-picking.ts +302 -0
- package/src/index.ts +9 -0
- package/src/pick-core.ts +33 -0
- package/src/pick-triangle.ts +3 -12
- package/src/pick-vertex.ts +77 -12
- package/src/pick.ts +6 -1
package/README.md
CHANGED
|
@@ -20,6 +20,23 @@ never the reverse.
|
|
|
20
20
|
- **`viewportToWorld(world, cameraEntity, screenX, screenY, viewportWidth, viewportHeight)`**
|
|
21
21
|
— exposes the same camera unprojection as a world-space `Ray` for cursor
|
|
22
22
|
placement, gizmos, and custom plane/triangle queries.
|
|
23
|
+
- **`pickDisplay` / `computeDisplayScreenRay`** — explicit display-space
|
|
24
|
+
entrypoints. They consume the effective `BarrelDistortionMapping` from the
|
|
25
|
+
submitted frame, map the displayed physical pixel once, then use the existing
|
|
26
|
+
unwarped camera math. The submitted mapping is mandatory, including its
|
|
27
|
+
identity case; absent, retired, lost, or zero-size frame contexts return a
|
|
28
|
+
miss. Legacy `pick` and `viewportToWorld` remain unwarped APIs.
|
|
29
|
+
- **`pickVertexDisplay` / `pickVertexOnEntityDisplay`** — display-space vertex
|
|
30
|
+
queries. They project each candidate back through the same scene-to-display
|
|
31
|
+
inverse before applying the optional physical-pixel radius and sorting, so a
|
|
32
|
+
nonlinear warp cannot change which vertex is closest merely by correcting the
|
|
33
|
+
pointer.
|
|
34
|
+
|
|
35
|
+
> [!WARNING]
|
|
36
|
+
> An omitted `barrelDistortion` field means that no accepted submitted display
|
|
37
|
+
> context is available. Treat it as a miss and wait for a new frame. An
|
|
38
|
+
> identity query is valid only with an explicit submitted mapping whose
|
|
39
|
+
> `strength` is `0`.
|
|
23
40
|
- **`pickTriangle`** — exact static CPU triangle query for a screen ray. It
|
|
24
41
|
transforms indexed or non-indexed triangle-list vertices into world space,
|
|
25
42
|
returns the nearest world point, distance, barycentric weights, entity,
|
|
@@ -84,6 +101,37 @@ and `orthographic` camera projections are supported. Reads the resolved
|
|
|
84
101
|
`GlobalTransform.world` mat4 directly (feat-20260601 D-3), so the camera + candidates
|
|
85
102
|
must have propagated transforms for the current frame.
|
|
86
103
|
|
|
104
|
+
### Display-space interaction
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { pickDisplay } from '@forgeax/engine-picking';
|
|
108
|
+
|
|
109
|
+
const hit = pickDisplay(
|
|
110
|
+
world,
|
|
111
|
+
cameraEntity,
|
|
112
|
+
outputPixelX,
|
|
113
|
+
outputPixelY,
|
|
114
|
+
submittedReceipt.barrelDistortion,
|
|
115
|
+
outputWidth,
|
|
116
|
+
outputHeight,
|
|
117
|
+
);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Coordinates are continuous physical output pixels. The host first converts the
|
|
121
|
+
CSS pointer through the actual canvas/viewport rectangle and output extent; it
|
|
122
|
+
does not add a half-pixel offset. Out-of-viewport and crop misses return
|
|
123
|
+
`undefined` before the math layer's normal screen clamp. Reuse the same receipt
|
|
124
|
+
mapping for labels, crosshairs, and display-space queries so a newer ECS camera
|
|
125
|
+
component cannot disagree with the frame on screen. The App
|
|
126
|
+
`subscribeBrowserFrameSubmitted(canvas, listener)` helper forwards the
|
|
127
|
+
deep-frozen mapping and frame identity from the accepted browser submission;
|
|
128
|
+
unsubscribe it when the canvas or renderer is retired. A lost or zero-size
|
|
129
|
+
context must be discarded and reacquired through the existing App/Renderer
|
|
130
|
+
recovery path. The width and height arguments are an explicit check against
|
|
131
|
+
`mapping.width` and `mapping.height`; a mismatch, an undefined mapping, or an
|
|
132
|
+
identity guess without a submitted mapping returns a miss. Display picking
|
|
133
|
+
never falls back to the live World camera.
|
|
134
|
+
|
|
87
135
|
### Screen-to-world (`viewportToWorld`)
|
|
88
136
|
|
|
89
137
|
| Function | Signature | Return |
|
|
@@ -132,10 +180,9 @@ Only `triangle-list` submeshes participate; skinned meshes report
|
|
|
132
180
|
nearest `TriangleHit`; `miss` means every candidate was tested and no triangle
|
|
133
181
|
intersects the ray; `unavailable` names intersecting entities whose CPU
|
|
134
182
|
geometry, current skinned pose, or explicit instance transforms cannot be
|
|
135
|
-
tested. For an entity carrying `Instances`,
|
|
136
|
-
`
|
|
137
|
-
|
|
138
|
-
read, so inspection cannot consume a later render upload range. Pass
|
|
183
|
+
tested. For an entity carrying `Instances`, the picker reads World-owned
|
|
184
|
+
`Instances.transforms`; a hit includes the zero-based `instanceIndex`.
|
|
185
|
+
No Renderer or collection resolver is needed. Pass
|
|
139
186
|
`AssetRegistry.guidOf` as `assetGuidOf` when provenance is needed. The query
|
|
140
187
|
does not mutate the World or own an asset registry.
|
|
141
188
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-picking.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/display-picking.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voxel-display-consumer.test-d.d.ts","sourceRoot":"","sources":["../../src/__tests__/voxel-display-consumer.test-d.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { EntityHandle, World } from '@forgeax/engine-ecs';
|
|
2
|
+
import { type BarrelDistortionMapping, type DisplayPoint } from '@forgeax/engine-render';
|
|
3
|
+
import { type PickHit } from './pick';
|
|
4
|
+
import { type ScreenRay } from './pick-core';
|
|
5
|
+
import { type VertexHit } from './pick-vertex';
|
|
6
|
+
export interface DisplayVertexPickOptions {
|
|
7
|
+
readonly limit?: number;
|
|
8
|
+
/** Maximum distance in displayed physical pixels; omitted keeps all ray hits. */
|
|
9
|
+
readonly radius?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Convert a displayed output pixel to the matching unwarped scene pixel.
|
|
13
|
+
*
|
|
14
|
+
* `undefined` is the fail-closed signal that no accepted submitted frame is
|
|
15
|
+
* available. It is not an identity mapping; callers must wait for a new
|
|
16
|
+
* submitted frame (including an explicit zero-strength mapping).
|
|
17
|
+
*/
|
|
18
|
+
export declare function displayToScenePixel(out: DisplayPoint, mapping: BarrelDistortionMapping | undefined, displayX: number, displayY: number): boolean;
|
|
19
|
+
/** Build a world ray from the physical pixel currently visible on screen. */
|
|
20
|
+
export declare function computeDisplayScreenRay(world: World, cameraEntity: EntityHandle, displayX: number, displayY: number, mapping: BarrelDistortionMapping | undefined, viewportWidth: number, viewportHeight: number): ScreenRay | undefined;
|
|
21
|
+
/** Explicit display-space entity pick; legacy `pick` remains unwarped. */
|
|
22
|
+
export declare function pickDisplay(world: World, _cameraEntity: EntityHandle, displayX: number, displayY: number, mapping: BarrelDistortionMapping | undefined, viewportWidth: number, viewportHeight: number): PickHit | undefined;
|
|
23
|
+
/** Pick vertices using displayed-pixel radius and ordering under the same mapping. */
|
|
24
|
+
export declare function pickVertexDisplay(world: World, _cameraEntity: EntityHandle, displayX: number, displayY: number, mapping: BarrelDistortionMapping | undefined, viewportWidth: number, viewportHeight: number, options?: DisplayVertexPickOptions): VertexHit | VertexHit[] | undefined;
|
|
25
|
+
/** Pick vertices on one entity using displayed-pixel radius and ordering. */
|
|
26
|
+
export declare function pickVertexOnEntityDisplay(world: World, _cameraEntity: EntityHandle, displayX: number, displayY: number, mapping: BarrelDistortionMapping | undefined, viewportWidth: number, viewportHeight: number, entity: EntityHandle, options?: DisplayVertexPickOptions): VertexHit | VertexHit[] | undefined;
|
|
27
|
+
//# sourceMappingURL=display-picking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display-picking.d.ts","sourceRoot":"","sources":["../src/display-picking.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE/D,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EAGlB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,OAAO,EAAqB,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,uBAAuB,GAAG,SAAS,EAC5C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAGT;AA8BD,6EAA6E;AAC7E,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,KAAK,EACZ,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uBAAuB,GAAG,SAAS,EAC5C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,SAAS,GAAG,SAAS,CAoBvB;AAqBD,0EAA0E;AAC1E,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,YAAY,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uBAAuB,GAAG,SAAS,EAC5C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,OAAO,GAAG,SAAS,CAkBrB;AAiED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,YAAY,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uBAAuB,GAAG,SAAS,EAC5C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,wBAAwB,GACjC,SAAS,GAAG,SAAS,EAAE,GAAG,SAAS,CAmCrC;AAED,6EAA6E;AAC7E,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,YAAY,EAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,uBAAuB,GAAG,SAAS,EAC5C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,wBAAwB,GACjC,SAAS,GAAG,SAAS,EAAE,GAAG,SAAS,CAkCrC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type { DisplayVertexPickOptions } from './display-picking';
|
|
2
|
+
export { computeDisplayScreenRay, displayToScenePixel, pickDisplay, pickVertexDisplay, pickVertexOnEntityDisplay, } from './display-picking';
|
|
1
3
|
export type { PickHit } from './pick';
|
|
2
4
|
export { pick } from './pick';
|
|
3
5
|
export type { PickErrorCode } from './pick-errors';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAG3B,YAAY,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,EACL,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,6BAA6B,GACnC,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|