diff --git a/docs/api/en/math/Quaternion.html b/docs/api/en/math/Quaternion.html index 9ec3b57657d205..daa1d27a37816b 100644 --- a/docs/api/en/math/Quaternion.html +++ b/docs/api/en/math/Quaternion.html @@ -138,6 +138,11 @@

[method:Quaternion multiplyQuaternions]( [param:Quaternion a], [param:Quater

[method:Quaternion premultiply]( [param:Quaternion q] )

Pre-multiplies this quaternion by [page:Quaternion q].

+

[method:Quaternion random]()

+

+ Sets this quaternion to a uniformly random, normalized quaternion. +

+

[method:Quaternion rotateTowards]( [param:Quaternion q], [param:Float step] )

[page:Quaternion q] - The target quaternion.
diff --git a/docs/api/en/math/Vector3.html b/docs/api/en/math/Vector3.html index 6cefd16889c817..a073479b6ce9d3 100644 --- a/docs/api/en/math/Vector3.html +++ b/docs/api/en/math/Vector3.html @@ -440,6 +440,11 @@

[method:this random]()

Sets each component of this vector to a pseudo-random value between 0 and 1, excluding 1.

+

[method:this randomDirection]()

+

+ Sets this vector to a uniformly random point on a unit sphere. +

+

Source

diff --git a/src/math/Quaternion.js b/src/math/Quaternion.js index 9078a612eccc53..485fe86537828e 100644 --- a/src/math/Quaternion.js +++ b/src/math/Quaternion.js @@ -608,6 +608,29 @@ class Quaternion { } + random() { + + // Derived from http://planning.cs.uiuc.edu/node198.html + // Note, this source uses w, x, y, z ordering, + // so we swap the order below. + + const u1 = Math.random(); + const sqrt1u1 = Math.sqrt( 1 - u1 ); + const sqrtu1 = Math.sqrt( u1 ); + + const u2 = 2 * Math.PI * Math.random(); + + const u3 = 2 * Math.PI * Math.random(); + + return this.set( + sqrt1u1 * Math.cos( u2 ), + sqrtu1 * Math.sin( u3 ), + sqrtu1 * Math.cos( u3 ), + sqrt1u1 * Math.sin( u2 ), + ); + + } + equals( quaternion ) { return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); diff --git a/src/math/Vector3.js b/src/math/Vector3.js index ecdd6c1a73cfab..df2e778275c187 100644 --- a/src/math/Vector3.js +++ b/src/math/Vector3.js @@ -711,6 +711,22 @@ class Vector3 { } + randomDirection() { + + // Derived from https://mathworld.wolfram.com/SpherePointPicking.html + + const u = ( Math.random() - 0.5 ) * 2; + const t = Math.random() * Math.PI * 2; + const f = Math.sqrt( 1 - u ** 2 ); + + this.x = f * Math.cos( t ); + this.y = f * Math.sin( t ); + this.z = u; + + return this; + + } + } Vector3.prototype.isVector3 = true; diff --git a/test/unit/src/math/Quaternion.tests.js b/test/unit/src/math/Quaternion.tests.js index c14a98c9735bc9..fda8f48284f905 100644 --- a/test/unit/src/math/Quaternion.tests.js +++ b/test/unit/src/math/Quaternion.tests.js @@ -673,6 +673,23 @@ export default QUnit.module( 'Maths', () => { } ); + QUnit.test( "random", ( assert ) => { + + var a = new Quaternion(); + + a.random(); + + var identity = new Quaternion(); + assert.notDeepEqual( + a, + identity, + 'randomizes at least one component of the quaternion' + ); + + assert.ok( ( 1 - a.length() ) <= Number.EPSILON, 'produces a normalized quaternion' ); + + } ); + QUnit.test( "equals", ( assert ) => { var a = new Quaternion( x, y, z, w ); diff --git a/test/unit/src/math/Vector3.tests.js b/test/unit/src/math/Vector3.tests.js index af7a97e7c9132d..ff4fbb39a686d6 100644 --- a/test/unit/src/math/Vector3.tests.js +++ b/test/unit/src/math/Vector3.tests.js @@ -989,6 +989,23 @@ export default QUnit.module( 'Maths', () => { } ); + QUnit.test( 'randomDirection', ( assert ) => { + + var vec = new Vector3(); + + vec.randomDirection(); + + var zero = new Vector3(); + assert.notDeepEqual( + vec, + zero, + 'randomizes at least one component of the vector' + ); + + assert.ok( ( 1 - vec.length() ) <= Number.EPSILON, 'produces a unit vector' ); + + } ); + } ); } );