Extensible 3D (X3D)
Part 1: Architecture and base components

20 Pointing device sensor component

# 20.1 Introduction

## 20.1.1 Name

The name of this component is "PointingDeviceSensor". This name shall be used when referring to this component in the COMPONENT statement (see 7.2.5.4 Component statement).

## 20.1.2 Overview

This clause describes the Pointing Device Sensor component of this part of ISO/IEC 19775. This includes how pointing device sensors operate conceptually as well as which varieties of pointing device sensors are provided. Table 20.1 provides links to the major topics in this clause.

Table 20.1 — Topics

20.1 Introduction 20.1.1 Name 20.1.2 Overview 20.2 Concepts 20.2.1 Overview of pointing device sensors 20.2.2 Drag sensors 20.2.3 Activating and manipulating pointing device sensors 20.3 Abstract types 20.3.1 X3DDragSensorNode 20.3.2 X3DPointingDeviceSensorNode 20.3.3 X3DTouchSensorNode 20.4 Node reference 20.4.1 CylinderSensor 20.4.2 PlaneSensor 20.4.3 SphereSensor 20.4.4 TouchSensor 20.5 Support levels Table 20.1 — Topics Table 20.2 — Pointing device sensor component support levels

# 20.2 Concepts

## 20.2.1 Overview of pointing device sensors

Pointing device sensors detect user pointing events such as the user clicking on a piece of geometry (i.e., TouchSensor). The following node types are pointing device sensors:

- CylinderSensor
- PlaneSensor
- SphereSensor
- TouchSensor

The Anchor node is also considered a pointing device sensor for the purpose of detecting user picking. However, it does not extend from the X3DPointingDeviceSensorNode interface.

Other components may add additional pointing device sensors.

A pointing device sensor is activated when the user locates the pointing device over geometry that is influenced by that specific pointing device sensor. Pointing device sensors have influence over all geometry that is descended from the sensor's parent groups. In the case of the Anchor node, the Anchor node itself is considered to be the parent group. Typically, the pointing device sensor is a sibling to the geometry that it influences. In other cases, the sensor is a sibling to groups which contain geometry (i.e., are influenced by the pointing device sensor).

The appearance properties of the geometry do not affect activation of the sensor. In particular, transparent materials or textures shall be treated as opaque with respect to activation of pointing device sensors.

For a given user activation, the lowest enabled pointing device sensor in the hierarchy is activated. All other pointing device sensors above the lowest enabled pointing device sensor are ignored. The hierarchy is defined by the geometry node over which the pointing device sensor is located and the entire hierarchy upward. If there are multiple pointing device sensors tied for lowest, each of these is activated simultaneously and independently, possibly resulting in multiple sensors activating and generating output simultaneously. This feature allows combinations of pointing device sensors (e.g., TouchSensor and PlaneSensor). If a pointing device sensor appears in the transformation hierarchy multiple times (DEF/USE), it shall be tested for activation in all of the coordinate systems in which it appears.

If a pointing device sensor is not enabled when the pointing device button is activated, it will not generate events related to the pointing device until after the pointing device is deactivated and the sensor is enabled (i.e., enabling a sensor in the middle of dragging does not result in the sensor activating immediately).

## 20.2.2 Drag sensors

Drag sensors are a subset of pointing device sensors. There are three types of drag sensors: CylinderSensor, PlaneSensor, and SphereSensor. Drag sensors have two outputOnly fields in common, trackPoint_changed and <value>_changed. These outputOnly fields send events for each movement of the activated pointing device according to their "virtual geometry" (e.g., cylinder for CylinderSensor). The trackPoint_changed outputOnly field sends the intersection point of the bearing with the drag sensor's virtual geometry. The <value>_changed outputOnly field sends the sum of the relative change since activation plus the sensor's offset field. The type and name of <value>_changed depends on the drag sensor type: rotation_changed for CylinderSensor, translation_changed for PlaneSensor, and rotation_changed for SphereSensor.

