Garrett Johnson пре 4 година
родитељ
комит
fcec5d9196
2 измењених фајлова са 235 додато и 95 уклоњено
  1. 231 0
      example/FlyOrbitControls.js
  2. 4 95
      example/index.js

+ 231 - 0
example/FlyOrbitControls.js

@@ -0,0 +1,231 @@
+import { Vector3, Vector4 } from 'three';
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
+
+const tempVector = new Vector4( 0, 0, 0, 0 );
+export class FlyOrbitControls extends OrbitControls {
+
+	constructor( camera, domElement ) {
+
+		super( camera, domElement );
+
+		domElement.tabIndex = 1;
+
+		this.baseSpeed = 1;
+		this.fastSpeed = 4;
+		this.forwardKey = 'w';
+		this.backKey = 's';
+		this.leftKey = 'a';
+		this.rightKey = 'd';
+		this.upKey = 'q';
+		this.downKey = 'e';
+		this.fastKey = 'shift';
+
+		let fastHeld = false;
+		let forwardHeld = false;
+		let backHeld = false;
+		let leftHeld = false;
+		let rightHeld = false;
+		let upHeld = false;
+		let downHeld = false;
+
+		let originalDistance = 0
+		let originalMinDistance = 0;
+		let originalMaxDistance = 0;
+		let rafHandle = - 1;
+		const originalTarget = new Vector3();
+
+		const endFlight = () => {
+
+			if ( rafHandle !== - 1 ) {
+
+				cancelAnimationFrame( rafHandle );
+				rafHandle = - 1;
+
+			}
+
+			this.minDistance = originalMinDistance;
+			this.maxDistance = originalMaxDistance;
+
+			const targetDistance = Math.min( originalDistance, camera.position.distanceTo( originalTarget ) );
+			this
+				.target
+				.set( 0, 0, - targetDistance )
+				.applyMatrix4( camera.matrixWorld );
+
+		};
+
+		const updateFlight = () => {
+
+			rafHandle = requestAnimationFrame( updateFlight );
+
+			const speed = fastHeld ? this.fastSpeed : this.baseSpeed;
+			tempVector.set( 0, 0, 0, 0 );
+			if ( forwardHeld ) tempVector.z -= 1;
+			if ( backHeld ) tempVector.z += 1;
+			if ( leftHeld ) tempVector.x -= 1;
+			if ( rightHeld ) tempVector.x += 1;
+			if ( upHeld ) tempVector.y += 1;
+			if ( downHeld ) tempVector.y -= 1;
+
+			tempVector.applyMatrix4( camera.matrixWorld );
+			camera
+				.position
+				.addScaledVector( tempVector, speed );
+			this
+				.target
+				.addScaledVector( tempVector, speed );
+
+		};
+		this.updateFlight = updateFlight;
+
+		const keyDownCallback = e => {
+
+			const key = e.key.toLowerCase();
+
+			if ( rafHandle === - 1 ) {
+
+				originalMaxDistance = this.maxDistance;
+				originalMinDistance = this.minDistance;
+				originalDistance = camera.position.distanceTo( this.target );
+				originalTarget.copy( this.target );
+
+			}
+
+			switch ( key ) {
+
+				case this.forwardKey:
+					forwardHeld = true;
+					break;
+				case this.backKey:
+					backHeld = true;
+					break;
+				case this.leftKey:
+					leftHeld = true;
+					break;
+				case this.rightKey:
+					rightHeld = true;
+					break;
+				case this.upKey:
+					upHeld = true;
+					break;
+				case this.downKey:
+					downHeld = true;
+					break;
+				case this.fastKey:
+					fastHeld = true;
+					break;
+
+			}
+
+			switch ( key ) {
+
+				case this.fastKey:
+				case this.forwardKey:
+				case this.backKey:
+				case this.leftKey:
+				case this.rightKey:
+				case this.upKey:
+				case this.downKey:
+					e.stopPropagation();
+					e.preventDefault();
+
+			}
+
+			if ( forwardHeld || backHeld || leftHeld || rightHeld || upHeld || downHeld ) {
+
+				this.minDistance = 0.01;
+				this.maxDistance = 0.01;
+
+				tempVector.set( 0, 0, - 1, 0 ).applyMatrix4( camera.matrixWorld );
+				this.target.copy( camera.position ).addScaledVector( tempVector, 0.01 );
+
+				if ( rafHandle === - 1 ) {
+
+					updateFlight();
+
+				}
+
+			}
+
+		};
+
+		const keyUpCallback = e => {
+
+			const key = e.key.toLowerCase();
+
+			switch( key ) {
+
+				case this.forwardKey:
+					forwardHeld = false;
+					break;
+				case this.backKey:
+					backHeld = false;
+					break;
+				case this.leftKey:
+					leftHeld = false;
+					break;
+				case this.rightKey:
+					rightHeld = false;
+					break;
+				case this.upKey:
+					upHeld = false;
+					break;
+				case this.downKey:
+					downHeld = false;
+					break;
+				case this.fastKey:
+					fastHeld = false;
+					break;
+
+			}
+
+			switch ( key ) {
+
+				case this.fastKey:
+				case this.forwardKey:
+				case this.backKey:
+				case this.leftKey:
+				case this.rightKey:
+				case this.upKey:
+				case this.downKey:
+					e.stopPropagation();
+					e.preventDefault();
+
+			}
+
+			if ( ! ( forwardHeld || backHeld || leftHeld || rightHeld || upHeld || downHeld ) ) {
+
+				endFlight();
+
+			}
+
+		};
+
+		const blurCallback = () => {
+
+			endFlight();
+
+		};
+
+		this.blurCallback = blurCallback;
+		this.keyDownCallback = keyDownCallback;
+		this.keyUpCallback = keyUpCallback;
+
+		this.domElement.addEventListener( 'blur', blurCallback );
+		this.domElement.addEventListener( 'keydown', keyDownCallback );
+		this.domElement.addEventListener( 'keyup', keyUpCallback );
+
+	}
+
+	dispose() {
+
+		super.dispose();
+
+		this.domElement.addEventListener( 'blur', this.blurCallback );
+		this.domElement.addEventListener( 'keydown', this.keyDownCallback );
+		this.domElement.addEventListener( 'keyup', this.keyUpCallback );
+
+	}
+
+
+}

