@realitycollective/iwsdk-environment 0.1.0-preview.1 → 0.1.0-preview.2
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/CHANGELOG.md +3 -0
- package/README.md +4 -2
- package/dist/audio-port.js +2 -1
- package/dist/audio-port.js.map +1 -1
- package/dist/environment-port.js +2 -1
- package/dist/environment-port.js.map +1 -1
- package/dist/world-sensing-port.js +2 -1
- package/dist/world-sensing-port.js.map +1 -1
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
|
+
- `verify:pack` now lints the shape of what ships: publint over every package directory, with warnings counted as errors, and attw (Are The Types Wrong) over every packed tarball, resolving the published types under node10, node16 and bundler resolution. `cjs-resolves-to-esm` is ignored by design, because every package is ESM-only and a require() caller is expected to use a dynamic import. Both run offline on the tarballs the script already builds; `publint` and `@arethetypeswrong/cli` are dev dependencies. The script stays identical across the Reality Collective repositories.
|
|
11
12
|
- `@realitycollective/webxr-environment` - the engine-free core. `EnvironmentDirector` holds a sky (gradient or solid), fog (linear or exponential), an ambient light and a key light as plain data; interpolates between named presets over a host-supplied `update(deltaMs)`; pushes only the slots that actually changed to an `EnvironmentPort`; and applies passthrough as a suppression over what the app asked for, so nothing has to remember what to restore. A partial `EnvironmentSpec` inherits the slots it omits and turns off the ones it sets to `null`, which is what makes presets composable. Six example presets (`void`, `dawn`, `noon`, `dusk`, `night`, `overcast`) to copy, and `clearedFog`, the helper that makes fog easeable in.
|
|
12
13
|
- `@realitycollective/webxr-environment` - `AudioDirector`: a cue registry, a bus and master mix with mute kept separate from gain, per-cue retrigger policy (`overlap` / `restart` / `ignore`), a per-cue minimum retrigger interval, and voice tracking. The `AudioPort` is handed an absolute resolved gain and has no mixing left to do. A silent one-shot is never started; a silent loop is, so that unmuting mid-flight finds the ambience bed already running.
|
|
13
14
|
- `@realitycollective/threejs-environment` - the three.js adapter. Gradient skies become an equirectangular `DataTexture` generated by a pure function and regenerated in place across a transition; `Fog` / `FogExp2` are mutated rather than rebuilt while the kind holds; the key light is positioned from the direction light travels. Audio runs over `Audio` / `PositionalAudio`, and a play that arrives before its buffer has decoded is held rather than dropped, so the first press of a session is not silent.
|
|
@@ -30,6 +31,8 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
30
31
|
|
|
31
32
|
### Fixed
|
|
32
33
|
|
|
34
|
+
- `@realitycollective/iwsdk-environment` imported three.js's `Vector3`, `Quaternion`, `Fog` and `FogExp2` through `@iwsdk/core`, which only provides them by `export * from 'three'`. That resolves in node and in every demo, and fails a consumer whose Vite config excludes `three` from dependency optimization, which any app that transforms three's source does: esbuild cannot enumerate a star re-export it is not bundling, and the dev server stops with `No matching export in "@iwsdk/core" for import "Vector3"`, a message that names neither the package nor the cause. The audio, environment and world-sensing ports now import those classes from `three`, declared as a peer dependency (`>=0.170.0`, the range the three.js adapter carries), which every IWSDK application already has. `@types/three` is pinned to `0.185.4` across the workspace (root `overrides`), the typings for the super-three 0.185 the workspace runs, so the tree holds one copy of the three typings rather than the two that made the adapter's tests import `Scene` through `@iwsdk/core`. The Anatomy Atlas XR client reported the failure against the UI Extensions adapter; the estate sweep found the same import here.
|
|
35
|
+
- Two gates, shared with every Reality Collective repository. `packages/webxr-environment/test/import-surface.test.ts` runs `scripts/import-surface.mjs` over every published package and fails an import of a name that a dependency only re-exports from another package, and any bare import of a package the manifest does not declare. `packages/iwsdk-environment/test/prebundle.test.ts` runs the dependency optimizer of every bundler `scripts/release.config.json` names (`scripts/prebundle-check.mjs`) over the adapter next to `@iwsdk/core`, once with defaults and once with every package `@iwsdk/core` re-exports wholesale excluded, so the consumer path is exercised on every `npm test`. It runs on **Vite 7 and Vite 8**, because this fault belongs to a bundler rather than to bundling: Vite 7 optimizes with esbuild, which requires every named import to be statically enumerable and so rejects a name behind an external `export *`, while Vite 8 optimizes with rolldown, which resolves the same import lazily through a namespace object and accepts it. Testing only one of them would say nothing about consumers on the other. The versions under test are ordinary devDependencies installed under npm aliases, `vite-7` and `vite-8`, the same mechanism the workspace already uses for `three`; add an entry to `prebundle.bundlers` to support another. Each run also feeds the optimizer a **deliberately broken copy** of the adapter, carrying one extra module that imports a name the host only re-exports wholesale, and asserts the bundler's verdict matches that bundler's `detectsStarHops` flag. The probed name is discovered from the host's own surface rather than hard-coded, so it stays valid as that surface changes. This is what stops the check becoming decoration: on a permissive bundler a gate that can only pass reports safety it never verified, and the suite now fails if a bundler's strictness moves in either direction, or if no supported bundler can detect the fault at all. Transpiling uses the TypeScript compiler the repository already builds with, so no bundler is a hidden requirement of the harness itself. Both were red before this fix.
|
|
33
36
|
- **A hand ray is now cast from the hand.** The three.js world-sensing port used to bind every hit test to the viewer's reference space and mention in a detail string that hands were not really supported, which meant the most common AR gesture - point at the floor, place something - silently aimed from the head. It now looks the input source up by handedness, binds to its `targetRaySpace`, waits visibly while there is no such source, and unbinds when the hand goes away.
|
|
34
37
|
- **`HitTestRequest.offsetRay` is no longer dropped.** It becomes an `XRRay` (injectable, defaulting to the browser's) and is passed to the runtime. When no `XRRay` is available the request still works and the report says the offset was ignored, rather than quietly aiming somewhere else.
|
|
35
38
|
- **`WorldHit.distance` is filled where a host can fill it.** The three.js port poses the ray's own space once per frame and measures from there. IWSDK keeps its ray to itself, so it reports `null`, and the contract now says exactly what `null` means and what it does not.
|
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ It drives IWSDK's own machinery rather than reaching past it to three.js:
|
|
|
45
45
|
|
|
46
46
|
Every one of those is an IWSDK platform component with no app-side equivalent. The adapter creates **no geometry**: a floor would be a mesh, and meshes are the app's.
|
|
47
47
|
|
|
48
|
-
**Fog is the exception.** IWSDK has no fog component, so it is set on `world.scene` directly, with `Fog` / `FogExp2` imported from `@iwsdk/core`
|
|
48
|
+
**Fog is the exception.** IWSDK has no fog component, so it is set on `world.scene` directly, with `Fog` / `FogExp2` imported from `three`, a declared peer. Importing them through `@iwsdk/core`'s `export * from 'three'` looked equivalent, but a consumer that excludes `three` from Vite's dependency optimizer cannot resolve names that only exist behind that star.
|
|
49
49
|
|
|
50
50
|
## Knowing when a sound finished
|
|
51
51
|
|
|
@@ -63,10 +63,12 @@ adapter.onCapabilitiesChange((c) => env.environment.setPassthrough(c.passthrough
|
|
|
63
63
|
|
|
64
64
|
A session belongs to the platform layer, not to the environment. `setPassthrough(true)` suppresses the sky and fog on top of whatever the app asked for, and turning it off restores exactly what was there - nothing has to remember what to put back.
|
|
65
65
|
|
|
66
|
-
## Peer
|
|
66
|
+
## Peer dependencies
|
|
67
67
|
|
|
68
68
|
`@iwsdk/core >= 0.5.0 < 0.6.0`, developed and tested against 0.5.3.
|
|
69
69
|
|
|
70
|
+
`three >= 0.170.0`, which every IWSDK application already carries (IWSDK projects alias it to `super-three`). The adapter imports three.js classes from `three` directly rather than through `@iwsdk/core`'s star re-export, so it prebundles even when an application excludes `three` from Vite's dependency optimizer to transform its source.
|
|
71
|
+
|
|
70
72
|
## Licence
|
|
71
73
|
|
|
72
74
|
MIT.
|
package/dist/audio-port.js
CHANGED
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
* A voice that never starts at all (a missing file, a decode failure) would
|
|
22
22
|
* otherwise be tracked forever, so it is reaped after `startTimeoutMs`.
|
|
23
23
|
*/
|
|
24
|
-
import { AudioSource, AudioUtils, DistanceModel, PlaybackMode,
|
|
24
|
+
import { AudioSource, AudioUtils, DistanceModel, PlaybackMode, Transform, } from "@iwsdk/core";
|
|
25
|
+
import { Quaternion, Vector3 } from "three";
|
|
25
26
|
export class IWSDKAudioPort {
|
|
26
27
|
#world;
|
|
27
28
|
#parent;
|
package/dist/audio-port.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-port.js","sourceRoot":"","sources":["../src/audio-port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `AudioPort` for Meta IWSDK, over `AudioSource` + `AudioUtils`.\n *\n * ---------------------------------------------------------------------------\n * ONE ENTITY PER VOICE\n * ---------------------------------------------------------------------------\n * IWSDK's audio is a component on an entity, with its own pooling and its own\n * retrigger policy per source. Reusing one entity per CUE would hand those\n * decisions back to IWSDK and make `restart` and `ignore` mean something\n * different here than on three.js, which is the divergence this stack exists\n * to remove. So a voice is an entity: the director's policy wins, every voice\n * is individually stoppable, and IWSDK's own `playbackMode` is pinned to\n * `Overlap` so it never second-guesses the core.\n *\n * ---------------------------------------------------------------------------\n * KNOWING WHEN A SOUND FINISHED\n * ---------------------------------------------------------------------------\n * IWSDK reports whether a source IS playing, never that it has just stopped.\n * So this port polls in `update()` - which the director already calls - and\n * reports the end once a voice has been observed playing and then is not.\n * A voice that never starts at all (a missing file, a decode failure) would\n * otherwise be tracked forever, so it is reaped after `startTimeoutMs`.\n */\nimport {\n AudioSource,\n AudioUtils,\n DistanceModel,\n PlaybackMode,\n Quaternion,\n Transform,\n Vector3,\n type Entity,\n type World,\n} from \"@iwsdk/core\";\nimport type { AudioPort, AudioVoiceRequest } from \"@realitycollective/webxr-environment\";\n\nexport interface IWSDKAudioPortOptions {\n /** Parent for the voice entities. Defaults to the world's default parent. */\n readonly parent?: Entity;\n /**\n * How long to wait for a voice to start before giving up on it,\n * milliseconds. Default 10 000 - generous, because a cold asset fetch on a\n * headset over hotel wifi is slower than anyone's patience.\n */\n readonly startTimeoutMs?: number;\n}\n\ninterface Voice {\n readonly entity: Entity;\n readonly request: AudioVoiceRequest;\n started: boolean;\n waitedMs: number;\n}\n\nexport class IWSDKAudioPort implements AudioPort {\n readonly #world: World;\n readonly #parent: Entity | undefined;\n readonly #startTimeoutMs: number;\n readonly #voices = new Map<number, Voice>();\n\n #disposed = false;\n\n constructor(world: World, options: IWSDKAudioPortOptions = {}) {\n this.#world = world;\n this.#parent = options.parent;\n this.#startTimeoutMs = options.startTimeoutMs ?? 10_000;\n }\n\n start(request: AudioVoiceRequest): void {\n if (this.#disposed) {\n request.ended();\n return;\n }\n const entity = this.#world.createTransformEntity(\n undefined,\n this.#parent === undefined ? undefined : { parent: this.#parent },\n );\n const positional = request.at !== null || (request.cue.positional ?? false);\n if (request.at !== null) {\n const view = entity.getVectorView(Transform, \"position\");\n view[0] = request.at[0];\n view[1] = request.at[1];\n view[2] = request.at[2];\n }\n // IWSDK's audio system hands the entity's transform to the same three.js\n // `PositionalAudio` the other adapter uses, so forward is +Z here too and\n // the entity is turned to point that axis the way the sound travels.\n const towards = request.facing ?? null;\n if (towards !== null) {\n const facing = TEMP_FACING.set(towards[0], towards[1], towards[2]);\n if (facing.lengthSq() > 0) {\n TEMP_ROTATION.setFromUnitVectors(AUDIO_FORWARD, facing.normalize());\n const view = entity.getVectorView(Transform, \"orientation\");\n view[0] = TEMP_ROTATION.x;\n view[1] = TEMP_ROTATION.y;\n view[2] = TEMP_ROTATION.z;\n view[3] = TEMP_ROTATION.w;\n }\n }\n const attenuation = request.spatial;\n entity.addComponent(AudioSource, {\n src: request.cue.src,\n volume: request.gain,\n loop: request.loop,\n positional,\n autoplay: false,\n // The core already applied the cue's policy before we got here.\n playbackMode: PlaybackMode.Overlap,\n // Anything the cue did not describe is left to IWSDK's own defaults,\n // which is why these are spread in rather than defaulted here: this port\n // has no opinion about how far a sound carries, and inventing one would\n // make the same cue sound different on each engine.\n ...(attenuation?.refDistance === undefined ? {} : { refDistance: attenuation.refDistance }),\n ...(attenuation?.rolloffFactor === undefined\n ? {}\n : { rolloffFactor: attenuation.rolloffFactor }),\n ...(attenuation?.maxDistance === undefined ? {} : { maxDistance: attenuation.maxDistance }),\n ...(attenuation?.model === undefined ? {} : { distanceModel: distanceModel(attenuation.model) }),\n // Radians in the contract, degrees on the component - IWSDK passes these\n // straight to the same Web Audio panner three.js uses.\n ...(attenuation?.cone === undefined\n ? {}\n : {\n coneInnerAngle: toDegrees(attenuation.cone.inner),\n coneOuterAngle: toDegrees(attenuation.cone.outer),\n coneOuterGain: attenuation.cone.outsideGain,\n }),\n });\n this.#voices.set(request.voiceId, { entity, request, started: false, waitedMs: 0 });\n AudioUtils.play(entity);\n }\n\n stop(voiceId: number): void {\n const voice = this.#voices.get(voiceId);\n if (voice === undefined) return;\n this.#voices.delete(voiceId);\n this.#retire(voice);\n }\n\n setGain(voiceId: number, gain: number): void {\n const voice = this.#voices.get(voiceId);\n if (voice === undefined) return;\n AudioUtils.setVolume(voice.entity, gain);\n }\n\n update(deltaMs: number): void {\n if (this.#disposed || this.#voices.size === 0) return;\n for (const [id, voice] of [...this.#voices]) {\n // A looping voice ends when someone stops it, never on its own.\n if (voice.request.loop) continue;\n const playing = AudioUtils.isPlaying(voice.entity);\n if (playing) {\n voice.started = true;\n continue;\n }\n if (!voice.started) {\n voice.waitedMs += deltaMs;\n if (voice.waitedMs < this.#startTimeoutMs) continue;\n console.warn(\n `[iwsdk-environment] cue \"${voice.request.cue.id}\" never started (${voice.request.cue.src})`,\n );\n }\n this.#voices.delete(id);\n this.#retire(voice);\n voice.request.ended();\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n this.#disposed = true;\n for (const [id, voice] of [...this.#voices]) {\n this.#voices.delete(id);\n this.#retire(voice);\n }\n }\n\n #retire(voice: Voice): void {\n AudioUtils.stop(voice.entity);\n voice.entity.destroy();\n }\n}\n\n/** Our distance model names onto IWSDK's enum, which holds the same three. */\nfunction distanceModel(model: \"linear\" | \"inverse\" | \"exponential\"): string {\n if (model === \"linear\") return DistanceModel.Linear;\n if (model === \"exponential\") return DistanceModel.Exponential;\n return DistanceModel.Inverse;\n}\n\n/** Web Audio points a source along +Z, and IWSDK's audio system follows it. */\nconst AUDIO_FORWARD = new Vector3(0, 0, 1);\nconst TEMP_FACING = new Vector3();\nconst TEMP_ROTATION = new Quaternion();\n\n/** Radians in the contract; degrees on the component. */\nfunction toDegrees(radians: number): number {\n return (radians * 180) / Math.PI;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"audio-port.js","sourceRoot":"","sources":["../src/audio-port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `AudioPort` for Meta IWSDK, over `AudioSource` + `AudioUtils`.\n *\n * ---------------------------------------------------------------------------\n * ONE ENTITY PER VOICE\n * ---------------------------------------------------------------------------\n * IWSDK's audio is a component on an entity, with its own pooling and its own\n * retrigger policy per source. Reusing one entity per CUE would hand those\n * decisions back to IWSDK and make `restart` and `ignore` mean something\n * different here than on three.js, which is the divergence this stack exists\n * to remove. So a voice is an entity: the director's policy wins, every voice\n * is individually stoppable, and IWSDK's own `playbackMode` is pinned to\n * `Overlap` so it never second-guesses the core.\n *\n * ---------------------------------------------------------------------------\n * KNOWING WHEN A SOUND FINISHED\n * ---------------------------------------------------------------------------\n * IWSDK reports whether a source IS playing, never that it has just stopped.\n * So this port polls in `update()` - which the director already calls - and\n * reports the end once a voice has been observed playing and then is not.\n * A voice that never starts at all (a missing file, a decode failure) would\n * otherwise be tracked forever, so it is reaped after `startTimeoutMs`.\n */\nimport {\n AudioSource,\n AudioUtils,\n DistanceModel,\n PlaybackMode,\n Transform,\n type Entity,\n type World,\n} from \"@iwsdk/core\";\nimport { Quaternion, Vector3 } from \"three\";\nimport type { AudioPort, AudioVoiceRequest } from \"@realitycollective/webxr-environment\";\n\nexport interface IWSDKAudioPortOptions {\n /** Parent for the voice entities. Defaults to the world's default parent. */\n readonly parent?: Entity;\n /**\n * How long to wait for a voice to start before giving up on it,\n * milliseconds. Default 10 000 - generous, because a cold asset fetch on a\n * headset over hotel wifi is slower than anyone's patience.\n */\n readonly startTimeoutMs?: number;\n}\n\ninterface Voice {\n readonly entity: Entity;\n readonly request: AudioVoiceRequest;\n started: boolean;\n waitedMs: number;\n}\n\nexport class IWSDKAudioPort implements AudioPort {\n readonly #world: World;\n readonly #parent: Entity | undefined;\n readonly #startTimeoutMs: number;\n readonly #voices = new Map<number, Voice>();\n\n #disposed = false;\n\n constructor(world: World, options: IWSDKAudioPortOptions = {}) {\n this.#world = world;\n this.#parent = options.parent;\n this.#startTimeoutMs = options.startTimeoutMs ?? 10_000;\n }\n\n start(request: AudioVoiceRequest): void {\n if (this.#disposed) {\n request.ended();\n return;\n }\n const entity = this.#world.createTransformEntity(\n undefined,\n this.#parent === undefined ? undefined : { parent: this.#parent },\n );\n const positional = request.at !== null || (request.cue.positional ?? false);\n if (request.at !== null) {\n const view = entity.getVectorView(Transform, \"position\");\n view[0] = request.at[0];\n view[1] = request.at[1];\n view[2] = request.at[2];\n }\n // IWSDK's audio system hands the entity's transform to the same three.js\n // `PositionalAudio` the other adapter uses, so forward is +Z here too and\n // the entity is turned to point that axis the way the sound travels.\n const towards = request.facing ?? null;\n if (towards !== null) {\n const facing = TEMP_FACING.set(towards[0], towards[1], towards[2]);\n if (facing.lengthSq() > 0) {\n TEMP_ROTATION.setFromUnitVectors(AUDIO_FORWARD, facing.normalize());\n const view = entity.getVectorView(Transform, \"orientation\");\n view[0] = TEMP_ROTATION.x;\n view[1] = TEMP_ROTATION.y;\n view[2] = TEMP_ROTATION.z;\n view[3] = TEMP_ROTATION.w;\n }\n }\n const attenuation = request.spatial;\n entity.addComponent(AudioSource, {\n src: request.cue.src,\n volume: request.gain,\n loop: request.loop,\n positional,\n autoplay: false,\n // The core already applied the cue's policy before we got here.\n playbackMode: PlaybackMode.Overlap,\n // Anything the cue did not describe is left to IWSDK's own defaults,\n // which is why these are spread in rather than defaulted here: this port\n // has no opinion about how far a sound carries, and inventing one would\n // make the same cue sound different on each engine.\n ...(attenuation?.refDistance === undefined ? {} : { refDistance: attenuation.refDistance }),\n ...(attenuation?.rolloffFactor === undefined\n ? {}\n : { rolloffFactor: attenuation.rolloffFactor }),\n ...(attenuation?.maxDistance === undefined ? {} : { maxDistance: attenuation.maxDistance }),\n ...(attenuation?.model === undefined ? {} : { distanceModel: distanceModel(attenuation.model) }),\n // Radians in the contract, degrees on the component - IWSDK passes these\n // straight to the same Web Audio panner three.js uses.\n ...(attenuation?.cone === undefined\n ? {}\n : {\n coneInnerAngle: toDegrees(attenuation.cone.inner),\n coneOuterAngle: toDegrees(attenuation.cone.outer),\n coneOuterGain: attenuation.cone.outsideGain,\n }),\n });\n this.#voices.set(request.voiceId, { entity, request, started: false, waitedMs: 0 });\n AudioUtils.play(entity);\n }\n\n stop(voiceId: number): void {\n const voice = this.#voices.get(voiceId);\n if (voice === undefined) return;\n this.#voices.delete(voiceId);\n this.#retire(voice);\n }\n\n setGain(voiceId: number, gain: number): void {\n const voice = this.#voices.get(voiceId);\n if (voice === undefined) return;\n AudioUtils.setVolume(voice.entity, gain);\n }\n\n update(deltaMs: number): void {\n if (this.#disposed || this.#voices.size === 0) return;\n for (const [id, voice] of [...this.#voices]) {\n // A looping voice ends when someone stops it, never on its own.\n if (voice.request.loop) continue;\n const playing = AudioUtils.isPlaying(voice.entity);\n if (playing) {\n voice.started = true;\n continue;\n }\n if (!voice.started) {\n voice.waitedMs += deltaMs;\n if (voice.waitedMs < this.#startTimeoutMs) continue;\n console.warn(\n `[iwsdk-environment] cue \"${voice.request.cue.id}\" never started (${voice.request.cue.src})`,\n );\n }\n this.#voices.delete(id);\n this.#retire(voice);\n voice.request.ended();\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n this.#disposed = true;\n for (const [id, voice] of [...this.#voices]) {\n this.#voices.delete(id);\n this.#retire(voice);\n }\n }\n\n #retire(voice: Voice): void {\n AudioUtils.stop(voice.entity);\n voice.entity.destroy();\n }\n}\n\n/** Our distance model names onto IWSDK's enum, which holds the same three. */\nfunction distanceModel(model: \"linear\" | \"inverse\" | \"exponential\"): string {\n if (model === \"linear\") return DistanceModel.Linear;\n if (model === \"exponential\") return DistanceModel.Exponential;\n return DistanceModel.Inverse;\n}\n\n/** Web Audio points a source along +Z, and IWSDK's audio system follows it. */\nconst AUDIO_FORWARD = new Vector3(0, 0, 1);\nconst TEMP_FACING = new Vector3();\nconst TEMP_ROTATION = new Quaternion();\n\n/** Radians in the contract; degrees on the component. */\nfunction toDegrees(radians: number): number {\n return (radians * 180) / Math.PI;\n}\n"]}
|
package/dist/environment-port.js
CHANGED
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
* `getVectorView`; `setValue` on one throws. Every colour write here goes
|
|
29
29
|
* through `writeColour` for that reason - it is not a style choice.
|
|
30
30
|
*/
|
|
31
|
-
import { AmbientLightComponent, DepthOccludable, DepthSensingSystem, DirectionalLightComponent, DomeGradient, DomeTexture,
|
|
31
|
+
import { AmbientLightComponent, DepthOccludable, DepthSensingSystem, DirectionalLightComponent, DomeGradient, DomeTexture, IBLGradient, IBLTexture, OcclusionShadersMode, Transform, } from "@iwsdk/core";
|
|
32
|
+
import { Fog, FogExp2, Quaternion, Vector3 } from "three";
|
|
32
33
|
import { clamp01, lerpRgb } from "@realitycollective/webxr-environment";
|
|
33
34
|
/** 0..1 softness onto IWSDK's blur radius in pixels, whose default is 20. */
|
|
34
35
|
const MAX_BLUR_RADIUS = 40;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment-port.js","sourceRoot":"","sources":["../src/environment-port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `EnvironmentPort` for Meta IWSDK.\n *\n * ---------------------------------------------------------------------------\n * IT USES IWSDK'S OWN MACHINERY, NOT THREE.JS BEHIND ITS BACK\n * ---------------------------------------------------------------------------\n * The sky is a `DomeGradient` on the level root and the lights are\n * `AmbientLightComponent` and `DirectionalLightComponent` on entities.\n * Reaching past IWSDK to write `scene.background` or to `scene.add()` a light\n * would work right up until IWSDK's own `EnvironmentSystem` or `LightSystem`\n * disagreed - and one of the things IWSDK's environment system already does\n * correctly is hide authored backgrounds in an AR session, which is behaviour\n * worth inheriting rather than fighting.\n *\n * No geometry is created here. Every component this port touches is an IWSDK\n * platform facility with no app-side equivalent; a floor would be a mesh, and\n * meshes are the app's.\n *\n * Fog is the exception. IWSDK has no fog component, so it is set on\n * `world.scene` directly, with three.js's own `Fog` / `FogExp2` imported from\n * `@iwsdk/core` (the framework's rule - one three.js instance, reached through\n * the framework's re-export).\n *\n * ---------------------------------------------------------------------------\n * WRITING COMPONENT COLOURS\n * ---------------------------------------------------------------------------\n * A `Types.Color` or `Types.Vec3` field must be written through\n * `getVectorView`; `setValue` on one throws. Every colour write here goes\n * through `writeColour` for that reason - it is not a style choice.\n */\nimport {\n AmbientLightComponent,\n DepthOccludable,\n DepthSensingSystem,\n DirectionalLightComponent,\n DomeGradient,\n DomeTexture,\n Fog,\n FogExp2,\n IBLGradient,\n IBLTexture,\n OcclusionShadersMode,\n Quaternion,\n Transform,\n Vector3,\n type Entity,\n type World,\n} from \"@iwsdk/core\";\nimport type {\n AmbientLightSpec,\n EnvironmentPort,\n EnvironmentPortHost,\n FogSpec,\n IblSpec,\n KeyLightSpec,\n OcclusionSpec,\n ResolvedLightEstimation,\n Rgb,\n SensingReport,\n SkyGradient,\n SkySpec,\n} from \"@realitycollective/webxr-environment\";\nimport { clamp01, lerpRgb } from \"@realitycollective/webxr-environment\";\n\nexport interface IWSDKEnvironmentPortOptions {\n /**\n * Where the light entities are parented. Defaults to the active level root,\n * which is also where the dome lives, so the whole environment is torn down\n * with the level.\n */\n readonly parent?: Entity;\n /** Dome brightness multiplier, used when a sky does not name its own. Default 1. */\n readonly skyIntensity?: number;\n /**\n * Which entities the real world is allowed to hide, for `scope: \"all\"`.\n *\n * IWSDK opts entities INTO occlusion one at a time, by patching the\n * materials under each one, so somebody has to say which entities those\n * are. It cannot be this port: the entities are content, content is the\n * app's, and walking a scene graph looking for meshes would be this package\n * guessing at the app's structure.\n *\n * With no list, `scope: \"all\"` reports `unavailable` and says why. An app\n * that would rather tag its own entities uses `scope: \"tagged\"` and adds\n * `DepthOccludable` itself; then this port only configures the system.\n */\n readonly occludables?: () => Iterable<Entity>;\n}\n\n/** 0..1 softness onto IWSDK's blur radius in pixels, whose default is 20. */\nconst MAX_BLUR_RADIUS = 40;\n\n/**\n * The narrowest thing a vector view is: elics types it as a union of every\n * typed array, and all these helpers need is indexed writes and a length.\n */\ntype NumericView = { [index: number]: number; readonly length: number };\n\n/** Local -Z is where an IWSDK directional light points. */\nconst LIGHT_FORWARD = new Vector3(0, 0, -1);\nconst TEMP_DIRECTION = new Vector3();\nconst TEMP_QUATERNION = new Quaternion();\n\nexport class IWSDKEnvironmentPort implements EnvironmentPort {\n readonly #world: World;\n readonly #parent: Entity | undefined;\n readonly #skyIntensity: number;\n\n readonly #occludables: (() => Iterable<Entity>) | undefined;\n\n #domeEntity: Entity | null = null;\n #iblEntity: Entity | null = null;\n #ambientEntity: Entity | null = null;\n #keyEntity: Entity | null = null;\n #fogKind: FogSpec[\"kind\"] | null = null;\n #host: EnvironmentPortHost | null = null;\n /** Only what THIS port added, so it never removes the app's own component. */\n #occluding: Entity[] = [];\n\n constructor(world: World, options: IWSDKEnvironmentPortOptions = {}) {\n this.#world = world;\n this.#parent = options.parent;\n this.#skyIntensity = options.skyIntensity ?? 1;\n this.#occludables = options.occludables;\n }\n\n observe(host: EnvironmentPortHost): () => void {\n this.#host = host;\n return () => {\n this.#host = null;\n };\n }\n\n applySky(sky: SkySpec | null): void {\n const root = this.#levelRoot();\n if (root === null) return;\n\n if (sky === null) {\n if (this.#domeEntity !== null && this.#domeEntity.hasComponent(DomeGradient)) {\n this.#domeEntity.removeComponent(DomeGradient);\n }\n this.#domeEntity = null;\n return;\n }\n\n if (sky.kind === \"texture\") {\n // An authored sky is a different IWSDK component, so the dome one goes\n // rather than sitting underneath and fighting over the same background.\n if (root.hasComponent(DomeGradient)) root.removeComponent(DomeGradient);\n if (!root.hasComponent(DomeTexture)) root.addComponent(DomeTexture);\n this.#domeEntity = root;\n root.setValue(DomeTexture, \"src\", sky.src);\n root.setValue(DomeTexture, \"intensity\", sky.intensity ?? this.#skyIntensity);\n root.setValue(DomeTexture, \"blurriness\", sky.blur ?? 0);\n writeVec3(root.getVectorView(DomeTexture, \"rotation\"), 0, sky.rotationY ?? 0, 0);\n root.setValue(DomeTexture, \"_needsUpdate\", true);\n return;\n }\n\n if (root.hasComponent(DomeTexture)) root.removeComponent(DomeTexture);\n if (this.#domeEntity !== root || !root.hasComponent(DomeGradient)) {\n if (!root.hasComponent(DomeGradient)) root.addComponent(DomeGradient);\n this.#domeEntity = root;\n }\n\n // IWSDK's dome is a Unity-style sky / equator / ground triple. A solid sky\n // is all three the same. A gradient uses the horizon colour the app gave,\n // and derives one from the ramp when it did not - which is the same colour\n // the three.js adapter puts at the horizon, so the two engines agree there\n // rather than only at the poles.\n if (sky.kind === \"solid\") {\n writeRgb(root.getVectorView(DomeGradient, \"sky\"), sky.colour);\n writeRgb(root.getVectorView(DomeGradient, \"equator\"), sky.colour);\n writeRgb(root.getVectorView(DomeGradient, \"ground\"), sky.colour);\n root.setValue(DomeGradient, \"intensity\", this.#skyIntensity);\n } else {\n writeRgb(root.getVectorView(DomeGradient, \"sky\"), sky.top);\n writeRgb(root.getVectorView(DomeGradient, \"equator\"), equatorOf(sky));\n writeRgb(root.getVectorView(DomeGradient, \"ground\"), sky.bottom);\n root.setValue(DomeGradient, \"intensity\", sky.intensity ?? this.#skyIntensity);\n }\n root.setValue(DomeGradient, \"_needsUpdate\", true);\n }\n\n /**\n * The environment map, as IWSDK's own image-based lighting components.\n *\n * `room` is not an approximation here: IWSDK's `IBLTexture` takes the string\n * `\"room\"` for its built-in probe, so the one kind three.js has to fake is\n * the one kind this host has natively.\n */\n applyIbl(ibl: IblSpec | null): void {\n const root = this.#levelRoot();\n if (root === null) return;\n\n if (ibl === null) {\n if (this.#iblEntity !== null) {\n if (this.#iblEntity.hasComponent(IBLGradient)) this.#iblEntity.removeComponent(IBLGradient);\n if (this.#iblEntity.hasComponent(IBLTexture)) this.#iblEntity.removeComponent(IBLTexture);\n }\n this.#iblEntity = null;\n return;\n }\n this.#iblEntity = root;\n\n if (ibl.kind === \"estimated\") {\n // IWSDK measures no reflections (UPSTREAM_ENHANCEMENTS 6.1), so the slot\n // keeps whatever it had rather than being cleared: an app that asked for\n // measured reflections and got none should not also lose its own map.\n this.#report({\n feature: \"lightEstimation\",\n state: \"unsupported\",\n detail: \"IWSDK measures no reflections, so an estimated environment map cannot be applied\",\n });\n return;\n }\n\n if (ibl.kind === \"gradient\") {\n if (root.hasComponent(IBLTexture)) root.removeComponent(IBLTexture);\n if (!root.hasComponent(IBLGradient)) root.addComponent(IBLGradient);\n writeRgb(root.getVectorView(IBLGradient, \"sky\"), ibl.top);\n writeRgb(root.getVectorView(IBLGradient, \"equator\"), equatorOf(ibl));\n writeRgb(root.getVectorView(IBLGradient, \"ground\"), ibl.bottom);\n root.setValue(IBLGradient, \"intensity\", ibl.intensity ?? 1);\n root.setValue(IBLGradient, \"_needsUpdate\", true);\n return;\n }\n\n if (root.hasComponent(IBLGradient)) root.removeComponent(IBLGradient);\n if (!root.hasComponent(IBLTexture)) root.addComponent(IBLTexture);\n root.setValue(IBLTexture, \"src\", ibl.kind === \"room\" ? \"room\" : ibl.src);\n root.setValue(IBLTexture, \"intensity\", ibl.intensity ?? 1);\n writeVec3(root.getVectorView(IBLTexture, \"rotation\"), 0, ibl.rotationY ?? 0, 0);\n root.setValue(IBLTexture, \"_needsUpdate\", true);\n }\n\n /**\n * Depth occlusion, through IWSDK's `DepthSensingSystem` and the per-entity\n * `DepthOccludable` component.\n *\n * IWSDK patches the materials under each opted-in entity, which is why the\n * scope matters more here than on three.js: there is no global mode to turn\n * on, and an entity nobody opted in is an entity the real world will not\n * hide. Whatever this port adds, it remembers, so turning occlusion off\n * never strips a component the app put there itself.\n */\n applyOcclusion(spec: OcclusionSpec | null): void {\n if (spec === null) {\n this.#releaseOccludables();\n const running = this.#system();\n if (running !== undefined) running.config.enableOcclusion.value = false;\n this.#report({ feature: \"occlusion\", state: \"unavailable\", detail: \"occlusion is off\" });\n return;\n }\n\n const blurRadius =\n spec.softness === undefined ? undefined : clamp01(spec.softness) * MAX_BLUR_RADIUS;\n const system = this.#system();\n if (system === undefined) {\n this.#world.registerSystem(DepthSensingSystem, {\n configData: {\n enableOcclusion: true,\n enableDepthTexture: true,\n useFloat32: spec.source?.format !== \"luminance-alpha\",\n ...(blurRadius === undefined ? {} : { blurRadius }),\n },\n });\n } else {\n system.config.enableOcclusion.value = true;\n system.config.useFloat32.value = spec.source?.format !== \"luminance-alpha\";\n if (blurRadius !== undefined) system.config.blurRadius.value = blurRadius;\n }\n\n const mode = occlusionMode(spec.mode);\n this.#releaseOccludables();\n if (spec.scope === \"tagged\") {\n this.#report({\n feature: \"occlusion\",\n state: \"active\",\n detail: \"occluding the entities the app marked with DepthOccludable\",\n });\n return;\n }\n if (this.#occludables === undefined) {\n this.#report({\n feature: \"occlusion\",\n state: \"unavailable\",\n detail:\n \"IWSDK occludes per entity; pass an occludables option, or use scope: tagged and add DepthOccludable yourself\",\n });\n return;\n }\n let count = 0;\n for (const entity of this.#occludables()) {\n if (entity.hasComponent(DepthOccludable)) continue;\n entity.addComponent(DepthOccludable, { mode });\n this.#occluding.push(entity);\n count += 1;\n }\n this.#report({\n feature: \"occlusion\",\n state: \"active\",\n detail: \"occluding \" + String(count) + \" entities\",\n });\n }\n\n /**\n * IWSDK 0.5.3 has no light estimation at all - no probe, no session hook,\n * nothing in its typings. This says so instead of leaving the app to wonder\n * why the room never lights anything, and the request is recorded in\n * docs/UPSTREAM_ENHANCEMENTS.md.\n */\n applyLightEstimation(estimation: ResolvedLightEstimation | null): void {\n if (estimation === null) {\n this.#report({\n feature: \"lightEstimation\",\n state: \"unavailable\",\n detail: \"light estimation is off\",\n });\n return;\n }\n this.#report({\n feature: \"lightEstimation\",\n state: \"unsupported\",\n detail: \"IWSDK 0.5.3 does not expose WebXR light estimation\",\n });\n }\n\n applyFog(fog: FogSpec | null): void {\n const scene = this.#world.scene;\n if (fog === null) {\n scene.fog = null;\n this.#fogKind = null;\n return;\n }\n if (this.#fogKind !== fog.kind || scene.fog === null) {\n scene.fog =\n fog.kind === \"linear\"\n ? new Fog(rgbToHexNumber(fog.colour), fog.near, fog.far)\n : new FogExp2(rgbToHexNumber(fog.colour), fog.density);\n this.#fogKind = fog.kind;\n return;\n }\n const existing = scene.fog;\n existing.color.setHex(rgbToHexNumber(fog.colour));\n if (fog.kind === \"linear\" && existing instanceof Fog) {\n existing.near = fog.near;\n existing.far = fog.far;\n } else if (fog.kind === \"exponential\" && existing instanceof FogExp2) {\n existing.density = fog.density;\n }\n }\n\n applyAmbient(light: AmbientLightSpec | null): void {\n if (light === null) {\n this.#destroy(\"ambient\");\n return;\n }\n const entity = this.#ensure(\"ambient\");\n if (!entity.hasComponent(AmbientLightComponent)) {\n entity.addComponent(AmbientLightComponent);\n }\n writeRgb(entity.getVectorView(AmbientLightComponent, \"color\"), light.colour);\n entity.setValue(AmbientLightComponent, \"intensity\", light.intensity);\n }\n\n applyKeyLight(light: KeyLightSpec | null): void {\n if (light === null) {\n this.#destroy(\"key\");\n return;\n }\n const entity = this.#ensure(\"key\");\n if (!entity.hasComponent(DirectionalLightComponent)) {\n entity.addComponent(DirectionalLightComponent);\n }\n writeRgb(entity.getVectorView(DirectionalLightComponent, \"color\"), light.colour);\n entity.setValue(DirectionalLightComponent, \"intensity\", light.intensity);\n entity.setValue(DirectionalLightComponent, \"castShadow\", light.castShadow ?? false);\n\n // The spec names the direction light TRAVELS; the component emits along\n // the entity's local -Z, so the entity is rotated to face that way. A\n // zero-length direction would produce a NaN quaternion, so it falls back\n // to straight down.\n const [x, y, z] = light.direction;\n if (Math.hypot(x, y, z) === 0) TEMP_DIRECTION.set(0, -1, 0);\n else TEMP_DIRECTION.set(x, y, z).normalize();\n TEMP_QUATERNION.setFromUnitVectors(LIGHT_FORWARD, TEMP_DIRECTION);\n writeQuaternion(entity.getVectorView(Transform, \"orientation\"), TEMP_QUATERNION);\n }\n\n dispose(): void {\n this.applySky(null);\n this.applyFog(null);\n this.applyAmbient(null);\n this.applyKeyLight(null);\n this.applyIbl(null);\n this.#releaseOccludables();\n this.#host = null;\n }\n\n #system() {\n return this.#world.getSystem(DepthSensingSystem);\n }\n\n #releaseOccludables(): void {\n for (const entity of this.#occluding) {\n if (entity.hasComponent(DepthOccludable)) entity.removeComponent(DepthOccludable);\n }\n this.#occluding = [];\n }\n\n #report(report: SensingReport): void {\n this.#host?.report(report);\n }\n\n #levelRoot(): Entity | null {\n return this.#parent ?? this.#world.activeLevel?.value ?? null;\n }\n\n /** The light entities exist independently of the level, so this cannot fail. */\n #ensure(which: \"ambient\" | \"key\"): Entity {\n const existing = which === \"ambient\" ? this.#ambientEntity : this.#keyEntity;\n if (existing !== null) return existing;\n const parent = this.#levelRoot();\n const entity = this.#world.createTransformEntity(\n undefined,\n parent === null ? undefined : { parent },\n );\n if (which === \"ambient\") this.#ambientEntity = entity;\n else this.#keyEntity = entity;\n return entity;\n }\n\n #destroy(which: \"ambient\" | \"key\"): void {\n const entity = which === \"ambient\" ? this.#ambientEntity : this.#keyEntity;\n entity?.destroy();\n if (which === \"ambient\") this.#ambientEntity = null;\n else this.#keyEntity = null;\n }\n}\n\n/**\n * The colour at the horizon: the app's, or the one the ramp implies.\n *\n * IWSDK's dome and IBL components are both three-stop, so this port always has\n * to supply a middle colour. Deriving it from the same ramp the three.js\n * adapter draws is what stops the two engines disagreeing about a sky the app\n * described once.\n */\nfunction equatorOf(gradient: SkyGradient | { top: Rgb; bottom: Rgb; equator?: Rgb }): Rgb {\n if (gradient.equator !== undefined) return gradient.equator;\n const exponent = \"exponent\" in gradient ? (gradient.exponent ?? 1) : 1;\n return lerpRgb(gradient.bottom, gradient.top, Math.pow(0.5, exponent));\n}\n\n/** Our mode names onto IWSDK's shader modes. */\nfunction occlusionMode(mode: OcclusionSpec[\"mode\"]): string {\n if (mode === \"hard\") return OcclusionShadersMode.HardOcclusion;\n if (mode === \"minmax-soft\") return OcclusionShadersMode.MinMaxSoftOcclusion;\n return OcclusionShadersMode.SoftOcclusion;\n}\n\n/** As `writeRgb`, for a `Types.Vec3` that is not a colour. */\nfunction writeVec3(view: NumericView, x: number, y: number, z: number): void {\n view[0] = x;\n view[1] = y;\n view[2] = z;\n}\n\n/** `[r, g, b]` in 0..1 -> a packed 0xRRGGBB, for the three.js-side setters. */\nfunction rgbToHexNumber(rgb: Rgb): number {\n const channel = (value: number) => Math.round(clamp01(value) * 255);\n return (channel(rgb[0]) << 16) | (channel(rgb[1]) << 8) | channel(rgb[2]);\n}\n\n/**\n * Write an RGBA colour into a component's vector view.\n *\n * The VIEW is passed in rather than the component and field name, so every\n * call site keeps elics's own `getVectorView` typing - which checks that the\n * field exists AND that it is an array type. A helper that took the component\n * would have to erase those generics, and the first misspelled field name\n * would then reach a headset instead of the compiler.\n *\n * Alpha is always 1: the specs describe opaque colours. Writing index 3 of a\n * three-component view is a no-op in JavaScript rather than an error, so no\n * length check is needed for a component whose colour is a `Types.Vec3`.\n */\nfunction writeRgb(view: NumericView, rgb: Rgb): void {\n view[0] = rgb[0];\n view[1] = rgb[1];\n view[2] = rgb[2];\n view[3] = 1;\n}\n\n/** As above, for a `Types.Vec4` orientation. */\nfunction writeQuaternion(view: NumericView, quaternion: Quaternion): void {\n view[0] = quaternion.x;\n view[1] = quaternion.y;\n view[2] = quaternion.z;\n view[3] = quaternion.w;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"environment-port.js","sourceRoot":"","sources":["../src/environment-port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `EnvironmentPort` for Meta IWSDK.\n *\n * ---------------------------------------------------------------------------\n * IT USES IWSDK'S OWN MACHINERY, NOT THREE.JS BEHIND ITS BACK\n * ---------------------------------------------------------------------------\n * The sky is a `DomeGradient` on the level root and the lights are\n * `AmbientLightComponent` and `DirectionalLightComponent` on entities.\n * Reaching past IWSDK to write `scene.background` or to `scene.add()` a light\n * would work right up until IWSDK's own `EnvironmentSystem` or `LightSystem`\n * disagreed - and one of the things IWSDK's environment system already does\n * correctly is hide authored backgrounds in an AR session, which is behaviour\n * worth inheriting rather than fighting.\n *\n * No geometry is created here. Every component this port touches is an IWSDK\n * platform facility with no app-side equivalent; a floor would be a mesh, and\n * meshes are the app's.\n *\n * Fog is the exception. IWSDK has no fog component, so it is set on\n * `world.scene` directly, with three.js's own `Fog` / `FogExp2` imported from\n * `@iwsdk/core` (the framework's rule - one three.js instance, reached through\n * the framework's re-export).\n *\n * ---------------------------------------------------------------------------\n * WRITING COMPONENT COLOURS\n * ---------------------------------------------------------------------------\n * A `Types.Color` or `Types.Vec3` field must be written through\n * `getVectorView`; `setValue` on one throws. Every colour write here goes\n * through `writeColour` for that reason - it is not a style choice.\n */\nimport {\n AmbientLightComponent,\n DepthOccludable,\n DepthSensingSystem,\n DirectionalLightComponent,\n DomeGradient,\n DomeTexture,\n IBLGradient,\n IBLTexture,\n OcclusionShadersMode,\n Transform,\n type Entity,\n type World,\n} from \"@iwsdk/core\";\nimport { Fog, FogExp2, Quaternion, Vector3 } from \"three\";\nimport type {\n AmbientLightSpec,\n EnvironmentPort,\n EnvironmentPortHost,\n FogSpec,\n IblSpec,\n KeyLightSpec,\n OcclusionSpec,\n ResolvedLightEstimation,\n Rgb,\n SensingReport,\n SkyGradient,\n SkySpec,\n} from \"@realitycollective/webxr-environment\";\nimport { clamp01, lerpRgb } from \"@realitycollective/webxr-environment\";\n\nexport interface IWSDKEnvironmentPortOptions {\n /**\n * Where the light entities are parented. Defaults to the active level root,\n * which is also where the dome lives, so the whole environment is torn down\n * with the level.\n */\n readonly parent?: Entity;\n /** Dome brightness multiplier, used when a sky does not name its own. Default 1. */\n readonly skyIntensity?: number;\n /**\n * Which entities the real world is allowed to hide, for `scope: \"all\"`.\n *\n * IWSDK opts entities INTO occlusion one at a time, by patching the\n * materials under each one, so somebody has to say which entities those\n * are. It cannot be this port: the entities are content, content is the\n * app's, and walking a scene graph looking for meshes would be this package\n * guessing at the app's structure.\n *\n * With no list, `scope: \"all\"` reports `unavailable` and says why. An app\n * that would rather tag its own entities uses `scope: \"tagged\"` and adds\n * `DepthOccludable` itself; then this port only configures the system.\n */\n readonly occludables?: () => Iterable<Entity>;\n}\n\n/** 0..1 softness onto IWSDK's blur radius in pixels, whose default is 20. */\nconst MAX_BLUR_RADIUS = 40;\n\n/**\n * The narrowest thing a vector view is: elics types it as a union of every\n * typed array, and all these helpers need is indexed writes and a length.\n */\ntype NumericView = { [index: number]: number; readonly length: number };\n\n/** Local -Z is where an IWSDK directional light points. */\nconst LIGHT_FORWARD = new Vector3(0, 0, -1);\nconst TEMP_DIRECTION = new Vector3();\nconst TEMP_QUATERNION = new Quaternion();\n\nexport class IWSDKEnvironmentPort implements EnvironmentPort {\n readonly #world: World;\n readonly #parent: Entity | undefined;\n readonly #skyIntensity: number;\n\n readonly #occludables: (() => Iterable<Entity>) | undefined;\n\n #domeEntity: Entity | null = null;\n #iblEntity: Entity | null = null;\n #ambientEntity: Entity | null = null;\n #keyEntity: Entity | null = null;\n #fogKind: FogSpec[\"kind\"] | null = null;\n #host: EnvironmentPortHost | null = null;\n /** Only what THIS port added, so it never removes the app's own component. */\n #occluding: Entity[] = [];\n\n constructor(world: World, options: IWSDKEnvironmentPortOptions = {}) {\n this.#world = world;\n this.#parent = options.parent;\n this.#skyIntensity = options.skyIntensity ?? 1;\n this.#occludables = options.occludables;\n }\n\n observe(host: EnvironmentPortHost): () => void {\n this.#host = host;\n return () => {\n this.#host = null;\n };\n }\n\n applySky(sky: SkySpec | null): void {\n const root = this.#levelRoot();\n if (root === null) return;\n\n if (sky === null) {\n if (this.#domeEntity !== null && this.#domeEntity.hasComponent(DomeGradient)) {\n this.#domeEntity.removeComponent(DomeGradient);\n }\n this.#domeEntity = null;\n return;\n }\n\n if (sky.kind === \"texture\") {\n // An authored sky is a different IWSDK component, so the dome one goes\n // rather than sitting underneath and fighting over the same background.\n if (root.hasComponent(DomeGradient)) root.removeComponent(DomeGradient);\n if (!root.hasComponent(DomeTexture)) root.addComponent(DomeTexture);\n this.#domeEntity = root;\n root.setValue(DomeTexture, \"src\", sky.src);\n root.setValue(DomeTexture, \"intensity\", sky.intensity ?? this.#skyIntensity);\n root.setValue(DomeTexture, \"blurriness\", sky.blur ?? 0);\n writeVec3(root.getVectorView(DomeTexture, \"rotation\"), 0, sky.rotationY ?? 0, 0);\n root.setValue(DomeTexture, \"_needsUpdate\", true);\n return;\n }\n\n if (root.hasComponent(DomeTexture)) root.removeComponent(DomeTexture);\n if (this.#domeEntity !== root || !root.hasComponent(DomeGradient)) {\n if (!root.hasComponent(DomeGradient)) root.addComponent(DomeGradient);\n this.#domeEntity = root;\n }\n\n // IWSDK's dome is a Unity-style sky / equator / ground triple. A solid sky\n // is all three the same. A gradient uses the horizon colour the app gave,\n // and derives one from the ramp when it did not - which is the same colour\n // the three.js adapter puts at the horizon, so the two engines agree there\n // rather than only at the poles.\n if (sky.kind === \"solid\") {\n writeRgb(root.getVectorView(DomeGradient, \"sky\"), sky.colour);\n writeRgb(root.getVectorView(DomeGradient, \"equator\"), sky.colour);\n writeRgb(root.getVectorView(DomeGradient, \"ground\"), sky.colour);\n root.setValue(DomeGradient, \"intensity\", this.#skyIntensity);\n } else {\n writeRgb(root.getVectorView(DomeGradient, \"sky\"), sky.top);\n writeRgb(root.getVectorView(DomeGradient, \"equator\"), equatorOf(sky));\n writeRgb(root.getVectorView(DomeGradient, \"ground\"), sky.bottom);\n root.setValue(DomeGradient, \"intensity\", sky.intensity ?? this.#skyIntensity);\n }\n root.setValue(DomeGradient, \"_needsUpdate\", true);\n }\n\n /**\n * The environment map, as IWSDK's own image-based lighting components.\n *\n * `room` is not an approximation here: IWSDK's `IBLTexture` takes the string\n * `\"room\"` for its built-in probe, so the one kind three.js has to fake is\n * the one kind this host has natively.\n */\n applyIbl(ibl: IblSpec | null): void {\n const root = this.#levelRoot();\n if (root === null) return;\n\n if (ibl === null) {\n if (this.#iblEntity !== null) {\n if (this.#iblEntity.hasComponent(IBLGradient)) this.#iblEntity.removeComponent(IBLGradient);\n if (this.#iblEntity.hasComponent(IBLTexture)) this.#iblEntity.removeComponent(IBLTexture);\n }\n this.#iblEntity = null;\n return;\n }\n this.#iblEntity = root;\n\n if (ibl.kind === \"estimated\") {\n // IWSDK measures no reflections (UPSTREAM_ENHANCEMENTS 6.1), so the slot\n // keeps whatever it had rather than being cleared: an app that asked for\n // measured reflections and got none should not also lose its own map.\n this.#report({\n feature: \"lightEstimation\",\n state: \"unsupported\",\n detail: \"IWSDK measures no reflections, so an estimated environment map cannot be applied\",\n });\n return;\n }\n\n if (ibl.kind === \"gradient\") {\n if (root.hasComponent(IBLTexture)) root.removeComponent(IBLTexture);\n if (!root.hasComponent(IBLGradient)) root.addComponent(IBLGradient);\n writeRgb(root.getVectorView(IBLGradient, \"sky\"), ibl.top);\n writeRgb(root.getVectorView(IBLGradient, \"equator\"), equatorOf(ibl));\n writeRgb(root.getVectorView(IBLGradient, \"ground\"), ibl.bottom);\n root.setValue(IBLGradient, \"intensity\", ibl.intensity ?? 1);\n root.setValue(IBLGradient, \"_needsUpdate\", true);\n return;\n }\n\n if (root.hasComponent(IBLGradient)) root.removeComponent(IBLGradient);\n if (!root.hasComponent(IBLTexture)) root.addComponent(IBLTexture);\n root.setValue(IBLTexture, \"src\", ibl.kind === \"room\" ? \"room\" : ibl.src);\n root.setValue(IBLTexture, \"intensity\", ibl.intensity ?? 1);\n writeVec3(root.getVectorView(IBLTexture, \"rotation\"), 0, ibl.rotationY ?? 0, 0);\n root.setValue(IBLTexture, \"_needsUpdate\", true);\n }\n\n /**\n * Depth occlusion, through IWSDK's `DepthSensingSystem` and the per-entity\n * `DepthOccludable` component.\n *\n * IWSDK patches the materials under each opted-in entity, which is why the\n * scope matters more here than on three.js: there is no global mode to turn\n * on, and an entity nobody opted in is an entity the real world will not\n * hide. Whatever this port adds, it remembers, so turning occlusion off\n * never strips a component the app put there itself.\n */\n applyOcclusion(spec: OcclusionSpec | null): void {\n if (spec === null) {\n this.#releaseOccludables();\n const running = this.#system();\n if (running !== undefined) running.config.enableOcclusion.value = false;\n this.#report({ feature: \"occlusion\", state: \"unavailable\", detail: \"occlusion is off\" });\n return;\n }\n\n const blurRadius =\n spec.softness === undefined ? undefined : clamp01(spec.softness) * MAX_BLUR_RADIUS;\n const system = this.#system();\n if (system === undefined) {\n this.#world.registerSystem(DepthSensingSystem, {\n configData: {\n enableOcclusion: true,\n enableDepthTexture: true,\n useFloat32: spec.source?.format !== \"luminance-alpha\",\n ...(blurRadius === undefined ? {} : { blurRadius }),\n },\n });\n } else {\n system.config.enableOcclusion.value = true;\n system.config.useFloat32.value = spec.source?.format !== \"luminance-alpha\";\n if (blurRadius !== undefined) system.config.blurRadius.value = blurRadius;\n }\n\n const mode = occlusionMode(spec.mode);\n this.#releaseOccludables();\n if (spec.scope === \"tagged\") {\n this.#report({\n feature: \"occlusion\",\n state: \"active\",\n detail: \"occluding the entities the app marked with DepthOccludable\",\n });\n return;\n }\n if (this.#occludables === undefined) {\n this.#report({\n feature: \"occlusion\",\n state: \"unavailable\",\n detail:\n \"IWSDK occludes per entity; pass an occludables option, or use scope: tagged and add DepthOccludable yourself\",\n });\n return;\n }\n let count = 0;\n for (const entity of this.#occludables()) {\n if (entity.hasComponent(DepthOccludable)) continue;\n entity.addComponent(DepthOccludable, { mode });\n this.#occluding.push(entity);\n count += 1;\n }\n this.#report({\n feature: \"occlusion\",\n state: \"active\",\n detail: \"occluding \" + String(count) + \" entities\",\n });\n }\n\n /**\n * IWSDK 0.5.3 has no light estimation at all - no probe, no session hook,\n * nothing in its typings. This says so instead of leaving the app to wonder\n * why the room never lights anything, and the request is recorded in\n * docs/UPSTREAM_ENHANCEMENTS.md.\n */\n applyLightEstimation(estimation: ResolvedLightEstimation | null): void {\n if (estimation === null) {\n this.#report({\n feature: \"lightEstimation\",\n state: \"unavailable\",\n detail: \"light estimation is off\",\n });\n return;\n }\n this.#report({\n feature: \"lightEstimation\",\n state: \"unsupported\",\n detail: \"IWSDK 0.5.3 does not expose WebXR light estimation\",\n });\n }\n\n applyFog(fog: FogSpec | null): void {\n const scene = this.#world.scene;\n if (fog === null) {\n scene.fog = null;\n this.#fogKind = null;\n return;\n }\n if (this.#fogKind !== fog.kind || scene.fog === null) {\n scene.fog =\n fog.kind === \"linear\"\n ? new Fog(rgbToHexNumber(fog.colour), fog.near, fog.far)\n : new FogExp2(rgbToHexNumber(fog.colour), fog.density);\n this.#fogKind = fog.kind;\n return;\n }\n const existing = scene.fog;\n existing.color.setHex(rgbToHexNumber(fog.colour));\n if (fog.kind === \"linear\" && existing instanceof Fog) {\n existing.near = fog.near;\n existing.far = fog.far;\n } else if (fog.kind === \"exponential\" && existing instanceof FogExp2) {\n existing.density = fog.density;\n }\n }\n\n applyAmbient(light: AmbientLightSpec | null): void {\n if (light === null) {\n this.#destroy(\"ambient\");\n return;\n }\n const entity = this.#ensure(\"ambient\");\n if (!entity.hasComponent(AmbientLightComponent)) {\n entity.addComponent(AmbientLightComponent);\n }\n writeRgb(entity.getVectorView(AmbientLightComponent, \"color\"), light.colour);\n entity.setValue(AmbientLightComponent, \"intensity\", light.intensity);\n }\n\n applyKeyLight(light: KeyLightSpec | null): void {\n if (light === null) {\n this.#destroy(\"key\");\n return;\n }\n const entity = this.#ensure(\"key\");\n if (!entity.hasComponent(DirectionalLightComponent)) {\n entity.addComponent(DirectionalLightComponent);\n }\n writeRgb(entity.getVectorView(DirectionalLightComponent, \"color\"), light.colour);\n entity.setValue(DirectionalLightComponent, \"intensity\", light.intensity);\n entity.setValue(DirectionalLightComponent, \"castShadow\", light.castShadow ?? false);\n\n // The spec names the direction light TRAVELS; the component emits along\n // the entity's local -Z, so the entity is rotated to face that way. A\n // zero-length direction would produce a NaN quaternion, so it falls back\n // to straight down.\n const [x, y, z] = light.direction;\n if (Math.hypot(x, y, z) === 0) TEMP_DIRECTION.set(0, -1, 0);\n else TEMP_DIRECTION.set(x, y, z).normalize();\n TEMP_QUATERNION.setFromUnitVectors(LIGHT_FORWARD, TEMP_DIRECTION);\n writeQuaternion(entity.getVectorView(Transform, \"orientation\"), TEMP_QUATERNION);\n }\n\n dispose(): void {\n this.applySky(null);\n this.applyFog(null);\n this.applyAmbient(null);\n this.applyKeyLight(null);\n this.applyIbl(null);\n this.#releaseOccludables();\n this.#host = null;\n }\n\n #system() {\n return this.#world.getSystem(DepthSensingSystem);\n }\n\n #releaseOccludables(): void {\n for (const entity of this.#occluding) {\n if (entity.hasComponent(DepthOccludable)) entity.removeComponent(DepthOccludable);\n }\n this.#occluding = [];\n }\n\n #report(report: SensingReport): void {\n this.#host?.report(report);\n }\n\n #levelRoot(): Entity | null {\n return this.#parent ?? this.#world.activeLevel?.value ?? null;\n }\n\n /** The light entities exist independently of the level, so this cannot fail. */\n #ensure(which: \"ambient\" | \"key\"): Entity {\n const existing = which === \"ambient\" ? this.#ambientEntity : this.#keyEntity;\n if (existing !== null) return existing;\n const parent = this.#levelRoot();\n const entity = this.#world.createTransformEntity(\n undefined,\n parent === null ? undefined : { parent },\n );\n if (which === \"ambient\") this.#ambientEntity = entity;\n else this.#keyEntity = entity;\n return entity;\n }\n\n #destroy(which: \"ambient\" | \"key\"): void {\n const entity = which === \"ambient\" ? this.#ambientEntity : this.#keyEntity;\n entity?.destroy();\n if (which === \"ambient\") this.#ambientEntity = null;\n else this.#keyEntity = null;\n }\n}\n\n/**\n * The colour at the horizon: the app's, or the one the ramp implies.\n *\n * IWSDK's dome and IBL components are both three-stop, so this port always has\n * to supply a middle colour. Deriving it from the same ramp the three.js\n * adapter draws is what stops the two engines disagreeing about a sky the app\n * described once.\n */\nfunction equatorOf(gradient: SkyGradient | { top: Rgb; bottom: Rgb; equator?: Rgb }): Rgb {\n if (gradient.equator !== undefined) return gradient.equator;\n const exponent = \"exponent\" in gradient ? (gradient.exponent ?? 1) : 1;\n return lerpRgb(gradient.bottom, gradient.top, Math.pow(0.5, exponent));\n}\n\n/** Our mode names onto IWSDK's shader modes. */\nfunction occlusionMode(mode: OcclusionSpec[\"mode\"]): string {\n if (mode === \"hard\") return OcclusionShadersMode.HardOcclusion;\n if (mode === \"minmax-soft\") return OcclusionShadersMode.MinMaxSoftOcclusion;\n return OcclusionShadersMode.SoftOcclusion;\n}\n\n/** As `writeRgb`, for a `Types.Vec3` that is not a colour. */\nfunction writeVec3(view: NumericView, x: number, y: number, z: number): void {\n view[0] = x;\n view[1] = y;\n view[2] = z;\n}\n\n/** `[r, g, b]` in 0..1 -> a packed 0xRRGGBB, for the three.js-side setters. */\nfunction rgbToHexNumber(rgb: Rgb): number {\n const channel = (value: number) => Math.round(clamp01(value) * 255);\n return (channel(rgb[0]) << 16) | (channel(rgb[1]) << 8) | channel(rgb[2]);\n}\n\n/**\n * Write an RGBA colour into a component's vector view.\n *\n * The VIEW is passed in rather than the component and field name, so every\n * call site keeps elics's own `getVectorView` typing - which checks that the\n * field exists AND that it is an array type. A helper that took the component\n * would have to erase those generics, and the first misspelled field name\n * would then reach a headset instead of the compiler.\n *\n * Alpha is always 1: the specs describe opaque colours. Writing index 3 of a\n * three-component view is a no-op in JavaScript rather than an error, so no\n * length check is needed for a component whose colour is a `Types.Vec3`.\n */\nfunction writeRgb(view: NumericView, rgb: Rgb): void {\n view[0] = rgb[0];\n view[1] = rgb[1];\n view[2] = rgb[2];\n view[3] = 1;\n}\n\n/** As above, for a `Types.Vec4` orientation. */\nfunction writeQuaternion(view: NumericView, quaternion: Quaternion): void {\n view[0] = quaternion.x;\n view[1] = quaternion.y;\n view[2] = quaternion.z;\n view[3] = quaternion.w;\n}\n"]}
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
* for them, the queries stay empty forever - so this port says `pending` and
|
|
25
25
|
* keeps saying it, rather than pretending to have turned something on.
|
|
26
26
|
*/
|
|
27
|
-
import { EnvironmentRaycastSystem, EnvironmentRaycastTarget,
|
|
27
|
+
import { EnvironmentRaycastSystem, EnvironmentRaycastTarget, RaycastSpace, XRAnchor, XRMesh, XRPlane, } from "@iwsdk/core";
|
|
28
|
+
import { Quaternion, Vector3 } from "three";
|
|
28
29
|
const TEMP_POSITION = new Vector3();
|
|
29
30
|
const TEMP_QUATERNION = new Quaternion();
|
|
30
31
|
export class IWSDKWorldSensingPort {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"world-sensing-port.js","sourceRoot":"","sources":["../src/world-sensing-port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `WorldSensingPort` for Meta IWSDK.\n *\n * ---------------------------------------------------------------------------\n * IWSDK HAS ALREADY DONE HALF OF THIS\n * ---------------------------------------------------------------------------\n * Where the three.js adapter reads an `XRFrame` directly, IWSDK's own\n * `SceneUnderstandingSystem` has already turned planes, meshes and anchors\n * into ENTITIES with components on them, positioned in the scene. So this port\n * queries for those entities and translates them, rather than reaching past\n * IWSDK to the session - which would fight the system that owns them.\n *\n * The same goes for hit testing: IWSDK's `EnvironmentRaycastSystem` casts from\n * a hand or the viewer and moves a target entity to the hit, so a request here\n * becomes an entity with an `EnvironmentRaycastTarget` on it and the answer is\n * read off that entity's transform.\n *\n * ---------------------------------------------------------------------------\n * WHAT IT CANNOT DO\n * ---------------------------------------------------------------------------\n * Ask for the features. `plane-detection`, `mesh-detection` and `anchors` are\n * session features, IWSDK requests them from its own world configuration, and\n * the session belongs to the platform layer either way. If the app did not ask\n * for them, the queries stay empty forever - so this port says `pending` and\n * keeps saying it, rather than pretending to have turned something on.\n */\nimport {\n EnvironmentRaycastSystem,\n EnvironmentRaycastTarget,\n Quaternion,\n RaycastSpace,\n Vector3,\n XRAnchor,\n XRMesh,\n XRPlane,\n type Entity,\n type World,\n} from \"@iwsdk/core\";\nimport type {\n HitTestRequest,\n ResolvedWorldDetection,\n SensingFeature,\n SensingReport,\n WorldAnchor,\n WorldHit,\n WorldMesh,\n WorldPlane,\n WorldPlaneOrientation,\n WorldPose,\n WorldSensingPort,\n WorldSensingPortHost,\n} from \"@realitycollective/webxr-environment\";\n\n/** The raw `XRPlane` IWSDK keeps on the component, as far as we read it. */\ninterface RawPlane {\n readonly polygon?: ArrayLike<{ readonly x: number; readonly z: number }>;\n readonly orientation?: string;\n readonly semanticLabel?: string;\n readonly lastChangedTime?: number;\n}\n\n/** One elics query, of which this port uses only the entity set. */\ninterface QueryLike {\n readonly entities: Iterable<Entity>;\n}\n\ninterface QueryManagerLike {\n registerQuery(config: { required: unknown[] }): QueryLike;\n}\n\nexport interface IWSDKWorldSensingPortOptions {\n /** Where hit-test target entities are parented. Default: no parent. */\n readonly parent?: Entity;\n}\n\nconst TEMP_POSITION = new Vector3();\nconst TEMP_QUATERNION = new Quaternion();\n\nexport class IWSDKWorldSensingPort implements WorldSensingPort {\n readonly #world: World;\n readonly #parent: Entity | undefined;\n readonly #ids = new WeakMap<object, string>();\n readonly #hitEntities = new Map<string, Entity>();\n readonly #anchorEntities = new Map<string, Entity>();\n readonly #states = new Map<SensingFeature, string>();\n\n /**\n * The three queries, registered once at construction.\n *\n * elics keeps one query per component mask and updates it as entities gain\n * and lose components, so registering up front costs one mask walk each and\n * removes any question of whether a set exists yet. An app that never turns\n * detection on simply never reads them.\n */\n readonly #planeQuery: QueryLike;\n readonly #meshQuery: QueryLike;\n readonly #anchorQuery: QueryLike;\n\n #host: WorldSensingPortHost | null = null;\n #detection: ResolvedWorldDetection | null = null;\n #nextId = 1;\n\n constructor(world: World, options: IWSDKWorldSensingPortOptions = {}) {\n this.#world = world;\n this.#parent = options.parent;\n const manager = (world as unknown as { queryManager: QueryManagerLike }).queryManager;\n this.#planeQuery = manager.registerQuery({ required: [XRPlane] });\n this.#meshQuery = manager.registerQuery({ required: [XRMesh] });\n this.#anchorQuery = manager.registerQuery({ required: [XRAnchor] });\n }\n\n observe(host: WorldSensingPortHost): () => void {\n this.#host = host;\n return () => {\n this.#host = null;\n };\n }\n\n setDetection(detection: ResolvedWorldDetection | null): void {\n this.#detection = detection;\n if (detection === null) {\n this.#host?.planes([]);\n this.#host?.meshes([]);\n this.#host?.anchors([]);\n for (const feature of [\"planes\", \"meshes\", \"anchors\"] as const) {\n this.#report({ feature, state: \"unavailable\", detail: \"detection is off\" });\n }\n return;\n }\n for (const feature of [\"planes\", \"meshes\", \"anchors\"] as const) {\n this.#report(\n detection[feature]\n ? {\n feature,\n state: \"pending\",\n detail: \"waiting for IWSDK's scene understanding to find something\",\n }\n : { feature, state: \"unavailable\", detail: \"detection is off\" },\n );\n }\n }\n\n startHitTest(request: HitTestRequest): void {\n this.#world.registerSystem(EnvironmentRaycastSystem);\n const entity = this.#world.createTransformEntity(\n undefined,\n this.#parent === undefined ? undefined : { parent: this.#parent },\n );\n entity.addComponent(EnvironmentRaycastTarget, { space: raycastSpace(request.space) });\n this.#hitEntities.set(request.id, entity);\n this.#report({\n feature: \"hitTest\",\n state: \"pending\",\n detail: \"waiting for a hit from the \" + request.space + \" ray\",\n });\n }\n\n stopHitTest(id: string): void {\n const entity = this.#hitEntities.get(id);\n if (entity === undefined) return;\n this.#hitEntities.delete(id);\n entity.destroy();\n }\n\n /**\n * IWSDK anchors an ENTITY rather than handing back an anchor object, so this\n * makes one at the requested pose and lets `SceneUnderstandingSystem` attach\n * it. The id that comes back is the same id the anchor will report with.\n */\n async createAnchor(pose: WorldPose): Promise<string | null> {\n const entity = this.#world.createTransformEntity(\n undefined,\n this.#parent === undefined ? undefined : { parent: this.#parent },\n );\n const object3D = entity.object3D;\n if (object3D === undefined) {\n entity.destroy();\n this.#report({\n feature: \"anchors\",\n state: \"unavailable\",\n detail: \"the anchor entity has no transform to place\",\n });\n return null;\n }\n object3D.position.set(pose.position[0], pose.position[1], pose.position[2]);\n object3D.quaternion.set(\n pose.orientation[0],\n pose.orientation[1],\n pose.orientation[2],\n pose.orientation[3],\n );\n object3D.updateMatrixWorld();\n entity.addComponent(XRAnchor);\n const id = this.#idFor(entity as unknown as object);\n this.#anchorEntities.set(id, entity);\n return id;\n }\n\n removeAnchor(id: string): void {\n const entity = this.#anchorEntities.get(id);\n if (entity === undefined) return;\n this.#anchorEntities.delete(id);\n entity.destroy();\n }\n\n update(): void {\n const detection = this.#detection;\n if (detection === null || this.#host === null) return;\n if (detection.planes) this.#readPlanes();\n if (detection.meshes) this.#readMeshes();\n if (detection.anchors) this.#readAnchors();\n this.#readHits();\n }\n\n dispose(): void {\n for (const entity of this.#hitEntities.values()) entity.destroy();\n this.#hitEntities.clear();\n this.#anchorEntities.clear();\n this.#host = null;\n }\n\n #readPlanes(): void {\n const planes: WorldPlane[] = [];\n for (const entity of this.#planeQuery.entities) {\n const pose = poseOf(entity);\n if (pose === null) continue;\n const raw = entity.getValue(XRPlane, \"_plane\") as RawPlane | undefined;\n const polygon = (raw?.polygon === undefined ? [] : Array.from(raw.polygon)).map(\n (point) => [point.x, point.z] as const,\n );\n planes.push({\n id: this.#idFor(entity as unknown as object),\n pose,\n extents: extentsOf(polygon),\n orientation: orientationOf(raw?.orientation),\n label: raw?.semanticLabel?.toLowerCase() ?? null,\n ...(polygon.length === 0 ? {} : { polygon }),\n ...(raw?.lastChangedTime === undefined ? {} : { changedAt: raw.lastChangedTime }),\n });\n }\n this.#host?.planes(planes);\n this.#report({ feature: \"planes\", state: \"active\", detail: planes.length + \" surfaces\" });\n }\n\n #readMeshes(): void {\n const meshes: WorldMesh[] = [];\n for (const entity of this.#meshQuery.entities) {\n const pose = poseOf(entity);\n if (pose === null) continue;\n // IWSDK measures the mesh for us and puts the size on the component, so\n // unlike the raw WebXR path there are no vertices to walk here.\n const dimensions = entity.getVectorView(XRMesh, \"dimensions\");\n const label = entity.getValue(XRMesh, \"semanticLabel\");\n meshes.push({\n id: this.#idFor(entity as unknown as object),\n pose,\n // A `Types.Vec3` view always has three components; the assertions are\n // there because `noUncheckedIndexedAccess` cannot know that, and a\n // fallback would be a branch no input can reach.\n extents: [dimensions[0] as number, dimensions[1] as number, dimensions[2] as number],\n label: typeof label === \"string\" && label.length > 0 ? label.toLowerCase() : null,\n });\n }\n this.#host?.meshes(meshes);\n this.#report({ feature: \"meshes\", state: \"active\", detail: meshes.length + \" meshes\" });\n }\n\n #readAnchors(): void {\n const anchors: WorldAnchor[] = [];\n for (const entity of this.#anchorQuery.entities) {\n const pose = poseOf(entity);\n if (pose === null) continue;\n anchors.push({\n id: this.#idFor(entity as unknown as object),\n pose,\n // IWSDK's own flag: false until the system has attached the entity to\n // a real anchor, which is exactly what \"not tracked yet\" means here.\n tracked: entity.getValue(XRAnchor, \"attached\") === true,\n });\n }\n this.#host?.anchors(anchors);\n this.#report({ feature: \"anchors\", state: \"active\", detail: anchors.length + \" anchors\" });\n }\n\n #readHits(): void {\n for (const [id, entity] of this.#hitEntities) {\n const result = entity.getValue(EnvironmentRaycastTarget, \"xrHitTestResult\");\n const pose = poseOf(entity);\n const hits: WorldHit[] =\n result === undefined || result === null || pose === null\n ? []\n : [{ sourceId: id, pose, distance: null }];\n this.#host?.hits(id, hits);\n if (hits.length > 0) {\n this.#report({ feature: \"hitTest\", state: \"active\", detail: \"hitting the room\" });\n }\n }\n }\n\n #idFor(object: object): string {\n const existing = this.#ids.get(object);\n if (existing !== undefined) return existing;\n const id = \"world-\" + String(this.#nextId);\n this.#nextId += 1;\n this.#ids.set(object, id);\n return id;\n }\n\n #report(report: SensingReport): void {\n const stamp = report.state + \"|\" + report.detail;\n if (this.#states.get(report.feature) === stamp) return;\n this.#states.set(report.feature, stamp);\n this.#host?.report(report);\n }\n}\n\n/** The world transform of the entity IWSDK positioned for us. */\nfunction poseOf(entity: Entity): WorldPose | null {\n const object3D = entity.object3D;\n if (object3D === undefined) return null;\n object3D.getWorldPosition(TEMP_POSITION);\n object3D.getWorldQuaternion(TEMP_QUATERNION);\n return {\n position: [TEMP_POSITION.x, TEMP_POSITION.y, TEMP_POSITION.z],\n orientation: [TEMP_QUATERNION.x, TEMP_QUATERNION.y, TEMP_QUATERNION.z, TEMP_QUATERNION.w],\n };\n}\n\nfunction orientationOf(value: string | undefined): WorldPlaneOrientation {\n const lowered = value?.toLowerCase();\n if (lowered === \"horizontal\" || lowered === \"vertical\") return lowered;\n return \"unknown\";\n}\n\nfunction extentsOf(polygon: readonly (readonly [number, number])[]): readonly [number, number] {\n if (polygon.length === 0) return [0, 0];\n let minX = Infinity;\n let maxX = -Infinity;\n let minZ = Infinity;\n let maxZ = -Infinity;\n for (const [x, z] of polygon) {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n minZ = Math.min(minZ, z);\n maxZ = Math.max(maxZ, z);\n }\n return [maxX - minX, maxZ - minZ];\n}\n\n/** Our three ray sources onto IWSDK's four. */\nfunction raycastSpace(space: HitTestRequest[\"space\"]): string {\n if (space === \"left\") return RaycastSpace.Left;\n if (space === \"right\") return RaycastSpace.Right;\n return RaycastSpace.Viewer;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"world-sensing-port.js","sourceRoot":"","sources":["../src/world-sensing-port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `WorldSensingPort` for Meta IWSDK.\n *\n * ---------------------------------------------------------------------------\n * IWSDK HAS ALREADY DONE HALF OF THIS\n * ---------------------------------------------------------------------------\n * Where the three.js adapter reads an `XRFrame` directly, IWSDK's own\n * `SceneUnderstandingSystem` has already turned planes, meshes and anchors\n * into ENTITIES with components on them, positioned in the scene. So this port\n * queries for those entities and translates them, rather than reaching past\n * IWSDK to the session - which would fight the system that owns them.\n *\n * The same goes for hit testing: IWSDK's `EnvironmentRaycastSystem` casts from\n * a hand or the viewer and moves a target entity to the hit, so a request here\n * becomes an entity with an `EnvironmentRaycastTarget` on it and the answer is\n * read off that entity's transform.\n *\n * ---------------------------------------------------------------------------\n * WHAT IT CANNOT DO\n * ---------------------------------------------------------------------------\n * Ask for the features. `plane-detection`, `mesh-detection` and `anchors` are\n * session features, IWSDK requests them from its own world configuration, and\n * the session belongs to the platform layer either way. If the app did not ask\n * for them, the queries stay empty forever - so this port says `pending` and\n * keeps saying it, rather than pretending to have turned something on.\n */\nimport {\n EnvironmentRaycastSystem,\n EnvironmentRaycastTarget,\n RaycastSpace,\n XRAnchor,\n XRMesh,\n XRPlane,\n type Entity,\n type World,\n} from \"@iwsdk/core\";\nimport { Quaternion, Vector3 } from \"three\";\nimport type {\n HitTestRequest,\n ResolvedWorldDetection,\n SensingFeature,\n SensingReport,\n WorldAnchor,\n WorldHit,\n WorldMesh,\n WorldPlane,\n WorldPlaneOrientation,\n WorldPose,\n WorldSensingPort,\n WorldSensingPortHost,\n} from \"@realitycollective/webxr-environment\";\n\n/** The raw `XRPlane` IWSDK keeps on the component, as far as we read it. */\ninterface RawPlane {\n readonly polygon?: ArrayLike<{ readonly x: number; readonly z: number }>;\n readonly orientation?: string;\n readonly semanticLabel?: string;\n readonly lastChangedTime?: number;\n}\n\n/** One elics query, of which this port uses only the entity set. */\ninterface QueryLike {\n readonly entities: Iterable<Entity>;\n}\n\ninterface QueryManagerLike {\n registerQuery(config: { required: unknown[] }): QueryLike;\n}\n\nexport interface IWSDKWorldSensingPortOptions {\n /** Where hit-test target entities are parented. Default: no parent. */\n readonly parent?: Entity;\n}\n\nconst TEMP_POSITION = new Vector3();\nconst TEMP_QUATERNION = new Quaternion();\n\nexport class IWSDKWorldSensingPort implements WorldSensingPort {\n readonly #world: World;\n readonly #parent: Entity | undefined;\n readonly #ids = new WeakMap<object, string>();\n readonly #hitEntities = new Map<string, Entity>();\n readonly #anchorEntities = new Map<string, Entity>();\n readonly #states = new Map<SensingFeature, string>();\n\n /**\n * The three queries, registered once at construction.\n *\n * elics keeps one query per component mask and updates it as entities gain\n * and lose components, so registering up front costs one mask walk each and\n * removes any question of whether a set exists yet. An app that never turns\n * detection on simply never reads them.\n */\n readonly #planeQuery: QueryLike;\n readonly #meshQuery: QueryLike;\n readonly #anchorQuery: QueryLike;\n\n #host: WorldSensingPortHost | null = null;\n #detection: ResolvedWorldDetection | null = null;\n #nextId = 1;\n\n constructor(world: World, options: IWSDKWorldSensingPortOptions = {}) {\n this.#world = world;\n this.#parent = options.parent;\n const manager = (world as unknown as { queryManager: QueryManagerLike }).queryManager;\n this.#planeQuery = manager.registerQuery({ required: [XRPlane] });\n this.#meshQuery = manager.registerQuery({ required: [XRMesh] });\n this.#anchorQuery = manager.registerQuery({ required: [XRAnchor] });\n }\n\n observe(host: WorldSensingPortHost): () => void {\n this.#host = host;\n return () => {\n this.#host = null;\n };\n }\n\n setDetection(detection: ResolvedWorldDetection | null): void {\n this.#detection = detection;\n if (detection === null) {\n this.#host?.planes([]);\n this.#host?.meshes([]);\n this.#host?.anchors([]);\n for (const feature of [\"planes\", \"meshes\", \"anchors\"] as const) {\n this.#report({ feature, state: \"unavailable\", detail: \"detection is off\" });\n }\n return;\n }\n for (const feature of [\"planes\", \"meshes\", \"anchors\"] as const) {\n this.#report(\n detection[feature]\n ? {\n feature,\n state: \"pending\",\n detail: \"waiting for IWSDK's scene understanding to find something\",\n }\n : { feature, state: \"unavailable\", detail: \"detection is off\" },\n );\n }\n }\n\n startHitTest(request: HitTestRequest): void {\n this.#world.registerSystem(EnvironmentRaycastSystem);\n const entity = this.#world.createTransformEntity(\n undefined,\n this.#parent === undefined ? undefined : { parent: this.#parent },\n );\n entity.addComponent(EnvironmentRaycastTarget, { space: raycastSpace(request.space) });\n this.#hitEntities.set(request.id, entity);\n this.#report({\n feature: \"hitTest\",\n state: \"pending\",\n detail: \"waiting for a hit from the \" + request.space + \" ray\",\n });\n }\n\n stopHitTest(id: string): void {\n const entity = this.#hitEntities.get(id);\n if (entity === undefined) return;\n this.#hitEntities.delete(id);\n entity.destroy();\n }\n\n /**\n * IWSDK anchors an ENTITY rather than handing back an anchor object, so this\n * makes one at the requested pose and lets `SceneUnderstandingSystem` attach\n * it. The id that comes back is the same id the anchor will report with.\n */\n async createAnchor(pose: WorldPose): Promise<string | null> {\n const entity = this.#world.createTransformEntity(\n undefined,\n this.#parent === undefined ? undefined : { parent: this.#parent },\n );\n const object3D = entity.object3D;\n if (object3D === undefined) {\n entity.destroy();\n this.#report({\n feature: \"anchors\",\n state: \"unavailable\",\n detail: \"the anchor entity has no transform to place\",\n });\n return null;\n }\n object3D.position.set(pose.position[0], pose.position[1], pose.position[2]);\n object3D.quaternion.set(\n pose.orientation[0],\n pose.orientation[1],\n pose.orientation[2],\n pose.orientation[3],\n );\n object3D.updateMatrixWorld();\n entity.addComponent(XRAnchor);\n const id = this.#idFor(entity as unknown as object);\n this.#anchorEntities.set(id, entity);\n return id;\n }\n\n removeAnchor(id: string): void {\n const entity = this.#anchorEntities.get(id);\n if (entity === undefined) return;\n this.#anchorEntities.delete(id);\n entity.destroy();\n }\n\n update(): void {\n const detection = this.#detection;\n if (detection === null || this.#host === null) return;\n if (detection.planes) this.#readPlanes();\n if (detection.meshes) this.#readMeshes();\n if (detection.anchors) this.#readAnchors();\n this.#readHits();\n }\n\n dispose(): void {\n for (const entity of this.#hitEntities.values()) entity.destroy();\n this.#hitEntities.clear();\n this.#anchorEntities.clear();\n this.#host = null;\n }\n\n #readPlanes(): void {\n const planes: WorldPlane[] = [];\n for (const entity of this.#planeQuery.entities) {\n const pose = poseOf(entity);\n if (pose === null) continue;\n const raw = entity.getValue(XRPlane, \"_plane\") as RawPlane | undefined;\n const polygon = (raw?.polygon === undefined ? [] : Array.from(raw.polygon)).map(\n (point) => [point.x, point.z] as const,\n );\n planes.push({\n id: this.#idFor(entity as unknown as object),\n pose,\n extents: extentsOf(polygon),\n orientation: orientationOf(raw?.orientation),\n label: raw?.semanticLabel?.toLowerCase() ?? null,\n ...(polygon.length === 0 ? {} : { polygon }),\n ...(raw?.lastChangedTime === undefined ? {} : { changedAt: raw.lastChangedTime }),\n });\n }\n this.#host?.planes(planes);\n this.#report({ feature: \"planes\", state: \"active\", detail: planes.length + \" surfaces\" });\n }\n\n #readMeshes(): void {\n const meshes: WorldMesh[] = [];\n for (const entity of this.#meshQuery.entities) {\n const pose = poseOf(entity);\n if (pose === null) continue;\n // IWSDK measures the mesh for us and puts the size on the component, so\n // unlike the raw WebXR path there are no vertices to walk here.\n const dimensions = entity.getVectorView(XRMesh, \"dimensions\");\n const label = entity.getValue(XRMesh, \"semanticLabel\");\n meshes.push({\n id: this.#idFor(entity as unknown as object),\n pose,\n // A `Types.Vec3` view always has three components; the assertions are\n // there because `noUncheckedIndexedAccess` cannot know that, and a\n // fallback would be a branch no input can reach.\n extents: [dimensions[0] as number, dimensions[1] as number, dimensions[2] as number],\n label: typeof label === \"string\" && label.length > 0 ? label.toLowerCase() : null,\n });\n }\n this.#host?.meshes(meshes);\n this.#report({ feature: \"meshes\", state: \"active\", detail: meshes.length + \" meshes\" });\n }\n\n #readAnchors(): void {\n const anchors: WorldAnchor[] = [];\n for (const entity of this.#anchorQuery.entities) {\n const pose = poseOf(entity);\n if (pose === null) continue;\n anchors.push({\n id: this.#idFor(entity as unknown as object),\n pose,\n // IWSDK's own flag: false until the system has attached the entity to\n // a real anchor, which is exactly what \"not tracked yet\" means here.\n tracked: entity.getValue(XRAnchor, \"attached\") === true,\n });\n }\n this.#host?.anchors(anchors);\n this.#report({ feature: \"anchors\", state: \"active\", detail: anchors.length + \" anchors\" });\n }\n\n #readHits(): void {\n for (const [id, entity] of this.#hitEntities) {\n const result = entity.getValue(EnvironmentRaycastTarget, \"xrHitTestResult\");\n const pose = poseOf(entity);\n const hits: WorldHit[] =\n result === undefined || result === null || pose === null\n ? []\n : [{ sourceId: id, pose, distance: null }];\n this.#host?.hits(id, hits);\n if (hits.length > 0) {\n this.#report({ feature: \"hitTest\", state: \"active\", detail: \"hitting the room\" });\n }\n }\n }\n\n #idFor(object: object): string {\n const existing = this.#ids.get(object);\n if (existing !== undefined) return existing;\n const id = \"world-\" + String(this.#nextId);\n this.#nextId += 1;\n this.#ids.set(object, id);\n return id;\n }\n\n #report(report: SensingReport): void {\n const stamp = report.state + \"|\" + report.detail;\n if (this.#states.get(report.feature) === stamp) return;\n this.#states.set(report.feature, stamp);\n this.#host?.report(report);\n }\n}\n\n/** The world transform of the entity IWSDK positioned for us. */\nfunction poseOf(entity: Entity): WorldPose | null {\n const object3D = entity.object3D;\n if (object3D === undefined) return null;\n object3D.getWorldPosition(TEMP_POSITION);\n object3D.getWorldQuaternion(TEMP_QUATERNION);\n return {\n position: [TEMP_POSITION.x, TEMP_POSITION.y, TEMP_POSITION.z],\n orientation: [TEMP_QUATERNION.x, TEMP_QUATERNION.y, TEMP_QUATERNION.z, TEMP_QUATERNION.w],\n };\n}\n\nfunction orientationOf(value: string | undefined): WorldPlaneOrientation {\n const lowered = value?.toLowerCase();\n if (lowered === \"horizontal\" || lowered === \"vertical\") return lowered;\n return \"unknown\";\n}\n\nfunction extentsOf(polygon: readonly (readonly [number, number])[]): readonly [number, number] {\n if (polygon.length === 0) return [0, 0];\n let minX = Infinity;\n let maxX = -Infinity;\n let minZ = Infinity;\n let maxZ = -Infinity;\n for (const [x, z] of polygon) {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n minZ = Math.min(minZ, z);\n maxZ = Math.max(maxZ, z);\n }\n return [maxX - minX, maxZ - minZ];\n}\n\n/** Our three ray sources onto IWSDK's four. */\nfunction raycastSpace(space: HitTestRequest[\"space\"]): string {\n if (space === \"left\") return RaycastSpace.Left;\n if (space === \"right\") return RaycastSpace.Right;\n return RaycastSpace.Viewer;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realitycollective/iwsdk-environment",
|
|
3
|
-
"version": "0.1.0-preview.
|
|
3
|
+
"version": "0.1.0-preview.2",
|
|
4
4
|
"description": "Meta IWSDK adapter for the Reality Collective WebXR Environment Extensions - drives IWSDK's own DomeGradient, light components, transform entities and AudioSource machinery from the engine-free @realitycollective/webxr-environment core, with a one-call registerEnvironment(world) setup and an ECS system that ticks the directors. Re-exports the core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"realitycollective",
|
|
@@ -35,15 +35,16 @@
|
|
|
35
35
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@realitycollective/webxr-environment": "^0.1.0-preview.
|
|
38
|
+
"@realitycollective/webxr-environment": "^0.1.0-preview.2"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@iwsdk/core": ">=0.5.0 <0.6.0"
|
|
41
|
+
"@iwsdk/core": ">=0.5.0 <0.6.0",
|
|
42
|
+
"three": ">=0.170.0"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"@iwsdk/core": "0.5.3",
|
|
45
46
|
"three": "npm:super-three@0.185.0",
|
|
46
|
-
"@types/three": "
|
|
47
|
+
"@types/three": "0.185.4"
|
|
47
48
|
},
|
|
48
49
|
"repository": {
|
|
49
50
|
"type": "git",
|