To simplify the application of these sensors, each node has an offset and an autoOffset exposed field. When the sensor generates events as a response to the activated pointing device motion, <value>_changed sends the sum of the relative change since the initial activation plus the offset field value. If autoOffset is TRUE when the pointing device is deactivated, the offset field is set to the sensor's last <value>_changed value and offset sends an offset_changed output event. This enables subsequent grabbing operations to accumulate the changes. If autoOffset is FALSE, the sensor does not set the offset field value at deactivation (or any other time).

## 20.2.3 Activating and manipulating pointing device sensors

The pointing device controls a pointer in the virtual world. While activated by the pointing device, a sensor will generate events as the pointer moves. Typically the pointing device may be categorized as either 2D (e.g., conventional mouse) or 3D (e.g., wand). It is suggested that the pointer controlled by a 2D device is mapped onto a plane a fixed distance from the viewer and perpendicular to the line of sight. The mapping of a 3D device may describe a 1:1 relationship between movement of the pointing device and movement of the pointer.

The position of the pointer defines a bearing which is used to determine which geometry is being indicated. When implementing a 2D pointing device it is suggested that the bearing is defined by the vector from the viewer position through the location of the pointer. When implementing a 3D pointing device it is suggested that the bearing is defined by extending a vector from the current position of the pointer in the direction indicated by the pointer.

In all cases the pointer is considered to be indicating a specific geometry when that geometry is intersected by the bearing. If the bearing intersects multiple sensors' geometries, only the sensor nearest to the pointer will be eligible for activation.

# 20.3 Abstract types

## 20.3.1 X3DDragSensorNode

    X3DDragSensorNode : X3DPointingDeviceSensorNode {
      SFBool   [in,out] autoOffset         TRUE
      SFString [in,out] description        ""
      SFBool   [in,out] enabled            TRUE
      SFNode   [in,out] metadata           NULL [X3DMetadataObject]
      SFBool   [out]    isActive
      SFBool   [out]    isOver
      SFVec3f  [out]    trackPoint_changed
    }

This abstract node type is the base type for all drag-style pointing device sensors.

## 20.3.2 X3DPointingDeviceSensorNode

    X3DPointingDeviceSensorNode : X3DSensorNode {
      SFString [in,out] description ""
      SFBool   [in,out] enabled     TRUE
      SFNode   [in,out] metadata    NULL [X3DMetadataObject]
      SFBool   [out]    isActive
      SFBool   [out]    isOver
    }

This abstract node type is the base type for all pointing device sensors.

## 20.3.3 X3DTouchSensorNode

    X3DTouchSensorNode : X3DPointingDeviceSensorNode {
      SFString [in,out] description ""
      SFBool   [in,out] enabled     TRUE
      SFNode   [in,out] metadata    NULL [X3DMetadataObject]
      SFBool   [out]    isActive
      SFBool   [out]    isOver
      SFTime   [out]    touchTime
    }

This abstract node type is the base type for all touch-style pointing device sensors.

# 20.4 Node reference

## 20.4.1 CylinderSensor

    CylinderSensor : X3DDragSensorNode {
      SFBool     [in,out] autoOffset         TRUE
      SFRotation [in,out] axisRotation       0 1 0 0
      SFString   [in,out] description        ""
      SFFloat    [in,out] diskAngle          π/12    [0,π/2]
      SFBool     [in,out] enabled            TRUE
      SFFloat    [in,out] maxAngle           -1      [-2π,2π]
      SFNode     [in,out] metadata           NULL    [X3DMetadataObject]
      SFFloat    [in,out] minAngle           0       [-2π,2π]
      SFFloat    [in,out] offset             0       (-∞,∞)
      SFBool     [out]    isActive
      SFBool     [out]    isOver
      SFRotation [out]    rotation_changed
      SFVec3f    [out]    trackPoint_changed
    }

The CylinderSensor node maps pointer motion (e.g., a mouse or wand) into a rotation on an invisible cylinder that is aligned with the Y-axis of the local sensor coordinate system. The local sensor coordinate system is created by applying the axisRotation field value to the local coordinate system. The CylinderSensor uses the descendent geometry of its parent node to determine whether it is liable to generate events.

