three.js 源代码凝视(七)Math/Euler.js
生活随笔
收集整理的這篇文章主要介紹了
three.js 源代码凝视(七)Math/Euler.js
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
商域無疆 (http://blog.csdn.net/omni360/)
本文遵循“署名-非商業用途-保持一致”創作公用協議
轉載請保留此句:商域無疆 - ?本博客專注于?敏捷開發及移動和物聯設備研究:數據可視化、GOLANG、Html5、WEBGL、THREE.JS,否則,出自本博客的文章拒絕轉載或再轉載,謝謝合作。
下面代碼是THREE.JS 源代碼文件里Math/Quaternion.js文件的凝視.
很多其它更新在 :?https://github.com/omni360/three.js.sourcecode/blob/master/Three.js
// File:src/math/Euler.js/*** @author mrdoob / http://mrdoob.com/* @author WestLangley / http://github.com/WestLangley* @author bhouston / http://exocortex.com*/ /* ///Euler對象的構造函數.用來創建一個歐拉角的對象.Euler對象的功能函數採用 ///定義構造的函數原型對象來實現. /// /// 使用方法: var euler = new Euler(5,3,2,'XYZ') /// 創建一個繞某軸旋轉5度,繞y軸旋轉某度,繞某軸旋轉2度,旋轉順序為'XYZ'.有了旋轉順序才干確定每一個x,y,z軸分別旋轉多少度. /// NOTE: 參數x,y,z代表3個軸的旋轉角度,具體哪個軸旋轉多少度,須要后面的參數(order)旋轉順序來確定. /// NOTE: 參數(x,y,z,order)為可選參數,假設不指定參數(x,y,z,order),將創建一個坐標為(0,0,0,'XYZ')的Eular(歐拉角)對象. /// NOTE: 參數order(旋轉順序) 默認順序是'XYZ' 取值范圍是['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ] /// /// 通俗的講,歐拉角就是用來描寫敘述一個物體在三維空間中方向的一種經常使用的方法.舉例來說,一個物體在三維空間中,繞x軸轉了多少度, /// y軸轉了多少度,z軸轉了多少度,來描寫敘述物體在三維空間中的方向. /// 有點相似香港電影里飛虎隊隊員之間說,"飛鷹,飛鷹,在你的正前方,5點鐘方向,發現目標,準備聚集目標." /// */ ///<summary>Euler</summary> ///<param name ="x" type="number">繞某軸旋轉x度</param> ///<param name ="y" type="number">繞某軸旋轉y度</param> ///<param name ="z" type="number">繞某軸旋轉z度</param> ///<param name ="order" type="String">order(旋轉順序) 默認順序是'XYZ' 取值范圍是['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]</param>THREE.Euler = function ( x, y, z, order ) {this._x = x || 0;this._y = y || 0;this._z = z || 0;this._order = order || THREE.Euler.DefaultOrder;};THREE.Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]; //(旋轉順序) 默認順序是'XYZ' 取值范圍是['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]THREE.Euler.DefaultOrder = 'XYZ'; //默認的旋轉順序為'XYZ'/**************************************** ****以下是Euler對象提供的功能函數. ****************************************/THREE.Euler.prototype = {constructor: THREE.Euler, //構造器_x: 0, _y: 0, _z: 0, _order: THREE.Euler.DefaultOrder, //將(_x,_y,_z,_order)初始化x,y,z為0,旋轉順序為默認旋轉順序'XYZ';/*///get x 方法用來獲取euler角x值.///NOTE: get x()的使用方法是Euler.prototype.x(Euler.x),這樣的使用方法在除ie瀏覽器以外的瀏覽器上能夠使用.*////<summary>get x</summary>///<returns type="number">返回euler角_x值</returns>get x () {return this._x; //返回euler角_x值},/*///set x 方法用來從新設置Euler角的x值.并返回新的值的Euler角.///NOTE: set x()的使用方法是Euler.prototype.x=value(Euler.x = value),這樣的使用方法在除ie瀏覽器以外的瀏覽器上能夠使用.*////<summary>set x</summary>///<param name ="value" type="number">繞x軸旋轉的角度值</param>set x ( value ) {this._x = value; //設置Euler角的_x值this.onChangeCallback(); //調用回調函數.},/*///get y 方法用來從獲取euler角y值.///NOTE: get y()的使用方法是Euler.prototype.y(Euler.y),這樣的使用方法在除ie瀏覽器以外的瀏覽器上能夠使用.*////<summary>get y</summary>///<returns type="number">返回euler角_y值</returns>get y () {return this._y; //返回euler角_y值},/*///set y 方法用來從新設置Euler角的y值.并返回新的值的Euler角.///NOTE: set y()的使用方法是Euler.prototype.y=value(Euler.y = value),這樣的使用方法在除ie瀏覽器以外的瀏覽器上能夠使用.*////<summary>set y</summary>///<param name ="value" type="number">繞y軸旋轉的角度值</param>set y ( value ) {this._y = value; //設置Euler角的_y值this.onChangeCallback(); //調用回調函數.},/*///get z 方法用來獲取euler角z值.///NOTE: get z()的使用方法是Euler.prototype.z(Euler.z),這樣的使用方法在除ie瀏覽器以外的瀏覽器上能夠使用.*////<summary>get z</summary>///<returns type="number">返回euler角_z值</returns>get z () {return this._z; //返回euler角_z值},/*///set z 方法用來從新設置Euler角的z值.并返回新的值的Euler角.///NOTE: set z()的使用方法是Euler.prototype.z=value(Euler.z = value),這樣的使用方法在除ie瀏覽器以外的瀏覽器上能夠使用.*////<summary>set z</summary>///<param name ="value" type="number">繞z軸旋轉的角度值</param>set z ( value ) {this._z = value; //設置Euler角的_z值this.onChangeCallback(); //調用回調函數.},/*///get order 方法用來獲取euler角order值.///NOTE: get order()的使用方法是Euler.prototype.order(Euler.order),這樣的使用方法在除ie瀏覽器以外的瀏覽器上能夠使用.*////<summary>get order</summary>///<returns type="number">返回euler角_z值</returns>get order () {return this._order; //返回euler角_order值},/*///set order 方法用來從新設置Euler角的order值.并返回新的值的Euler角.///NOTE: set order()的使用方法是Euler.prototype.order=value(Euler.order = value),這樣的使用方法在除ie瀏覽器以外的瀏覽器上能夠使用./// NOTE: 參數(x,y,z,order)為可選參數,假設不指定參數(x,y,z,order),將創建一個坐標為(0,0,0,'XYZ')的Eular(歐拉角)對象./// NOTE: 參數order(旋轉順序) 默認順序是'XYZ' 取值范圍是['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]*////<summary>set order</summary>///<param name ="value" type="number">繞z軸旋轉的角度值</param>set order ( value ) {this._order = value; //設置Euler角的_order值this.onChangeCallback(); //調用回調函數.},///TODO:這里缺少setX()方法.///TODO:這里缺少setY()方法.///TODO:這里缺少setZ()方法.///TODO:這里缺少setW()方法.///TODO:這里缺少setComponent()方法.///TODO:這里缺少getComponent()方法./*///set方法用來從新設置Euler(歐拉角)的x,y,z,order值.并返回新的坐標值的Euler(歐拉角)./// TODO:改動set方法,兼容x,y,z,order參數省略支持多態.*////<summary>set</summary>///<param name ="x" type="number">繞某軸旋轉x度</param>///<param name ="y" type="number">繞某軸旋轉y度</param>///<param name ="z" type="number">繞某軸旋轉z度</param>///<param name ="order" type="number">order(旋轉順序) 默認順序是'XYZ' 取值范圍是['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]</param>///<returns type="Euler(歐拉角)">返回新的Euler(歐拉角)</returns>set: function ( x, y, z, order ) {this._x = x;this._y = y;this._z = z;this._order = order || this._order;this.onChangeCallback(); //調用回調函數.return this; //返回新的Euler(歐拉角)},/*///copy方法用來復制Euler(歐拉角)的(x,y,z,order)值.并返回新的Euler(歐拉角).*////<summary>copy</summary>///<param name ="euler(歐拉角)" type="Quaternion">Euler(歐拉角)</param>///<returns type="Euler(歐拉角)">返回新的Euler(歐拉角)</returns> copy: function ( euler ) {this._x = euler._x;this._y = euler._y;this._z = euler._z;this._order = euler._order;this.onChangeCallback(); //調用回調函數.return this; //返回新的Euler(歐拉角)},/*///setFromRotationMatrix方法利用一個參數m(旋轉矩陣),達到旋轉變換的目的吧./// NOTE:m是一個旋轉矩陣,很多其它公式:http://en.wikipedia.org/wiki/Transformation_matrix/// /// 例子:這個例子是z軸旋轉30度./----------------------------------------------------\|cos(heading) = 0.866 | sin(heading) = 0.5 | 0 ||-----------------------|----------------------------|matrix = |-sin(heading) = -0.5 |cos(heading) = 0.866 | 0 ||-----------------------|----------------------|-----|| 0 | 0 | 1 |\----------------------------------------------------/angle = acos ( ( m00 + m11 + m22 - 1)/2)angle = acos ( ( 0.866 + 0.866 + 1 - 1)/2)angle = acos ( 0.866 )angle = 30 degreesx = (m21 - m12) = 0 - 0 =0y = (m02 - m20) = 0 - 0 =0z = (m10 - m01) = -0.5 - 0.5 = -1*////<summary>setFromRotationMatrix</summary>///<param name ="m" type="Matrix3">3x3矩陣(旋轉矩陣)</param>///<param name ="order" type="String">order(旋轉順序) 默認順序是'XYZ' 取值范圍是['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]</param>///<returns type="Euler(歐拉角)">返回新的Euler(歐拉角)</returns>setFromRotationMatrix: function ( m, order ) {var clamp = THREE.Math.clamp; //clamp用來設置數值的取值范圍// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)// 確保參數m是一個3x3的旋轉矩陣.var te = m.elements;var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];order = order || this._order;if ( order === 'XYZ' ) {this._y = Math.asin( clamp( m13, - 1, 1 ) );if ( Math.abs( m13 ) < 0.99999 ) {this._x = Math.atan2( - m23, m33 );this._z = Math.atan2( - m12, m11 );} else {this._x = Math.atan2( m32, m22 );this._z = 0;}} else if ( order === 'YXZ' ) {this._x = Math.asin( - clamp( m23, - 1, 1 ) );if ( Math.abs( m23 ) < 0.99999 ) {this._y = Math.atan2( m13, m33 );this._z = Math.atan2( m21, m22 );} else {this._y = Math.atan2( - m31, m11 );this._z = 0;}} else if ( order === 'ZXY' ) {this._x = Math.asin( clamp( m32, - 1, 1 ) );if ( Math.abs( m32 ) < 0.99999 ) {this._y = Math.atan2( - m31, m33 );this._z = Math.atan2( - m12, m22 );} else {this._y = 0;this._z = Math.atan2( m21, m11 );}} else if ( order === 'ZYX' ) {this._y = Math.asin( - clamp( m31, - 1, 1 ) );if ( Math.abs( m31 ) < 0.99999 ) {this._x = Math.atan2( m32, m33 );this._z = Math.atan2( m21, m11 );} else {this._x = 0;this._z = Math.atan2( - m12, m22 );}} else if ( order === 'YZX' ) {this._z = Math.asin( clamp( m21, - 1, 1 ) );if ( Math.abs( m21 ) < 0.99999 ) {this._x = Math.atan2( - m23, m22 );this._y = Math.atan2( - m31, m11 );} else {this._x = 0;this._y = Math.atan2( m13, m33 );}} else if ( order === 'XZY' ) {this._z = Math.asin( - clamp( m12, - 1, 1 ) );if ( Math.abs( m12 ) < 0.99999 ) {this._x = Math.atan2( m32, m22 );this._y = Math.atan2( m13, m11 );} else {this._x = Math.atan2( - m23, m33 );this._y = 0;}} else {console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order ) //通過依照以上幾種旋轉順序設置歐拉角對象失敗報錯}this._order = order; //又一次設置旋轉順序this.onChangeCallback(); //調用回調函數.return this; //返回新的Euler(歐拉角)},/*///setFromQuaternion方法通過四元數設置Euler(歐拉角)./// NOTE:參數(q)必須是單位向量,通過調用.normalize()得到單位向量./// NOTE:參數update是一個可選參數.假設不設置默覺得true.*////<summary>setFromQuaternion</summary>///<param name ="q" type="Quaternion">四元數</param>///<param name ="order" type="String">旋轉順序</param>///<param name ="update" type="bool">update表示是否調用回調函數bool型標記值</param>///<returns type="Euler(歐拉角)">返回新的Euler(歐拉角)</returns>setFromQuaternion: function ( q, order, update ) {var clamp = THREE.Math.clamp; //clamp用來設置數值的取值范圍// q is assumed to be normalized// 確保q是一個單位向量// 以下網址是對四元數轉換成歐拉角的一個具體的介紹.里面有好多的數學算法.// http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.mvar sqx = q.x * q.x;var sqy = q.y * q.y;var sqz = q.z * q.z;var sqw = q.w * q.w;order = order || this._order;if ( order === 'XYZ' ) {this._x = Math.atan2( 2 * ( q.x * q.w - q.y * q.z ), ( sqw - sqx - sqy + sqz ) );this._y = Math.asin( clamp( 2 * ( q.x * q.z + q.y * q.w ), - 1, 1 ) );this._z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw + sqx - sqy - sqz ) );} else if ( order === 'YXZ' ) {this._x = Math.asin( clamp( 2 * ( q.x * q.w - q.y * q.z ), - 1, 1 ) );this._y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw - sqx - sqy + sqz ) );this._z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw - sqx + sqy - sqz ) );} else if ( order === 'ZXY' ) {this._x = Math.asin( clamp( 2 * ( q.x * q.w + q.y * q.z ), - 1, 1 ) );this._y = Math.atan2( 2 * ( q.y * q.w - q.z * q.x ), ( sqw - sqx - sqy + sqz ) );this._z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw - sqx + sqy - sqz ) );} else if ( order === 'ZYX' ) {this._x = Math.atan2( 2 * ( q.x * q.w + q.z * q.y ), ( sqw - sqx - sqy + sqz ) );this._y = Math.asin( clamp( 2 * ( q.y * q.w - q.x * q.z ), - 1, 1 ) );this._z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw + sqx - sqy - sqz ) );} else if ( order === 'YZX' ) {this._x = Math.atan2( 2 * ( q.x * q.w - q.z * q.y ), ( sqw - sqx + sqy - sqz ) );this._y = Math.atan2( 2 * ( q.y * q.w - q.x * q.z ), ( sqw + sqx - sqy - sqz ) );this._z = Math.asin( clamp( 2 * ( q.x * q.y + q.z * q.w ), - 1, 1 ) );} else if ( order === 'XZY' ) {this._x = Math.atan2( 2 * ( q.x * q.w + q.y * q.z ), ( sqw - sqx + sqy - sqz ) );this._y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw + sqx - sqy - sqz ) );this._z = Math.asin( clamp( 2 * ( q.z * q.w - q.x * q.y ), - 1, 1 ) );} else {console.warn( 'THREE.Euler: .setFromQuaternion() given unsupported order: ' + order ) //通過依照以上幾種旋轉順序設置歐拉角對象失敗報錯}this._order = order; //又一次設置旋轉順序if ( update !== false ) this.onChangeCallback(); //通過update參數推斷是否調用回調函數.return this; //返回新的Euler(歐拉角)},/*///reorder方法通過四元數設置Euler(歐拉角)的旋轉順序./// NOTE:參數(q)必須是單位向量,通過調用.normalize()得到單位向量./// WARNING: reorder 方法將丟棄Euler(歐拉角)的旋轉順序信息.*////<summary>reorder</summary>///<param name ="order" type="String">旋轉順序</param>///<returns type="Euler(歐拉角)">返回新的Euler(歐拉角)</returns>reorder: function () {// WARNING: reorder 方法將丟棄Euler(歐拉角)的旋轉順序信息.// WARNING: this discards revolution information -bhoustonvar q = new THREE.Quaternion();return function ( newOrder ) {q.setFromEuler( this );this.setFromQuaternion( q, newOrder ); //調用setFromQuaternion()方法,返回新旋轉順序的Euler(歐拉角)};}(),/*equals方法///equals方法相當于比較運算符===,將當前Euler(歐拉角)和參數euler中的(x,y,z,order)值進行對照,返回bool型值.*////<summary>equals</summary>///<param name ="v" type="Euler(歐拉角)">Euler(歐拉角)(x,y,z,order)</param>///<returns type="bool">返回true or false</returns> equals: function ( euler ) {return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );},/*fromArray方法///fromArray方法將存儲Euler(歐拉角)(x,y,z,order)值的數組賦值給當前Euler(歐拉角)對象/// NOTE:參數order是一個可選參數.假設不設置使用默認的旋轉順序.*////<summary>fromArray</summary>///<param name ="array" type="Array">Euler(歐拉角)(x,y,z,order)值數組array[x,y,z,order]</param>///<returns type="Euler(歐拉角)">返回新的Euler(歐拉角)</returns> fromArray: function ( array ) {this._x = array[ 0 ];this._y = array[ 1 ];this._z = array[ 2 ];if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];this.onChangeCallback(); //調用回調函數.return this; //返回新的Euler(歐拉角)},/*toArray方法///toArray方法將當前Euler(歐拉角)對象的屬性賦值給數組array[5,3,2,'XYZ'].返回一個數組對象.*////<summary>toArray</summary>///<returns type="Array">Euler(歐拉角)(_x,_y,_z,_order)值數組array[x,y,z,order]</returns> toArray: function () {return [ this._x, this._y, this._z, this._order ]; //返回一個包括x,y,z,order數值的數組,},/*onChange方法///onChange方法在將回調函數表達式作為callback參數傳遞給onChangeCallback()方法.*////<summary>onChange</summary>///<param name ="callback" type="function">回調函數</param>///<returns type="Euler(歐拉角)">Euler(歐拉角)</returns> onChange: function ( callback ) {this.onChangeCallback = callback;return this;},/*onChangeCallback方法///onChangeCallback方法克隆一個Euler(歐拉角)對象.///NOTE:onChangeCallback()方法在這里就是一個空的函數屬性,在上面大部分的方法中都調用了onChangeCallback()方法,這是一種非常方便的方法.*////<summary>onChangeCallback</summary>onChangeCallback: function () {},/*clone方法///clone方法克隆一個Euler(歐拉角)對象.*////<summary>clone</summary>///<returns type="Euler(歐拉角)">返回Euler(歐拉角)對象</returns> clone: function () {return new THREE.Euler( this._x, this._y, this._z, this._order );}};
商域無疆 (http://blog.csdn.net/omni360/)
本文遵循“署名-非商業用途-保持一致”創作公用協議
轉載請保留此句:商域無疆 - ?本博客專注于?敏捷開發及移動和物聯設備研究:數據可視化、GOLANG、Html5、WEBGL、THREE.JS,否則,出自本博客的文章拒絕轉載或再轉載,謝謝合作。
下面代碼是THREE.JS 源代碼文件里Math/Quaternion.js文件的凝視.
很多其它更新在 :?https://github.com/omni360/three.js.sourcecode/blob/master/Three.js
總結
以上是生活随笔為你收集整理的three.js 源代码凝视(七)Math/Euler.js的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈c++静态绑定、动态绑定
- 下一篇: StringUtils 的使用