Interaction Types
IWSDK’s grabbing system provides three distinct interaction patterns, each implemented with different handle configurations and pointer management strategies. Understanding their architectural differences helps choose the right pattern for specific use cases.
Single-controller direct manipulation optimized for immediate, responsive interactions.
Architecture Characteristics
- Handle Configuration:
multitouch: false, projectRays: false - Pointer Events:
pointerEventsType: { deny: 'ray' } — prevents ray interference - Transform Support: Translation and rotation only (no scaling)
The system creates a standard HandleStore with constraints derived directly from component properties:
// Simplified handle creation from GrabSystem
const handle = new HandleStore(object, () => ({
rotate: entity.getValue(OneHandGrabbable, 'rotate') ? {
x: [rotateMin[0], rotateMax[0]],
y: [rotateMin[1], rotateMax[1]],
z: [rotateMin[2], rotateMax[2]]
} : false,
translate: entity.getValue(OneHandGrabbable, 'translate') ? {
x: [translateMin[0], translateMax[0]],
y: [translateMin[1], translateMax[1]],
z: [translateMin[2], translateMax[2]]
} : false,
multitouch: false // Single pointer only
}));
- Immediacy vs Complexity — Instant response but limited to basic transformations
- Simplicity vs Capability — Easy to predict behavior but no scaling operations
- Performance vs Features — Minimal overhead but fewer manipulation options
- Interactive tools and instruments (valves, levers, handles)
- Simple object repositioning
- Quick grab-and-move interactions
- Objects that should maintain their scale
Dual-controller manipulation enabling advanced operations including scaling through multi-pointer coordination.
Architecture Characteristics
- Handle Configuration:
multitouch: true, enables dual-pointer calculations - Pointer Events:
pointerEventsType: { deny: 'ray' } — same ray denial as one-hand - Transform Support: Translation, rotation, and scaling
Multi-Pointer Mathematics
Two-hand grabbing uses the relationship between controllers to derive transformations:
- Translation: Controlled by primary hand position
- Rotation: Derived from the orientation relationship between hands
- Scaling: Based on the distance between controllers — closer hands reduce scale, farther hands increase scale
The handle configuration enables multitouch and adds scaling constraints:
const handle = new HandleStore(object, () => ({
rotate: /* rotation constraints */,
translate: /* translation constraints */,
scale: entity.getValue(TwoHandsGrabbable, 'scale') ? {
x: [scaleMin[0], scaleMax[0]],
y: [scaleMin[1], scaleMax[1]],
z: [scaleMin[2], scaleMax[2]]
} : false,
multitouch: true // Enables dual-pointer processing
}));
- Capability vs Complexity — Supports scaling but requires coordination between hands
- Precision vs Effort — Enables precise manipulation but demands two-hand engagement
- Features vs Performance — Rich interaction set but higher computational cost
- Resizable objects (artwork, models, UI panels)
- Precise positioning tasks requiring stability
- Objects where scale adjustment is important
- Complex manipulation requiring both hands’ dexterity
Ray-based remote manipulation with specialized movement algorithms for telekinetic-style interactions.
Architecture Characteristics
- Handle Configuration: Custom
DistanceGrabHandle class with movement mode algorithms - Pointer Events:
pointerEventsType: { deny: 'grab' } — opposite configuration from direct grabbing - Transform Support: Translation, rotation, and scaling with mode-specific behaviors
Distance grabbing implements four distinct movement algorithms:
MoveTowardsTarget Algorithm
// From DistanceGrabHandle.update()
const pointerOrigin = p1.pointerWorldOrigin;
const distance = pointerOrigin.distanceTo(position);
if (distance > this.moveSpeed) {
const step = pointerOrigin.sub(position)
.normalize()
.multiplyScalar(this.moveSpeed);
position.add(step);
} else {
// Snap to target when close enough
position.copy(pointerOrigin);
quaternion.copy(p1.pointerWorldQuaternion);
}
// Delta-based movement tracking
const current = p1.pointerWorldOrigin;
if (this.previousPointerOrigin != undefined) {
const delta = current.sub(this.previousPointerOrigin);
position.add(delta);
}
this.previousPointerOrigin.copy(current);
MoveFromTarget & RotateAtSource
- MoveFromTarget: Direct 1:1 mapping with ray endpoint (delegates to standard handle)
- RotateAtSource: Rotation-only mode with automatic translation/scale disabling
Distance grabbing uses a reverse pointer event configuration to prevent conflicts:
// Distance grabbable objects deny grab pointers, accept rays
obj.pointerEventsType = { deny: 'grab' };
// Versus direct grabbing which denies rays
obj.pointerEventsType = { deny: 'ray' };
Return-to-Origin Mechanics
The returnToOrigin feature overrides the standard handle application:
// From DistanceGrabHandle.apply()
if (this.returnToOrigin && this.outputState?.last) {
target.position.copy(this.initialTargetPosition);
target.quaternion.copy(this.initialTargetQuaternion);
target.scale.copy(this.initialTargetScale);
return; // Skip standard handle application
}
- Reach vs Directness — Can interact with any visible object but lacks direct tactile feedback
- Flexibility vs Predictability — Multiple movement modes provide options but require mode selection
- Magic vs Realism — Enables impossible interactions but may feel less grounded
- Out-of-reach objects in large environments
- Magical or supernatural interaction themes
- Accessibility — reaching objects without physical movement
- Telekinetic gameplay mechanics
- Immediate objects: Use direct grabbing (one/two-hand)
- Remote objects: Use distance grabbing
- Resizable content: Requires two-hand grabbing
- Tool-like objects: Usually one-hand grabbing
Most applications combine multiple grabbing types:
- Gallery Setup: Paintings (one-hand rotation-only), Sculptures (two-hand with scaling), Floating artifacts (distance with return-to-origin)
- Workshop Environment: Tools (one-hand), Workpieces (two-hand), Stored materials (distance)
- Gaming Context: Weapons (one-hand), Interactive objects (two-hand), Magic items (distance)
The system’s automatic handle management makes it seamless to use different grabbing types on different objects within the same scene.