The description field in the CylinderSensor node specifies a textual description of the CylinderSensor node. This may be used by browser-specific user interfaces that wish to present users with more detailed information about the CylinderSensor.

The enabled field enables and disables the CylinderSensor node. If TRUE, the sensor reacts appropriately to user events. If FALSE, the sensor does not track user input or send events. If enabled receives a FALSE event and isActive is TRUE, the sensor becomes disabled and deactivated, and outputs an isActive FALSE event. If enabled receives a TRUE event the sensor is enabled and ready for user activation.

A CylinderSensor node generates events when the pointing device is activated while the pointer is indicating any descendent geometry nodes of the sensor's parent group. See 20.2.3 Activating and manipulating pointing device sensors, for more details on using the pointing device to activate the CylinderSensor.

Upon activation of the pointing device while indicating the sensor's geometry, an isActive TRUE event is sent. The initial acute angle between the bearing vector and the local sensor coordinate system Y-axis of the CylinderSensor node determines whether the sides of the invisible cylinder or the caps (disks) are used for manipulation. If the initial angle is less than the diskAngle, the geometry is treated as an infinitely large disk lying in the Y=0 plane of the local sensor coordinate system and coincident with the initial intersection point. Dragging motion is mapped into a rotation around the +Y-axis vector of the local sensor coordinate system. The perpendicular vector from the initial intersection point to this Y-axis defines zero rotation about the Y-axis of the local sensor coordinate system. For each subsequent position of the bearing, a rotation_changed event is sent that equals the sum of the rotation about the +Y-axis vector of the local sensor coordinate system (from the initial intersection to the new intersection) plus the offset value. trackPoint_changed events reflect the unclamped drag position on the surface of this disk. When the pointing device is deactivated and autoOffset is TRUE, offset is set to the last rotation angle and an offset_changed event is generated. See 20.2.2 Drag sensors, for a more general description of autoOffset and offset fields.

