Support per-instance cursor events on BatchedMesh / InstancedMesh#5824
Support per-instance cursor events on BatchedMesh / InstancedMesh#5824vincentfretin wants to merge 2 commits into
Conversation
Multiple a-entities sharing a single BatchedMesh (draw-call reduction) or InstancedMesh (instancing) all map to the same host entity, so the raycaster and cursor collapse hover / click tracking across every logical instance: ray moves between two instances of the same shared mesh, nothing fires. raycaster: also fire raycaster-closest-entity-changed when the closest hit's (entity, batchId, instanceId) tuple changes, even if the entity is unchanged. No per-instance mapping in core — the raycaster's role stops at surfacing batchId / instanceId on intersection details. cursor: track (intersectedEl, intersection.batchId, intersection.instanceId) as the hover identity. Transitions within a shared mesh now fire mouseleave with the OLD tuple and mouseenter with the NEW tuple. The stored intersection is used for event payloads so leave events carry the outgoing instance's details, not the incoming one. App-level mapping: the new examples/test/raycaster-batched-mesh example shows a `batch-proxy` component on each host entity that holds its own map from id to member entity and forwards mouseenter / mouseleave / click to the matching per-instance entity. Keeping the map in userspace lets apps encode whatever identity makes sense (batchId, instanceId, custom composite keys) without expanding the core component API. Tests cover intersection details carrying batchId / instanceId, raycaster-closest-entity-changed firing on tuple-only change, and the cursor's tuple-aware mouseleave/mouseenter sequencing with the outgoing tuple in detail.intersection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
91280af to
9da6302
Compare
…ersection Guards the regression where the cursor emitted click with the intersection stashed at hover start instead of a fresh getIntersection: moving the ray across the same entity between mousedown and click now verifies the event detail carries the current uv. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
I fixed the tests I forgot to run yesterday when I fixed the uv issue and added a non regression test for the fresh uv coordinates on click. I created another branch with the dist so you can see the example |
|
Conceptually all raycasting and cursor interactions happen on the entity level, regardless of what the Three.js contents of that entity is. While exposing more details about the intersections so that the app-level logic can handle it is fine, the changes to the events don't seem correct to me. Though obviously both are needed for the example to work properly. For one, My main concern is with users that simply load any arbitrary GLTF file. Depending on the file itself, an Perhaps the The |
I open this for feedback. I just started using it in a project where I use a component to handle an hover/open/close animation on an instance of an InstancedMesh in a glb.
Live example
Multiple a-entities sharing a single BatchedMesh (draw-call reduction) or InstancedMesh (instancing) all map to the same host entity, so the raycaster and cursor collapse hover / click tracking across every logical instance: ray moves between two instances of the same shared mesh, nothing fires.
raycaster: also fire raycaster-closest-entity-changed when the closest hit's (entity, batchId, instanceId) tuple changes, even if the entity is unchanged. No per-instance mapping in core — the raycaster's role stops at surfacing batchId / instanceId on intersection details.
cursor: track (intersectedEl, intersection.batchId, intersection.instanceId) as the hover identity. Transitions within a shared mesh now fire mouseleave with the OLD tuple and mouseenter with the NEW tuple. The stored intersection is used for event payloads so leave events carry the outgoing instance's details, not the incoming one.
App-level mapping: the new examples/test/raycaster-batched-mesh example shows a
batch-proxycomponent on each host entity that holds its own map from id to member entity and forwards mouseenter / mouseleave / click to the matching per-instance entity. Keeping the map in userspace lets apps encode whatever identity makes sense (batchId, instanceId, custom composite keys) without expanding the core component API.Tests cover intersection details carrying batchId / instanceId, raycaster-closest-entity-changed firing on tuple-only change, and the cursor's tuple-aware mouseleave/mouseenter sequencing with the outgoing tuple in detail.intersection.