+ 4 - 95
example/index.js

@@ -29,7 +29,7 @@ import {
 	Vector4,
 	Vector3,
 } from 'three';
-import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
+import { FlyOrbitControls } from './FlyOrbitControls.js';
 import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
 import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
 import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
@@ -152,7 +152,7 @@ function init() {
 	secondRenderer.domElement.style.top = '0';
 	secondRenderer.domElement.style.outline = '#0f1416 solid 2px';
 
-	secondControls = new OrbitControls( secondCamera, secondRenderer.domElement );
+	secondControls = new FlyOrbitControls( secondCamera, secondRenderer.domElement );
 	secondControls.screenSpacePanning = false;
 	secondControls.minDistance = 1;
 	secondControls.maxDistance = 2000;
@@ -176,13 +176,13 @@ function init() {
 	thirdPersonRenderer.domElement.style.left = '5px';
 	thirdPersonRenderer.domElement.style.bottom = '5px';
 
-	thirdPersonControls = new OrbitControls( thirdPersonCamera, thirdPersonRenderer.domElement );
+	thirdPersonControls = new FlyOrbitControls( thirdPersonCamera, thirdPersonRenderer.domElement );
 	thirdPersonControls.screenSpacePanning = false;
 	thirdPersonControls.minDistance = 1;
 	thirdPersonControls.maxDistance = 2000;
 
 	// controls
-	controls = new OrbitControls( camera, renderer.domElement );
+	controls = new FlyOrbitControls( camera, renderer.domElement );
 	controls.screenSpacePanning = false;
 	controls.minDistance = 1;
 	controls.maxDistance = 2000;
@@ -305,92 +305,6 @@ function init() {
 	stats.showPanel( 0 );
 	document.body.appendChild( stats.dom );
 
-	window.addEventListener( 'keydown', e => {
-
-		if ( moveDirection.length() === 0 ) {
-
-			originalDistance = camera.position.distanceTo( controls.target );
-			originalTarget.copy( controls.target );
-
-		}
-
-		switch ( e.key ) {
-
-			case 'w':
-				moveDirection.z = - 1;
-				break;
-			case 's':
-				moveDirection.z = 1;
-				break;
-			case 'a':
-				moveDirection.x = - 1;
-				break;
-			case 'd':
-				moveDirection.x = 1;
-				break;
-			case 'q':
-				moveDirection.y = 1;
-				break;
-			case 'e':
-				moveDirection.y = - 1;
-				break;
-			case 'r':
-				console.log( originalDistance );
-				moveDirection.set( 0, 0, - 1, 0 ).applyMatrix4( camera.matrixWorld );
-				controls.target.set( 0, 0, 0 );
-				camera.position.set( 0, 0, 0 ).addScaledVector( moveDirection, - originalDistance );
-				moveDirection.set( 0, 0, 0, 0 );
-				break;
-
-		}
-
-		if ( moveDirection.length() !== 0 ) {
-
-			const vec = new Vector4( 0, 0, - 1, 0 );
-			vec.applyMatrix4( camera.matrixWorld );
-			controls.minDistance = 0.01;
-			controls.maxDistance = 0.01;
-			controls.target.copy( camera.position ).addScaledVector( vec, 0.01 );
-
-		}
-
-	} );
-
-	window.addEventListener( 'keyup', e => {
-
-		switch( e.key ) {
-
-			case 'w':
-			case 's':
-				moveDirection.z = 0;
-				break;
-			case 'a':
-			case 'd':
-				moveDirection.x = 0;
-				break;
-			case 'q':
-			case 'e':
-				moveDirection.y = 0;
-				break;
-
-		}
-
-		if ( moveDirection.length() === 0 ) {
-
-			const vec = new Vector4( 0, 0, - 1, 0 );
-			vec.applyMatrix4( camera.matrixWorld );
-			controls.minDistance = 1;
-			controls.maxDistance = 2000;
-			controls
-				.target
-				.copy( camera.position )
-				.addScaledVector( vec, Math.min( originalDistance, camera.position.distanceTo( originalTarget ) ) );
-
-		}
-
-
-	} );
-
 }
 
 function onWindowResize() {
@@ -654,11 +568,6 @@ function animate() {
 
 function render() {
 
-	const dir = new Vector4();
-	dir.copy( moveDirection ).applyMatrix4( camera.matrixWorld );
-	camera.position.addScaledVector( dir, 1.5 );
-	controls.target.addScaledVector( dir, 1.5 );
-
 	updateOrthoCamera();
 
 	cameraHelper.visible = false;