From d7636259eebec3ec9960ac9d6b30b2f50076765f Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Thu, 22 Apr 2021 17:43:17 +0100 Subject: [PATCH] Refactored interaction code. --- editor/js/Viewport.VR.js | 53 ++------------ editor/sw.js | 4 +- .../jsm/interactive/HTMLMesh.js | 42 ++++++++--- examples/jsm/interactive/InteractiveGroup.js | 73 +++++++++++++++++++ examples/jsm/webxr/InteractionManager.js | 66 ----------------- examples/webxr_vr_sandbox.html | 13 ++-- 6 files changed, 121 insertions(+), 130 deletions(-) rename editor/js/libs/three.html.js => examples/jsm/interactive/HTMLMesh.js (85%) create mode 100644 examples/jsm/interactive/InteractiveGroup.js delete mode 100644 examples/jsm/webxr/InteractionManager.js diff --git a/editor/js/Viewport.VR.js b/editor/js/Viewport.VR.js index ad0a19dade..1f81ece5ba 100644 --- a/editor/js/Viewport.VR.js +++ b/editor/js/Viewport.VR.js @@ -1,6 +1,7 @@ import * as THREE from '../../build/three.module.js'; -import { HTMLMesh } from './libs/three.html.js'; +import { InteractiveGroup } from '../../examples/jsm/interactive/InteractiveGroup.js'; +import { HTMLMesh } from '../../examples/jsm/interactive/HTMLMesh.js'; import { XRControllerModelFactory } from '../../examples/jsm/webxr/XRControllerModelFactory.js'; @@ -29,7 +30,7 @@ class VR { if ( group === null ) { - group = new THREE.Group(); + group = new InteractiveGroup( renderer ); editor.sceneHelpers.add( group ); const mesh = new HTMLMesh( sidebar ); @@ -41,19 +42,16 @@ class VR { // controllers - const controller1 = renderer.xr.getController( 0 ); - controller1.addEventListener( 'select', onSelect ); - group.add( controller1 ); - - const controller2 = renderer.xr.getController( 1 ); - controller2.addEventListener( 'select', onSelect ); - group.add( controller2 ); - const geometry = new THREE.BufferGeometry(); geometry.setFromPoints( [ new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, - 5 ) ] ); + const controller1 = renderer.xr.getController( 0 ); controller1.add( new THREE.Line( geometry ) ); + group.add( controller1 ); + + const controller2 = renderer.xr.getController( 1 ); controller2.add( new THREE.Line( geometry ) ); + group.add( controller2 ); // @@ -101,41 +99,6 @@ class VR { }; - // - - function onSelect( event ) { - - const controller = event.target; - - const intersections = getIntersections( controller ); - - if ( intersections.length > 0 ) { - - const intersection = intersections[ 0 ]; - - const object = intersection.object; - const uv = intersection.uv; - - object.material.map.dispatchEvent( 'click', uv.x, 1 - uv.y ); - - } - - } - - const raycaster = new THREE.Raycaster(); - const tempMatrix = new THREE.Matrix4(); - - function getIntersections( controller ) { - - tempMatrix.identity().extractRotation( controller.matrixWorld ); - - raycaster.ray.origin.setFromMatrixPosition( controller.matrixWorld ); - raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix ); - - return raycaster.intersectObjects( intersectables ); - - } - // signals signals.toggleVR.add( () => { diff --git a/editor/sw.js b/editor/sw.js index 580c0281ae..e6480ee245 100644 --- a/editor/sw.js +++ b/editor/sw.js @@ -57,6 +57,9 @@ const assets = [ '../examples/jsm/curves/NURBSCurve.js', '../examples/jsm/curves/NURBSUtils.js', + '../examples/jsm/interactive/HTMLMesh.js', + '../examples/jsm/interactive/InteractiveGroup.js', + '../examples/jsm/environments/RoomEnvironment.js', '../examples/jsm/exporters/ColladaExporter.js', @@ -108,7 +111,6 @@ const assets = [ './js/libs/tern-threejs/threejs.js', './js/libs/signals.min.js', - './js/libs/three.html.js', './js/libs/ui.js', './js/libs/ui.three.js', diff --git a/editor/js/libs/three.html.js b/examples/jsm/interactive/HTMLMesh.js similarity index 85% rename from editor/js/libs/three.html.js rename to examples/jsm/interactive/HTMLMesh.js index ba4cc80afe..19e2ddc4cd 100644 --- a/editor/js/libs/three.html.js +++ b/examples/jsm/interactive/HTMLMesh.js @@ -1,21 +1,41 @@ -import * as THREE from '../../../build/three.module.js'; +import { + CanvasTexture, + LinearFilter, + Mesh, + MeshBasicMaterial, + PlaneGeometry, + sRGBEncoding +} from '../../../build/three.module.js'; -class HTMLMesh extends THREE.Mesh { +class HTMLMesh extends Mesh { constructor( dom ) { const texture = new HTMLTexture( dom ); - const geometry = new THREE.PlaneGeometry( texture.image.width * 0.002, texture.image.height * 0.002 ); - const material = new THREE.MeshBasicMaterial( { map: texture, toneMapped: false } ); + const geometry = new PlaneGeometry( texture.image.width * 0.002, texture.image.height * 0.002 ); + const material = new MeshBasicMaterial( { map: texture, toneMapped: false } ); super( geometry, material ); + function onEvent( event ) { + + console.log( event.type ); + + material.map.dispatchEvent( event ); + + } + + this.addEventListener( 'mousedown', onEvent ); + this.addEventListener( 'mousemove', onEvent ); + this.addEventListener( 'mouseup', onEvent ); + this.addEventListener( 'click', onEvent ); + } } -class HTMLTexture extends THREE.CanvasTexture { +class HTMLTexture extends CanvasTexture { constructor( dom ) { @@ -24,15 +44,15 @@ class HTMLTexture extends THREE.CanvasTexture { this.dom = dom; this.anisotropy = 16; - this.encoding = THREE.sRGBEncoding; - this.minFilter = THREE.LinearFilter; - this.magFilter = THREE.LinearFilter; + this.encoding = sRGBEncoding; + this.minFilter = LinearFilter; + this.magFilter = LinearFilter; } - dispatchEvent( event, x, y ) { + dispatchEvent( event ) { - htmlevent( this.dom, event, x, y ); + htmlevent( this.dom, event.type, event.data.x, event.data.y ); this.update(); @@ -288,4 +308,4 @@ function htmlevent( element, event, x, y ) { } -export { HTMLMesh, HTMLTexture }; +export { HTMLMesh }; diff --git a/examples/jsm/interactive/InteractiveGroup.js b/examples/jsm/interactive/InteractiveGroup.js new file mode 100644 index 0000000000..060cf613ca --- /dev/null +++ b/examples/jsm/interactive/InteractiveGroup.js @@ -0,0 +1,73 @@ +import { + Group, + Matrix4, + Raycaster, + Vector2 +} from '../../../build/three.module.js'; + +const _event = { type: '', data: new Vector2() }; + +class InteractiveGroup extends Group { + + constructor( renderer ) { + + super(); + + const scope = this; + + const raycaster = new Raycaster(); + const tempMatrix = new Matrix4(); + + // TODO PointerEvents + + const events = { + 'move': 'mousemove', + 'select': 'click', + 'selectstart': 'mousedown', + 'selectend': 'mouseup' + }; + + function onXRControllerEvent( event ) { + + const controller = event.target; + + tempMatrix.identity().extractRotation( controller.matrixWorld ); + + raycaster.ray.origin.setFromMatrixPosition( controller.matrixWorld ); + raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix ); + + const intersections = raycaster.intersectObjects( scope.children ); + + if ( intersections.length > 0 ) { + + const intersection = intersections[ 0 ]; + + const object = intersection.object; + const uv = intersection.uv; + + _event.type = events[ event.type ]; + _event.data.set( uv.x, 1 - uv.y ); + + object.dispatchEvent( _event ); + + } + + } + + const controller1 = renderer.xr.getController( 0 ); + controller1.addEventListener( 'move', onXRControllerEvent ); + controller1.addEventListener( 'select', onXRControllerEvent ); + controller1.addEventListener( 'selectstart', onXRControllerEvent ); + controller1.addEventListener( 'selectend', onXRControllerEvent ); + + const controller2 = renderer.xr.getController( 1 ); + controller2.addEventListener( 'move', onXRControllerEvent ); + controller2.addEventListener( 'select', onXRControllerEvent ); + controller2.addEventListener( 'selectstart', onXRControllerEvent ); + controller2.addEventListener( 'selectend', onXRControllerEvent ); + + } + +} + +export { InteractiveGroup }; diff --git a/examples/jsm/webxr/InteractionManager.js b/examples/jsm/webxr/InteractionManager.js deleted file mode 100644 index 944f9188eb..0000000000 --- a/examples/jsm/webxr/InteractionManager.js +++ /dev/null @@ -1,66 +0,0 @@ -import { - Matrix4, - Raycaster -} from '../../../build/three.module.js'; - -class InteractionManager { - - constructor( objects ) { - - this._objects = objects; - this._raycaster = new Raycaster(); - this._tempMatrix = new Matrix4(); - - } - - listenPointerEvents() { - - // TODO - - } - - listenXRControllerEvents( controller ) { - - const scope = this; - - const events = { - 'move': 'mousemove', - 'select': 'click', - 'selectstart': 'mousedown', - 'selectend': 'mouseup' - }; - - function onEvent( event ) { - - const controller = event.target; - - scope._tempMatrix.identity().extractRotation( controller.matrixWorld ); - - scope._raycaster.ray.origin.setFromMatrixPosition( controller.matrixWorld ); - scope._raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( scope._tempMatrix ); - - const intersections = scope._raycaster.intersectObjects( scope._objects ); - - if ( intersections.length > 0 ) { - - const intersection = intersections[ 0 ]; - - const object = intersection.object; - const uv = intersection.uv; - - object.material.map.dispatchEvent( events[ event.type ], uv.x, 1 - uv.y ); - - } - - } - - controller.addEventListener( 'move', onEvent ); - controller.addEventListener( 'select', onEvent ); - controller.addEventListener( 'selectstart', onEvent ); - controller.addEventListener( 'selectend', onEvent ); - - } - -} - -export { InteractionManager }; diff --git a/examples/webxr_vr_sandbox.html b/examples/webxr_vr_sandbox.html index e516ff683b..1a1469e1c7 100644 --- a/examples/webxr_vr_sandbox.html +++ b/examples/webxr_vr_sandbox.html @@ -15,8 +15,8 @@ import { Reflector } from './jsm/objects/Reflector.js'; import { VRButton } from './jsm/webxr/VRButton.js'; - import { HTMLMesh } from '../editor/js/libs/three.html.js'; - import { InteractionManager } from './jsm/webxr/InteractionManager.js'; + import { HTMLMesh } from './jsm/interactive/HTMLMesh.js'; + import { InteractiveGroup } from './jsm/interactive/InteractiveGroup.js'; import { XRControllerModelFactory } from './jsm/webxr/XRControllerModelFactory.js'; import { GUI } from './jsm/libs/dat.gui.module.js'; @@ -181,20 +181,19 @@ gui.add( parameters, 'p', 0, 10, 1 ).onChange( onChange ); gui.add( parameters, 'q', 0, 10, 1 ).onChange( onChange ); + const group = new InteractiveGroup( renderer ); + scene.add( group ); + const mesh = new HTMLMesh( gui.domElement ); mesh.position.x = - 1; mesh.position.y = 1; mesh.position.z = - 1; mesh.visible = false; - scene.add( mesh ); + group.add( mesh ); renderer.xr.addEventListener( 'sessionstart', () => { mesh.visible = true; } ); renderer.xr.addEventListener( 'sessionend', () => { mesh.visible = false; } ); - const interaction = new InteractionManager( [ mesh ] ); - interaction.listenXRControllerEvents( controller1 ); - interaction.listenXRControllerEvents( controller2 ); - } function onWindowResize() { -- GitLab