From 96f26a8444d1612bb1465291205964959cf784b0 Mon Sep 17 00:00:00 2001 From: Lee Stemkoski Date: Tue, 22 Mar 2022 12:23:10 -0400 Subject: [PATCH] performance improvements --- js/player-move.js | 94 +++++++++++++++++++++--------------------- js/raycaster-extras.js | 80 ++++++++++++++++++----------------- quest-extras.html | 15 ++++++- 3 files changed, 104 insertions(+), 85 deletions(-) diff --git a/js/player-move.js b/js/player-move.js index 8666ee7..4d75bfb 100644 --- a/js/player-move.js +++ b/js/player-move.js @@ -25,6 +25,9 @@ AFRAME.registerComponent("player-move", { this.moveSpeed = 1; // units per second + // create a vector to store camera direction + this.cameraDirection = new THREE.Vector3(); + // quick turns this.turnReady = true; this.startAngle = 0; @@ -77,7 +80,7 @@ AFRAME.registerComponent("player-move", { tick: function() { // always update deltaTime! - let deltaTime = this.clock.getDelta(); + this.deltaTime = this.clock.getDelta(); if ( !this.enabled ) return; @@ -92,21 +95,21 @@ AFRAME.registerComponent("player-move", { this.raycaster.intersectionDetail.els[0].classList.contains(this.data.navigationMeshClass) ) { // show marker to indicate teleport zone - let point = this.raycaster.intersectionDetail.intersections[0].point; + this.point = this.raycaster.intersectionDetail.intersections[0].point; - let t = this.clock.elapsedTime/3 % 1; - let alpha = Math.min(2*t, 0.5); - this.navTarget1.object3D.position.set(point.x, point.y, point.z); + this.t = this.clock.elapsedTime/3 % 1; + this.alpha = Math.min(2*this.t, 0.5); + this.navTarget1.object3D.position.set(this.point.x, this.point.y, this.point.z); this.navTarget1.object3D.visible = true; - this.navTarget1.object3D.scale.set( 1-t, 1-t, 1 ); - this.navTarget1.object3D.children[0].material.opacity = alpha; + this.navTarget1.object3D.scale.set( 1-this.t, 1-this.t, 1 ); + this.navTarget1.object3D.children[0].material.opacity = this.alpha; - t = (this.clock.elapsedTime/3 + 0.5) % 1; - alpha = Math.min(2*t, 0.5); - this.navTarget2.object3D.position.set(point.x, point.y, point.z); + this.t = (this.clock.elapsedTime/3 + 0.5) % 1; + this.alpha = Math.min(2*this.t, 0.5); + this.navTarget2.object3D.position.set(this.point.x, this.point.y, this.point.z); this.navTarget2.object3D.visible = true; - this.navTarget2.object3D.scale.set( 1-t, 1-t, 1 ); - this.navTarget2.object3D.children[0].material.opacity = alpha; + this.navTarget2.object3D.scale.set( 1-this.t, 1-this.t, 1 ); + this.navTarget2.object3D.children[0].material.opacity = this.alpha; if (this.controllerData.rightTrigger.pressed && !this.fadeInProgress) { @@ -114,7 +117,7 @@ AFRAME.registerComponent("player-move", { this.fadeSphere.object3D.visible = true; this.fadeInProgress = true; this.fadeTime = 0; - this.point = {x:point.x, y:point.y, z:point.z}; + this.teleportPoint = {x:this.point.x, y:this.point.y, z:this.point.z}; } } else @@ -127,15 +130,15 @@ AFRAME.registerComponent("player-move", { // currently teleporting if (this.fadeInProgress) { - this.fadeTime += deltaTime; + this.fadeTime += this.deltaTime; // fade to dark and then to light - let alpha = -Math.abs(this.fadeTime - this.fadeDuration)/this.fadeDuration + 1; - this.fadeSphere.setAttribute("material", "opacity", alpha); + this.alpha = -Math.abs(this.fadeTime - this.fadeDuration)/this.fadeDuration + 1; + this.fadeSphere.setAttribute("material", "opacity", this.alpha); if (this.fadeTime >= this.fadeDuration) { - this.el.object3D.position.set(this.point.x, this.point.y, this.point.z); + this.el.object3D.position.set(this.teleportPoint.x, this.teleportPoint.y, this.teleportPoint.z); } if (this.fadeTime >= 2 * this.fadeDuration) { @@ -150,34 +153,33 @@ AFRAME.registerComponent("player-move", { // move with left joystick (while not pressing left grip); // move faster when pressing trigger - let leftJoystickLength = Math.sqrt(this.controllerData.leftAxisX * this.controllerData.leftAxisX + + this.leftJoystickLength = Math.sqrt(this.controllerData.leftAxisX * this.controllerData.leftAxisX + this.controllerData.leftAxisY * this.controllerData.leftAxisY ); if ( this.data.motionEnabled && - leftJoystickLength > 0.001 && + this.leftJoystickLength > 0.001 && !this.controllerData.leftGrip.pressing ) { - // create a vector to store camera direction - let cameraDirection = new THREE.Vector3(); - this.el.sceneEl.camera.getWorldDirection(cameraDirection); - let cameraAngle = Math.atan2(cameraDirection.z, cameraDirection.x); + // this.cameraDirection: a vector to store camera direction + this.el.sceneEl.camera.getWorldDirection(this.cameraDirection); + this.cameraAngle = Math.atan2(this.cameraDirection.z, this.cameraDirection.x); - let leftJoystickAngle = Math.atan2(this.controllerData.leftAxisY, this.controllerData.leftAxisX); + this.leftJoystickAngle = Math.atan2(this.controllerData.leftAxisY, this.controllerData.leftAxisX); - let moveAngle = cameraAngle + leftJoystickAngle; + this.moveAngle = this.cameraAngle + this.leftJoystickAngle; - let moveDistance = this.moveSpeed * deltaTime; + this.moveDistance = this.moveSpeed * this.deltaTime; // move faster if pressing trigger at same time - moveDistance *= (1 + 9 * this.controllerData.leftTrigger.value); + this.moveDistance *= (1 + 9 * this.controllerData.leftTrigger.value); // convert move distance and angle to right and forward amounts // scale by magnitude of joystick press (smaller press moves player slower) - let moveRight = -leftJoystickLength * Math.sin(moveAngle) * moveDistance; - let moveForward = leftJoystickLength * Math.cos(moveAngle) * moveDistance; + this.moveRight = -this.leftJoystickLength * Math.sin(this.moveAngle) * this.moveDistance; + this.moveForward = this.leftJoystickLength * Math.cos(this.moveAngle) * this.moveDistance; - this.el.object3D.position.x = this.el.object3D.position.x + moveRight; - this.el.object3D.position.z = this.el.object3D.position.z + moveForward; + this.el.object3D.position.x = this.el.object3D.position.x + this.moveRight; + this.el.object3D.position.z = this.el.object3D.position.z + this.moveForward; } // ===================================================================== @@ -187,23 +189,23 @@ AFRAME.registerComponent("player-move", { // while pressing left grip, press left joystick left/right to turn left/right by N degrees; // -or- just press right joystick left/right to turn left/right by N degrees. // joystick must return to rest/center position before turning again - let leftX = this.controllerData.leftAxisX; - let rightX = this.controllerData.rightAxisX; + this.leftX = this.controllerData.leftAxisX; + this.rightX = this.controllerData.rightAxisX; - if ( Math.abs(leftX) < 0.10 && Math.abs(rightX) < 0.10 ) + if ( Math.abs(this.leftX) < 0.10 && Math.abs(this.rightX) < 0.10 ) { this.turnReady = true; } if ( this.data.motionEnabled && this.turnReady && - ((this.controllerData.leftGrip.pressing && Math.abs(leftX) > 0.90) || Math.abs(rightX) > 0.90) + ((this.controllerData.leftGrip.pressing && Math.abs(this.leftX) > 0.90) || Math.abs(this.rightX) > 0.90) ) { this.startAngle = this.el.getAttribute("rotation").y; - if ( leftX > 0.90 || rightX > 0.90 ) + if ( this.leftX > 0.90 || this.rightX > 0.90 ) this.endAngle = this.startAngle - this.turnAngle; - if ( leftX < -0.90 || rightX < -0.90 ) + if ( this.leftX < -0.90 || this.rightX < -0.90 ) this.endAngle = this.startAngle + this.turnAngle; this.turnInProgress = true; @@ -213,10 +215,10 @@ AFRAME.registerComponent("player-move", { if (this.turnInProgress) { - this.turnTime += deltaTime; - let rot = this.el.getAttribute("rotation"); - rot.y = this.lerp(this.startAngle, this.endAngle, this.turnTime/this.turnDuration); - this.el.setAttribute("rotation", rot); + this.turnTime += this.deltaTime; + this.rot = this.el.getAttribute("rotation"); + this.rot.y = this.lerp(this.startAngle, this.endAngle, this.turnTime/this.turnDuration); + this.el.setAttribute("rotation", this.rot); if (this.turnTime >= this.turnDuration) this.turnInProgress = false; @@ -234,13 +236,13 @@ AFRAME.registerComponent("player-move", { this.controllerData.leftGrip.pressing && Math.abs(this.controllerData.leftAxisY) > 0.25 ) { - let y = this.controllerData.leftAxisY; - y = Math.sign(y) * (Math.abs(y) - 1/4); - let moveDistance = -this.moveSpeed * y * deltaTime; + this.y = this.controllerData.leftAxisY; + this.y = Math.sign(this.y) * (Math.abs(this.y) - 1/4); + this.moveDistance = -this.moveSpeed * this.y * this.deltaTime; // move faster if pressing trigger at same time - moveDistance *= (1 + 9 * this.controllerData.leftTrigger.value); + this.moveDistance *= (1 + 9 * this.controllerData.leftTrigger.value); - this.el.object3D.position.y = this.el.object3D.position.y + moveDistance; + this.el.object3D.position.y = this.el.object3D.position.y + this.moveDistance; } } }); diff --git a/js/raycaster-extras.js b/js/raycaster-extras.js index 435ffb8..4575d06 100644 --- a/js/raycaster-extras.js +++ b/js/raycaster-extras.js @@ -41,6 +41,8 @@ AFRAME.registerComponent('raycaster-extras', { this.beamEntity.setAttribute("material", "src", this.data.beamImageSrc); this.beamEntity.setAttribute("material", "color", this.data.beamColor); this.beamEntity.setAttribute("material", "opacity", this.data.beamOpacity); + this.beamColorDefault = new THREE.Color(this.data.beamColor); + this.beamColorActive = new THREE.Color("cyan"); this.el.appendChild(this.beamEntity); @@ -77,50 +79,52 @@ AFRAME.registerComponent('raycaster-extras', { this.clock = new THREE.Clock(); this.moveSpeed = 1; + this.raycasterConfig = null; + }, tick: function () { - let deltaTime = this.clock.getDelta(); + this.deltaTime = this.clock.getDelta(); // change color of beam when interacting with trigger or grip button ================================== if ( this.controllerData.rightTrigger.pressing || this.controllerData.rightGrip.pressing ) - this.beamEntity.setAttribute("material", "color", "cyan"); + this.beamEntity.object3D.children[0].material.color = this.beamColorActive; // setAttribute("material", "color", "cyan"); else - this.beamEntity.setAttribute("material", "color", this.data.beamColor); + this.beamEntity.object3D.children[0].material.color = this.beamColorDefault; // setAttribute("material", "color", this.data.beamColor); // calculate position and rotation of beam ============================================================ // based on model-specific values that customize raycaster line; // note: this data may change when switching from browser to VR mode, so need to keep checking in tick() - let raycasterConfig = this.el.getAttribute("raycaster"); - let currentRayDirection = raycasterConfig.direction; - let currentRayOrigin = raycasterConfig.origin; + if (this.raycasterConfig == null) + this.raycasterConfig = this.el.getAttribute("raycaster"); + + this.currentRayDirection = this.raycasterConfig.direction; + this.currentRayOrigin = this.raycasterConfig.origin; if ( this.currentBeamDirection == null || this.currentBeamOrigin == null || - !this.vectorsEqual(this.currentBeamOrigin, currentRayOrigin) || - !this.vectorsEqual(this.currentBeamDirection, currentRayDirection) ) + !this.vectorsEqual(this.currentBeamOrigin, this.currentRayOrigin) || + !this.vectorsEqual(this.currentBeamDirection, this.currentRayDirection) ) { // align beam rotation with ray direction angle // (beam is always only rotated around x-axis) - let beamAngleX = 180 + Math.atan2(currentRayDirection.z, currentRayDirection.y) * 180/Math.PI; - let rot = {x: beamAngleX, y: 0, z: 0}; - this.beamEntity.setAttribute("rotation", rot); - this.currentBeamDirection = currentRayDirection; + this.beamAngleX = 180 + Math.atan2(this.currentRayDirection.z, this.currentRayDirection.y) * 180/Math.PI; + this.rot = {x: this.beamAngleX, y: 0, z: 0}; + this.beamEntity.setAttribute("rotation", this.rot); + this.currentBeamDirection = this.currentRayDirection; - this.beamAngleX = beamAngleX; - // align beam position with ray origin point // and shift so beam cylinder end is at origin - let angleRad = beamAngleX * Math.PI/180; - let cylinderShift = this.data.beamLength / 2.05; - let pos = { x: currentRayOrigin.x, - y: currentRayOrigin.y - Math.cos(angleRad) * cylinderShift, - z: currentRayOrigin.z - Math.sin(angleRad) * cylinderShift }; - this.beamEntity.setAttribute("position", pos); - this.currentBeamOrigin = currentRayOrigin; + this.angleRad = this.beamAngleX * Math.PI/180; + this.cylinderShift = this.data.beamLength / 2.05; + this.pos = { x: this.currentRayOrigin.x, + y: this.currentRayOrigin.y - Math.cos(this.angleRad) * this.cylinderShift, + z: this.currentRayOrigin.z - Math.sin(this.angleRad) * this.cylinderShift }; + this.beamEntity.setAttribute("position", this.pos); + this.currentBeamOrigin = this.currentRayOrigin; } // update which element has focus =================================================================== @@ -152,21 +156,23 @@ AFRAME.registerComponent('raycaster-extras', { if ( this.focusedElement != null ) { - this.cursorEntity.setAttribute("visible", true) + this.cursorEntity.object3D.visible = true; - this.cursorEntity.setAttribute("position", - { x: this.intersectionPoint.x, - y: this.intersectionPoint.y, - z: this.intersectionPoint.z } ); + this.cursorEntity.object3D.position.set( + this.intersectionPoint.x, + this.intersectionPoint.y, + this.intersectionPoint.z ); // shorten raycaster let dist = this.raycaster.intersectionDetail.intersections[0].distance; - this.el.setAttribute("raycaster", "far", dist + 0.1); + this.raycaster.raycaster.far = dist + 0.1; + // equivalent to: this.el.setAttribute("raycaster", "far", dist + 0.1); } else { - this.cursorEntity.setAttribute("visible", false) - this.el.setAttribute("raycaster", "far", 12); + this.cursorEntity.object3D.visible = false; + this.raycaster.raycaster.far = 12; + // equivalent to: this.el.setAttribute("raycaster", "far", 12); } // grab element ===================================================================================== @@ -187,8 +193,8 @@ AFRAME.registerComponent('raycaster-extras', { // raycaster-graphics keeps setting cursorEntity visible true, // so force cursor hidden by making setting children visibility to false // why? easier to focus on object without cursor in the way. - this.cursorCenter.setAttribute("visible", false); - this.cursorBorder.setAttribute("visible", false); + this.cursorCenter.object3D.visible = false; + this.cursorBorder.object3D.visible = false; // turn off emission (set by raycaster-hover-glow) this.focusedElement.setAttribute("material", "emissive", "#000000"); @@ -222,11 +228,11 @@ AFRAME.registerComponent('raycaster-extras', { // if not pulling entity that is too close, then okay to move it if ( !(this.controllerData.rightAxisY > 0 && distance < 0.05) ) { - let moveDistance = 2 * this.moveSpeed * deltaTime * this.controllerData.rightAxisY; + this.moveDistance = 2 * this.moveSpeed * this.deltaTime * this.controllerData.rightAxisY; // move faster if pressing trigger at same time - moveDistance *= (1 + 1 * this.controllerData.rightTrigger.value); + this.moveDistance *= (1 + 1 * this.controllerData.rightTrigger.value); - this.tempVector.setLength(moveDistance); + this.tempVector.setLength(this.moveDistance); // temporarily attach element back to root scene @@ -241,7 +247,7 @@ AFRAME.registerComponent('raycaster-extras', { let material = this.beamEntity.getAttribute("material"); material.repeat.x = 2; material.repeat.y = 30; - material.offset.y -= 10 * moveDistance; + material.offset.y -= 10 * this.moveDistance; this.beamEntity.setAttribute("material", material); } @@ -268,8 +274,8 @@ AFRAME.registerComponent('raycaster-extras', { material.offset.y = 0.001; this.beamEntity.setAttribute("material", material); - this.cursorCenter.setAttribute("visible", true); - this.cursorBorder.setAttribute("visible", true); + this.cursorCenter.object3D.visible = true; + this.cursorBorder.object3D.visible = true; this.grabbedElement.components["raycaster-target"].isGrabbed = false; diff --git a/quest-extras.html b/quest-extras.html index b52ba88..a4d9fa2 100644 --- a/quest-extras.html +++ b/quest-extras.html @@ -53,11 +53,21 @@ color = "#000337"> + + + + + navigationMeshClass: groundPlane;"> @@ -72,10 +82,11 @@ oculus-touch-controls="hand: left"> +