If the initial acute angle between the bearing vector and the local sensor coordinate system Y-axis of the CylinderSensor node is greater than or equal to diskAngle, the sensor behaves like a cylinder. The shortest distance between the point of intersection (between the bearing and the sensor's geometry) and the Y-axis of the parent group's local coordinate system determines the radius of an invisible cylinder used to map pointing device motion and marks the zero rotation value. For each subsequent position of the bearing, a rotation_changed event is sent that equals the sum of the right-handed rotation from the original intersection about the +Y-axis vector plus the offset value. trackPoint_changed events reflect the unclamped drag position on the surface of the invisible cylinder. When the pointing device is deactivated and autoOffset is TRUE, offset is set to the last rotation angle and an offset_changed event is generated. More details are available in 20.2.2 Drag sensors.

When the sensor generates an isActive TRUE event, it grabs all further motion events from the pointing device until it is released and generates an isActive FALSE event (other pointing device sensors shall not generate events during this time). Motion of the pointing device while isActive is TRUE is referred to as a "drag" operation. If a 2D pointing device is in use, isActive events will typically reflect the state of the primary button associated with the device (i.e., isActive is TRUE when the primary button is pressed and FALSE when it is released). If a 3D pointing device (e.g., a wand) is in use, isActive events will typically reflect whether the pointer is within or in contact with the sensor's geometry.

While the pointing device is activated, trackPoint_changed and rotation_changed events are output and are interpreted from pointing device motion based on the sensor's local coordinate system at the time of activation. trackPoint_changed events represent the unclamped intersection points on the surface of the invisible cylinder or disk. If the initial angle results in cylinder rotation (as opposed to disk behaviour) and if the pointing device is dragged off the cylinder while activated, browsers may interpret this in a variety of ways (e.g., clamp all values to the cylinder and continuing to rotate as the point is dragged away from the cylinder). Each movement of the pointing device while isActive is TRUE generates trackPoint_changed and rotation_changed events.

The minAngle and maxAngle fields clamp rotation_changed events to a range of values. If minAngle is greater than maxAngle, rotation_changed events are not clamped. The minAngle and maxAngle fields are restricted to the range [-2π, 2π].

More information about this behaviour is described in 20.2 Concepts.

## 20.4.2 PlaneSensor

    PlaneSensor : X3DDragSensorNode {
      SFBool     [in,out] autoOffset          TRUE
      SFRotation [in,out] axisRotation        0 0 1 0
      SFString   [in,out] description         ""
      SFBool     [in,out] enabled             TRUE
      SFVec2f    [in,out] maxPosition         -1 -1 (-∞,∞)
      SFNode     [in,out] metadata            NULL  [X3DMetadataObject]
      SFVec2f    [in,out] minPosition         0 0   (-∞,∞)
      SFVec3f    [in,out] offset              0 0 0 (-∞,∞)
      SFBool     [out]    isActive
      SFBool     [out]    isOver
      SFVec3f    [out]    trackPoint_changed
      SFVec3f    [out]    translation_changed
    }

The PlaneSensor node maps pointing device motion into two-dimensional translation in a plane parallel to the Z=0 plane of the local sensor coordinate system. The local sensor coordinate system is created by applying the axisRotation field value to the local coordinate system. The PlaneSensor node uses the descendent geometry of its parent node to determine whether it is liable to generate events.

The description field in the PlaneSensor node specifies a textual description of the PlaneSensor node. This may be used by browser-specific user interfaces that wish to present users with more detailed information about the PlaneSensor.

The enabled field enables and disables the PlaneSensor. If enabled is TRUE, the sensor reacts appropriately to user events. If enabled is FALSE, the sensor does not track user input or send events. If enabled receives a FALSE event and isActive is TRUE, the sensor becomes disabled and deactivated, and outputs an isActive FALSE event. If enabled receives a TRUE event, the sensor is enabled and made ready for user activation.

The PlaneSensor node generates events when the pointing device is activated while the pointer is indicating any descendent geometry nodes of the sensor's parent group. See 20.2.3 Activating and manipulating pointing device sensors, for details on using the pointing device to activate the PlaneSensor.

Upon activation of the pointing device (e.g., mouse button down) while indicating the sensor's geometry, an isActive TRUE event is sent. Pointer motion is mapped into relative translation in the tracking plane, (a plane parallel to the local sensor coordinate system Z=0 plane and coincident with the initial point of intersection). For each subsequent movement of the bearing, a translation_changed event is output which corresponds to the sum of the relative translation from the original intersection point to the intersection point of the new bearing in the plane plus the offset value. The sign of the translation is defined by the Z=0 plane of the local sensor coordinate system. trackPoint_changed events reflect the unclamped drag position on the surface of this plane. When the pointing device is deactivated and autoOffset is TRUE, offset is set to the last translation_changed value and an offset_changed event is generated. More details are provided in 20.2.2 Drag sensors.

When the sensor generates an isActive TRUE event, it grabs all further motion events from the pointing device until it is deactivated and generates an isActive FALSE event. Other pointing device sensors shall not generate events during this time. Motion of the pointing device while isActive is TRUE is referred to as a "drag" operation. If a 2D pointing device is in use, isActive events typically reflect the state of the primary button associated with the device (i.e., isActive is TRUE when the primary button is pressed, and is FALSE when it is released). If a 3D pointing device (e.g., wand) is in use, isActive events typically reflect whether the pointer is within or in contact with the sensor's geometry.

minPosition and maxPosition may be set to clamp translation_changed events to a range of values as measured from the origin of the Z=0 plane of the local sensor coordinate system. If the X or Y component of minPosition is greater than the corresponding component of maxPosition, translation_changed events are not clamped in that dimension. If the X or Y component of minPosition is equal to the corresponding component of maxPosition, that component is constrained to the given value. This technique provides a way to implement a line sensor that maps dragging motion into a translation in one dimension.

While the pointing device is activated and moved, trackPoint_changed and translation_changed events are sent. trackPoint_changed events represent the unclamped intersection points on the surface of the tracking plane. If the pointing device is dragged off of the tracking plane while activated (e.g., above horizon line), browsers may interpret this in a variety ways (e.g., clamp all values to the horizon). Each movement of the pointing device, while isActive is TRUE, generates trackPoint_changed and translation_changed events.

Further information about this behaviour can be found in 20.2 Concepts.

## 20.4.3 SphereSensor

    SphereSensor : X3DDragSensorNode {
      SFBool     [in,out] autoOffset         TRUE
      SFString   [in,out] description        ""
      SFBool     [in,out] enabled            TRUE
      SFNode     [in,out] metadata           NULL    [X3DMetadataObject]
      SFRotation [in,out] offset             0 1 0 0 [-1,1],(-∞,∞)
      SFBool     [out]    isActive
      SFBool     [out]    isOver
      SFRotation [out]    rotation_changed
      SFVec3f    [out]    trackPoint_changed
    }

The SphereSensor node maps pointing device motion into spherical rotation about the origin of the local coordinate system. The SphereSensor node uses the descendent geometry of its parent node to determine whether it is liable to generate events.

The description field in the SphereSensor node specifies a textual description of the SphereSensor node. This may be used by browser-specific user interfaces that wish to present users with more detailed information about the SphereSensor.

The enabled field enables and disables the SphereSensor node. If enabled is TRUE, the sensor reacts appropriately to user events. If enabled is FALSE, the sensor does not track user input or send events. If enabled receives a FALSE event and isActive is TRUE, the sensor becomes disabled and deactivated, and outputs an isActive FALSE event. If enabled receives a TRUE event the sensor is enabled and ready for user activation.

The SphereSensor node generates events when the pointing device is activated while the pointer is indicating any descendent geometry nodes of the sensor's parent group. See 20.2.3 Activating and manipulating pointing device sensors, for details on using the pointing device to activate the SphereSensor.

Upon activation of the pointing device (e.g., mouse button down) over the sensor's geometry, an isActive TRUE event is sent. The vector defined by the initial point of intersection on the SphereSensor's geometry and the local origin determines the radius of the sphere that is used to map subsequent pointing device motion while dragging. The virtual sphere defined by this radius and the local origin at the time of activation is used to interpret subsequent pointing device motion and is not affected by any changes to the sensor's coordinate system while the sensor is active. For each position of the bearing, a rotation_changed event is sent which corresponds to the sum of the relative rotation from the original intersection point plus the offset value. trackPoint_changed events reflect the unclamped drag position on the surface of this sphere. When the pointing device is deactivated and autoOffset is TRUE, offset is set to the last rotation_changed value and an offset_changed event is generated. See 20.2 Concepts, for more details.

When the sensor generates an isActive TRUE event, it grabs all further motion events from the pointing device until it is released and generates an isActive FALSE event (other pointing device sensors shall not generate events during this time). Motion of the pointing device while isActive is TRUE is termed a "drag" operation. If a 2D pointing device is in use, isActive events will typically reflect the state of the primary button associated with the device (i.e., isActive is TRUE when the primary button is pressed and FALSE when it is released). If a 3D pointing device (e.g., wand) is in use, isActive events will typically reflect whether the pointer is within (or in contact with) the sensor's geometry.

While the pointing device is activated, trackPoint_changed and rotation_changed events are output. trackPoint_changed events represent the unclamped intersection points on the surface of the invisible sphere. If the pointing device is dragged off the sphere while activated, browsers may interpret this in a variety of ways (e.g., clamp all values to the sphere or continue to rotate as the point is dragged away from the sphere). Each movement of the pointing device while isActive is TRUE generates trackPoint_changed and rotation_changed events.

Further information about this behaviour can be found in 20.2 Concepts.

## 20.4.4 TouchSensor

    TouchSensor : X3DTouchSensorNode {
      SFString [in,out] description         ""
      SFBool   [in,out] enabled             TRUE
      SFNode   [in,out] metadata            NULL [X3DMetadataObject]
      SFVec3f  [out]    hitNormal_changed
      SFVec3f  [out]    hitPoint_changed
      SFVec2f  [out]    hitTexCoord_changed
      SFBool   [out]    isActive
      SFBool   [out]    isOver
      SFTime   [out]    touchTime
    }

A TouchSensor node tracks the location and state of the pointing device and detects when the user points at geometry contained by the TouchSensor node's parent group.

The description field in the TouchSensor node specifies a textual description of the TouchSensor node. This may be used by browser-specific user interfaces that wish to present users with more detailed information about the TouchSensor.

A TouchSensor node can be enabled or disabled by sending it an enabled event with a value of TRUE or FALSE. If the TouchSensor node is disabled, it does not track user input or send events.

The TouchSensor generates events when the pointing device points toward any geometry nodes that are descendants of the TouchSensor's parent group. See 20.2.3 Activating and manipulating pointing device sensors, for more details on using the pointing device to activate the TouchSensor.

The isOver field reflects the state of the pointing device with regard to whether it is pointing towards the TouchSensor node's geometry or not. When the pointing device changes state from a position such that its bearing does not intersect any of the TouchSensor node's geometry to one in which it does intersect geometry, an isOver TRUE event is generated. When the pointing device moves from a position such that its bearing intersects geometry to one in which it no longer intersects the geometry, or some other geometry is obstructing the TouchSensor node's geometry, an isOver FALSE event is generated. These events are generated only when the pointing device has moved and changed `over' state. Events are not generated if the geometry itself is animating and moving underneath the pointing device.

As the user moves the bearing over the TouchSensor node's geometry, the point of intersection (if any) between the bearing and the geometry is determined. Each movement of the pointing device, while isOver is TRUE, generates hitPoint_changed, hitNormal_changed and hitTexCoord_changed events. hitPoint_changed events contain the 3D point on the surface of the underlying geometry, given in the TouchSensor node's coordinate system. hitNormal_changed events contain the surface normal vector at the hitPoint. hitTexCoord_changed events contain the texture coordinates of that surface at the hitPoint. The values of hitTexCoord_changed and hitNormal_changed events are computed as appropriate for the associated shape.

If isOver is TRUE, the user may activate the pointing device to cause the TouchSensor node to generate isActive events (e.g., by pressing the primary mouse button). When the TouchSensor node generates an isActive TRUE event, it grabs all further motion events from the pointing device until it is released and generates an isActive FALSE event (other pointing device sensors will not generate events during this time). Motion of the pointing device while isActive is TRUE is termed a "drag" operation. If a 2D pointing device is in use, isActive events reflect the state of the primary button associated with the device (i.e., isActive is TRUE when the primary button is pressed and FALSE when it is released). If a 3D pointing device is in use, isActive events will typically reflect whether the pointing device is within (or in contact with) the TouchSensor node's geometry.

The field touchTime is generated when all three of the following conditions are true:

1. The pointing device was pointing towards the geometry when it was initially activated (isActive is TRUE).
2. The pointing device is currently pointing towards the geometry (isOver is TRUE).
3. The pointing device is deactivated (isActive FALSE event is also generated).

More information about this behaviour is described in 20.2 Concepts.

# 20.5 Support levels

The Pointing Device Sensor component provides one level of support as specified in Table 20.2.

Table 20.2 — Pointing device sensor component support levels

Level | Prerequisites | Nodes/Features | Support
--- | --- | --- | ---
1 | Core 1 Grouping 1 Shape 1 |  |
|  | DragSensorNodeType (abstract) | n/a
|  | PointingDeviceSensorNodeType (abstract) | n/a
|  | TouchSensorNodeType (abstract) | n/a
|  | CylinderSensor | All fields fully supported.
|  | PlaneSensor | All fields fully supported.
|  | SphereSensor | All fields fully supported.
|  | TouchSensor | All fields fully supported.