From 46ede50e8dc762949e11fbc1212c19b4ebec001b Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Mon, 13 Aug 2018 20:46:58 +0200 Subject: [PATCH] Matrix3: Added lookAt() --- src/core/Object3D.js | 13 +++------- src/math/Matrix3.js | 56 ++++++++++++++++++++++++++++++++++++++++++ src/math/Quaternion.js | 23 ++++++++++++----- 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/core/Object3D.js b/src/core/Object3D.js index f707ef717b47b3..c0030a9f7fb1b5 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -307,7 +307,8 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), // This method does not support objects with rotated and/or translated parent(s) - var m1 = new Matrix4(); + var m1 = new Matrix3(); + var targetDirection = new Vector3(); var vector = new Vector3(); return function lookAt( x, y, z ) { @@ -322,15 +323,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), } - if ( this.isCamera ) { - - m1.lookAt( this.position, vector, this.up ); - - } else { - - m1.lookAt( vector, this.position, this.up ); + targetDirection.subVectors( vector, this.position ).normalize(); - } + m1.lookAt( this.forward, targetDirection, this.up ); this.quaternion.setFromRotationMatrix( m1 ); diff --git a/src/math/Matrix3.js b/src/math/Matrix3.js index 5918293a056b8c..66e9bb210d5f9a 100644 --- a/src/math/Matrix3.js +++ b/src/math/Matrix3.js @@ -114,6 +114,62 @@ Object.assign( Matrix3.prototype, { }(), + makeBasis: function ( xAxis, yAxis, zAxis ) { + + this.set( + xAxis.x, yAxis.x, zAxis.x, + xAxis.y, yAxis.y, zAxis.y, + xAxis.z, yAxis.z, zAxis.z + ); + + return this; + + }, + + lookAt: function () { + + var localRight = new Vector3(); + var worldRight = new Vector3(); + var worldUp = new Vector3( 0, 1, 0 ); + var perpWorldUp = new Vector3(); + var temp = new Vector3(); + + var m1 = new Matrix3(); + var m2 = new Matrix3(); + + return function lookAt( localForward, targetDirection, localUp ) { + + localRight.crossVectors( localUp, localForward ).normalize(); + + // orthonormal linear basis A { localRight, localUp, localForward } for the object local space + + worldRight.crossVectors( worldUp, targetDirection ).normalize(); + + if ( worldRight.lengthSq() === 0 ) { + + // handle case when it's not possible to build a basis from targetDirection and worldUp + // slightly shift targetDirection in order to avoid collinearity + + temp.copy( targetDirection ).addScalar( Number.EPSILON ); + worldRight.crossVectors( worldUp, temp ).normalize(); + + } + + perpWorldUp.crossVectors( targetDirection, worldRight ).normalize(); + + // orthonormal linear basis B { worldRight, perpWorldUp, targetDirection } for the desired target orientation + + m1.makeBasis( worldRight, perpWorldUp, targetDirection ); + m2.makeBasis( localRight, localUp, localForward ); + + // construct a matrix that maps basis A to B + + this.multiplyMatrices( m1, m2.transpose() ); + + }; + + }(), + multiply: function ( m ) { return this.multiplyMatrices( this, m ); diff --git a/src/math/Quaternion.js b/src/math/Quaternion.js index 019823e932034a..decc3ad03a27f8 100644 --- a/src/math/Quaternion.js +++ b/src/math/Quaternion.js @@ -295,14 +295,25 @@ Object.assign( Quaternion.prototype, { // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) - var te = m.elements, + var te = m.elements; - m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], - m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], - m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], + var m11, m12, m13, m21, m22, m23, m31, m32, m33; - trace = m11 + m22 + m33, - s; + if ( m.isMatrix3 ) { + + m11 = te[ 0 ]; m12 = te[ 3 ]; m13 = te[ 6 ]; + m21 = te[ 1 ]; m22 = te[ 4 ]; m23 = te[ 7 ]; + m31 = te[ 2 ]; m32 = te[ 5 ]; m33 = te[ 8 ]; + + } else { + + m11 = te[ 0 ]; m12 = te[ 4 ]; m13 = te[ 8 ]; + m21 = te[ 1 ]; m22 = te[ 5 ]; m23 = te[ 9 ]; + m31 = te[ 2 ]; m32 = te[ 6 ]; m33 = te[ 10 ]; + + } + + var trace = m11 + m22 + m33, s; if ( trace > 0 ) {