Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/jsm/effects/PeppersGhostEffect.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class PeppersGhostEffect {
/**
* Constructs a new peppers ghost effect.
*
* @param {(Renderer|WebGLRenderer)} renderer - The renderer.
* @param {(WebGPURenderer|WebGLRenderer)} renderer - The renderer.
*/
constructor( renderer ) {

Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/helpers/ViewHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class ViewHelper extends Object3D {
* Renders the helper in a separate view in the bottom-right corner
* of the viewport.
*
* @param {WebgLRenderer|Renderer} renderer - The renderer.
* @param {WebGLRenderer|WebGPURenderer} renderer - The renderer.
*/
this.render = function ( renderer ) {

Expand Down
25 changes: 25 additions & 0 deletions examples/jsm/interactive/HTMLMesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,29 @@ import {
Color
} from 'three';

/**
* This class can be used to render a DOM element onto a canvas and use it as a texture
* for a plane mesh.
*
* A typical use case for this class is to render the GUI of `lil-gui` as a texture so it
* is compatible for VR.
*
* ```js
* const gui = new GUI( { width: 300 } ); // create lil-gui instance
*
* const mesh = new HTMLMesh( gui.domElement );
* scene.add( mesh );
* ```
*
* @augments Mesh
*/
class HTMLMesh extends Mesh {

/**
* Constructs a new HTML mesh.
*
* @param {HTMLElement} dom - The DOM element to display as a plane mesh.
*/
constructor( dom ) {

const texture = new HTMLTexture( dom );
Expand All @@ -30,6 +51,10 @@ class HTMLMesh extends Mesh {
this.addEventListener( 'mouseup', onEvent );
this.addEventListener( 'click', onEvent );

/**
* Frees the GPU-related resources allocated by this instance and removes all event listeners.
* Call this method whenever this instance is no longer used in your app.
*/
this.dispose = function () {

geometry.dispose();
Expand Down
70 changes: 65 additions & 5 deletions examples/jsm/interactive/InteractiveGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ import {
const _pointer = new Vector2();
const _event = { type: '', data: _pointer };

// TODO: Dispatch pointerevents too

/**
* The XR events that are mapped to "standard" pointer events
*/
// The XR events that are mapped to "standard" pointer events.
const _events = {
'move': 'mousemove',
'select': 'click',
Expand All @@ -21,17 +17,58 @@ const _events = {

const _raycaster = new Raycaster();

/**
* This class can be used to group 3D objects in an interactive group.
* The group itself can listen to Pointer, Mouse or XR controller events to
* detect selections of descendant 3D objects. If a 3D object is selected,
* the respective event is going to dispatched to it.
*
* ```js
* const group = new InteractiveGroup();
* group.listenToPointerEvents( renderer, camera );
* group.listenToXRControllerEvents( controller1 );
* group.listenToXRControllerEvents( controller2 );
* scene.add( group );
*
* // now add objects that should be interactive
* group.add( mesh1, mesh2, mesh3 );
* ```
* @augments Group
*/
class InteractiveGroup extends Group {

constructor() {

super();

/**
* The internal raycaster.
*
* @type {Raycaster}
*/
this.raycaster = new Raycaster();

/**
* The internal raycaster.
*
* @type {?HTMLDOMElement}
* @default null
*/
this.element = null;

/**
* The camera used for raycasting.
*
* @type {?Camera}
* @default null
*/
this.camera = null;

/**
* An array of XR controllers.
*
* @type {Array<Group>}
*/
this.controllers = [];

this._onPointerEvent = this.onPointerEvent.bind( this );
Expand Down Expand Up @@ -92,6 +129,14 @@ class InteractiveGroup extends Group {

}

/**
* Calling this method makes sure the interactive group listens to Pointer and Mouse events.
* The taret is the `domElement` of the given renderer. The camera is required for the internal
* raycasting so 3D objects can be detected based on the events.
*
* @param {(WebGPURenderer|WebGLRenderer)} renderer - The renderer.
* @param {Camera} camera - The camera.
*/
listenToPointerEvents( renderer, camera ) {

this.camera = camera;
Expand All @@ -107,6 +152,9 @@ class InteractiveGroup extends Group {

}

/**
* Disconnects this interactive group from all Pointer and Mouse Events.
*/
disconnectionPointerEvents() {

if ( this.element !== null ) {
Expand All @@ -123,6 +171,12 @@ class InteractiveGroup extends Group {

}

/**
* Calling this method makes sure the interactive group listens to events of
* the given XR controller.
*
* @param {Group} controller - The XR controller.
*/
listenToXRControllerEvents( controller ) {

this.controllers.push( controller );
Expand All @@ -133,6 +187,9 @@ class InteractiveGroup extends Group {

}

/**
* Disconnects this interactive group from all XR controllers.
*/
disconnectXrControllerEvents() {

for ( const controller of this.controllers ) {
Expand All @@ -146,6 +203,9 @@ class InteractiveGroup extends Group {

}

/**
* Disconnects this interactive group from the DOM and all XR controllers.
*/
disconnect() {

this.disconnectionPointerEvents();
Expand Down
83 changes: 74 additions & 9 deletions examples/jsm/interactive/SelectionBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import {
Quaternion,
} from 'three';

/**
* This is a class to check whether objects are in a selection area in 3D space
*/

const _frustum = new Frustum();
const _center = new Vector3();

Expand All @@ -33,34 +29,103 @@ const _matrix = new Matrix4();
const _quaternion = new Quaternion();
const _scale = new Vector3();

/**
* This class can be used to select 3D objects in a scene with a selection box.
* It is recommended to visualize the selected area with the help of {@link SelectionHelper}.
*
* ```js
* const selectionBox = new SelectionBox( camera, scene );
* const selectedObjects = selectionBox.select( startPoint, endPoint );
* ```
*/
class SelectionBox {

/**
* Constructs a new selection box.
*
* @param {Camera} camera - The camera the scene is rendered with.
* @param {Scene} scene - The scene.
* @param {number} [deep=Number.MAX_VALUE] - How deep the selection frustum of perspective cameras should extend.
*/
constructor( camera, scene, deep = Number.MAX_VALUE ) {

/**
* The camera the scene is rendered with.
*
* @type {Camera}
*/
this.camera = camera;

/**
* The camera the scene is rendered with.
*
* @type {Scene}
*/
this.scene = scene;

/**
* The start point of the selction.
*
* @type {Vector3}
*/
this.startPoint = new Vector3();

/**
* The end point of the selction.
*
* @type {Vector3}
*/
this.endPoint = new Vector3();

/**
* The selected 3D objects.
*
* @type {Array<Object3D>}
*/
this.collection = [];

/**
* The selected instance IDs of instanced meshes.
*
* @type {Object}
*/
this.instances = {};

/**
* How deep the selection frustum of perspective cameras should extend.
*
* @type {number}
* @default Number.MAX_VALUE
*/
this.deep = deep;

}

/**
* This method selects 3D objects in the scene based on the given start
* and end point. If no parameters are provided, the method uses the start
* and end values of the respective members.
*
* @param {Vector3} [startPoint] - The start point.
* @param {Vector3} [endPoint] - The end point.
* @return {Array<Object3D>} The selected 3D objects.
*/
select( startPoint, endPoint ) {

this.startPoint = startPoint || this.startPoint;
this.endPoint = endPoint || this.endPoint;
this.collection = [];

this.updateFrustum( this.startPoint, this.endPoint );
this.searchChildInFrustum( _frustum, this.scene );
this._updateFrustum( this.startPoint, this.endPoint );
this._searchChildInFrustum( _frustum, this.scene );

return this.collection;

}

updateFrustum( startPoint, endPoint ) {
// private

_updateFrustum( startPoint, endPoint ) {

startPoint = startPoint || this.startPoint;
endPoint = endPoint || this.endPoint;
Expand Down Expand Up @@ -170,7 +235,7 @@ class SelectionBox {

}

searchChildInFrustum( frustum, object ) {
_searchChildInFrustum( frustum, object ) {

if ( object.isMesh || object.isLine || object.isPoints ) {

Expand Down Expand Up @@ -214,7 +279,7 @@ class SelectionBox {

for ( let x = 0; x < object.children.length; x ++ ) {

this.searchChildInFrustum( frustum, object.children[ x ] );
this._searchChildInFrustum( frustum, object.children[ x ] );

}

Expand Down
Loading
Loading