123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305 |
- const NULL = 0;
- const PI = 3.14159265358979323846264338327;
- const AreaShowType = {
- Area_AabbBox: 0, //Aabb包围盒
- Area_Hexaherdron: 1, //六面体
- Area_TriangularPrism: 2, //三棱柱
- Area_Cylinder: 3, //圆柱
- }
- // 添加 Math.clamp 函数
- if (!Math.clamp)
- {
- Math.clamp = function(a, min, max) {
- if (a < min) return min;
- else if (a > max) return max;
- return a;
- }
- }
- /**
- * 三维向量,包含向量常用的运算方法,当前系统使用数组表示向量,三维向量是包含三个Number的数组
- */
- let Vec3 = (function(){
- return {
- /**
- * 判断对象是否是合格的向量
- * @param {*} a 检查对象
- */
- check: function(a)
- {
- if (!Array.isArray(a))
- return false;
- for(let i = 0; i < 3; ++i)
- if (isNaN(a[i]))
- return false;
- return true;
- },
- /**
- * 向量a与向量b相加,a + b
- * @param {[Number, Number, Number]} a 向量a
- * @param {[Number, Number, Number]} b 向量b
- */
- add: function(a, b)
- {
- return [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
- },
- /**
- * 向量a与常数b相加,a + b
- * @param {[Number, Number, Number]} a 向量a
- * @param {Number} b 常数b
- */
- addScalar: function(a, b)
- {
- return [a[0] + b, a[1] + b, a[2] + b];
- },
- /**
- * 向量a与向量b相减, a - b
- * @param {[Number, Number, Number]} a 向量a
- * @param {[Number, Number, Number]} b 向量b
- */
- sub: function(a, b)
- {
- return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
- },
- /**
- * 向量a与常数b相减,a - b
- * @param {[Number, Number, Number]} a 向量a
- * @param {Number} b 常数b
- */
- subScalar: function(a, b)
- {
- return [a[0] - b, a[1] - b, a[2] - b];
- },
- /**
- * 向量a与向量b相乘, a * b
- * @param {[Number, Number, Number]} a 向量a
- * @param {[Number, Number, Number]} b 向量b
- */
- multiply: function(a, b)
- {
- return [a[0] * b[0], a[1] * b[1], a[2] * b[2]];
- },
- /**
- * 向量a与常数b相乘,a * b
- * @param {[Number, Number, Number]} a 向量a
- * @param {Number} b 常数b
- */
- multiplyScalar: function(a, b)
- {
- return [a[0] * b, a[1] * b, a[2] * b];
- },
-
- /**
- * 向量a与向量b相除, a / b
- * @param {[Number, Number, Number]} a 向量a
- * @param {[Number, Number, Number]} b 向量b
- * @note 向量b各分量不能为0
- */
- divide: function(a, b)
- {
- return [a[0] / b[0], a[1] / b[1], a[2] / b[2]];
- },
- /**
- * 向量a与常数b相除,a / b
- * @param {[Number, Number, Number]} a 向量a
- * @param {Number} b 常数b
- * @note 常数b不能为0
- */
- divideScalar: function(a, b)
- {
- return [a[0] / b, a[1] / b, a[2] / b];
- },
- /**
- * 向量a与向量b点乘, dot(a, b) = |a| * |b| * cos
- * @param {[Number, Number, Number]} a 向量a
- * @param {[Number, Number, Number]} b 向量b
- */
- dot: function(a, b)
- {
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
- },
- /**
- * 向量a与向量b叉乘, cross(a, b) = 法向量,同时垂直于向量a和向量b
- * @param {[Number, Number, Number]} a 向量a
- * @param {[Number, Number, Number]} b 向量b
- */
- cross: function(a, b)
- {
- return [a[1] * b[2] - b[1] * a[2],
- a[2] * b[0] - b[2] * a[0],
- a[0] * b[1] - b[0] * a[1]
- ];
- },
-
- /**
- * 获取向量a的模长/长度, length(a) = |a|
- * @param {[Number, Number, Number]} a 向量a
- */
- length: function(a)
- {
- return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
- },
- /**
- * 获取向量a的模长/长度的平方,lengthSq(a) = length(a) * length(a)
- * @param {[Number, Number, Number]} a 向量a
- */
- lengthSq: function(a)
- {
- return a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
- },
- /**
- * 向量取反
- * @param {[Number, Number, Number]} a 向量a
- */
- negate: function(a)
- {
- return [-a[0], -a[1], -a[2]];
- },
- /**
- * 获取单位向量
- * @param {[Number, Number, Number]} a 向量a
- */
- normalize: function(a)
- {
- var len = Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]) || 1;
- return [a[0] / len, a[1] / len, a[2] / len];
- },
- /**
- * 向量a与向量b的夹角
- * @param {[Number, Number, Number]} a 向量a
- * @param {[Number, Number, Number]} b 向量b
- * @param 返回两个向量的夹角(角度制)
- */
- angleBetween: function (a, b)
- {
- const denominator = Vec3.length(a) * Vec3.length(b);
- if (denominator === 0)
- return Math.PI / 2 * (180 / Math.PI);
- let theta = Vec3.dot(a, b) / denominator;
- if (theta < -1)
- theta = -1;
- if (theta > 1)
- theta = 1;
- let angle = Math.acos(theta)
- angle *= 180 / Math.PI
- return angle
- }
- }
- })();
- /**
- * 行优先4x4矩阵
- */
- let Matrix4 = (function(){
- return {
- /**
- * 获取单位矩阵
- * @returns 单位矩阵
- */
- identity: function()
- {
- return [ 1, 0, 0, 0
- ,0, 1, 0, 0
- ,0, 0, 1, 0
- ,0, 0, 0, 1];
- },
- /**
- * 检查a是否是合法的矩阵
- * @param {*} a 检查对象
- */
- check: function(a)
- {
- if (!Array.isArray(a))
- return false;
- for(let i = 0; i < 16; ++i)
- if (isNaN(a[i]))
- return false;
- return true;
- },
- /**
- * 矩阵a与矩阵b相乘
- * @param {[...Number]} a
- * @param {[...Number]} b
- */
- multiply: function(a, b) {
- const ae = a;
- const be = b;
- const a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12];
- const a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13];
- const a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14];
- const a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15];
- const b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12];
- const b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13];
- const b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14];
- const b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15];
- let rMat =[]
- rMat[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
- rMat[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
- rMat[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
- rMat[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
- rMat[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
- rMat[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
- rMat[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
- rMat[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
- rMat[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
- rMat[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
- rMat[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
- rMat[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
- rMat[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
- rMat[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
- rMat[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
- rMat[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
- return rMat;
- },
- /**
- * 矩阵a与三维坐标b相乘,返回变换后的坐标
- * @param {[...Number]} a 矩阵a
- * @param {[Number,Number,Number]} b 三维坐标b
- */
- multiplyPos: function(a, b) {
- var ret = [];
- for(var i = 0; i < 3; ++i)
- {
- ret[i] = a[12 + i];
- for(var j = 0; j < 3; ++j)
- {
- ret[i] += b[j] * a[j * 4 + i];
- }
- }
- return ret;
- },
- /**
- * 矩阵a与方向向量b相乘,返回变化后的方向
- * @param {[...Number]} a 矩阵a
- * @param {[Number,Number,Number]} b 三维向量b
- */
- multiplyDir: function(a, b) {
- var ret = [];
- for(var i = 0; i < 3; ++i)
- {
- ret[i] = 0;
- for(var j = 0; j < 3; ++j)
- {
- ret[i] += b[j] * a[j * 4 + i];
- }
- }
- return ret;
- },
- /**
- * 构造TRS矩阵
- * @param position 位置
- * @param quaternion 旋转四元数(顺序wxyz)
- * @param scale 缩放
- * @returns 4x4 TRS矩阵
- */
- compose: function(position, quaternion, scale) {
- var ret = [];
- const x = quaternion[1];
- const y = quaternion[2];
- const z = quaternion[3];
- const w = quaternion[0];
- const x2 = x + x;
- const y2 = y + y;
- const z2 = z + z;
- const xx = x * x2;
- const xy = x * y2;
- const xz = x * z2;
- const yy = y * y2;
- const yz = y * z2;
- const zz = z * z2;
- const wx = w * x2;
- const wy = w * y2;
- const wz = w * z2;
- const sx = scale[0];
- const sy = scale[1];
- const sz = scale[2];
- ret[0] = (1 - (yy + zz)) * sx;
- ret[1] = (xy + wz) * sx;
- ret[2] = (xz - wy) * sx;
- ret[3] = 0;
- ret[4] = (xy - wz) * sy;
- ret[5] = (1 - (xx + zz)) * sy;
- ret[6] = (yz + wx) * sy;
- ret[7] = 0;
- ret[8] = (xz + wy) * sz;
- ret[9] = (yz - wx) * sz;
- ret[10] = (1 - (xx + yy)) * sz;
- ret[11] = 0;
- ret[12] = position[0];
- ret[13] = position[1];
- ret[14] = position[2];
- ret[15] = 1;
- return ret;
- },
- /**
- * 矩阵萃取
- * @param {*} m 将被萃取的矩阵对象
- * @returns 萃取结果
- * - position: 萃取的位置信息
- * - quaternion: 萃取的旋转四元数信息
- * - rotation: 萃取的旋转矩阵信息
- * - scale:萃取的缩放信息
- */
- decompose: function(m)
- {
- var a = {};
- var vx = [m[0], m[1], m[2]];
- var vy = [m[4], m[5], m[6]];
- var vz = [m[8], m[9], m[10]];
- let sx = Vec3.length(vx);
- const sy = Vec3.length(vy);
- const sz = Vec3.length(vz);
- // if determine is negative, we need to invert one scale
- const det = Matrix4.determinant(m);
- if ( det < 0 )
- sx = - sx;
- a.position = [];
- a.position[0] = m[ 12 ];
- a.position[1] = m[ 13 ];
- a.position[2] = m[ 14 ];
- // scale the rotation part
- var rMat = m;
- rMat[12] = 0;
- rMat[13] = 0;
- rMat[14] = 0;
- const invSX = 1 / sx;
- const invSY = 1 / sy;
- const invSZ = 1 / sz;
-
- rMat[ 0 ] *= invSX;
- rMat[ 1 ] *= invSX;
- rMat[ 2 ] *= invSX;
- rMat[ 4 ] *= invSY;
- rMat[ 5 ] *= invSY;
- rMat[ 6 ] *= invSY;
-
- rMat[ 8 ] *= invSZ;
- rMat[ 9 ] *= invSZ;
- rMat[ 10 ] *= invSZ;
- a.rotation = rMat;
- a.quaternion = Quat.fromRotationMatrix(rMat);
- a.scale = [];
- a.scale[0] = sx;
- a.scale[1] = sy;
- a.scale[2] = sz;
- return a;
- },
- /**
- * 计算矩阵行列式
- * @param {*} m 将被计算行列式的矩阵对象
- * @returns 矩阵的行列式值
- */
- determinant: function(m)
- {
- const n11 = m[ 0 ], n12 = m[ 1 ], n13 = m[ 2 ], n14 = m[ 3 ];
- const n21 = m[ 4 ], n22 = m[ 5 ], n23 = m[ 6 ], n24 = m[ 7 ];
- const n31 = m[ 8 ], n32 = m[ 9 ], n33 = m[ 10 ], n34 = m[ 11 ];
- const n41 = m[ 12 ], n42 = m[ 13 ], n43 = m[ 14 ], n44 = m[ 15 ];
-
- return (
- n41 * (
- + n14 * n23 * n32
- - n13 * n24 * n32
- - n14 * n22 * n33
- + n12 * n24 * n33
- + n13 * n22 * n34
- - n12 * n23 * n34
- ) +
- n42 * (
- + n11 * n23 * n34
- - n11 * n24 * n33
- + n14 * n21 * n33
- - n13 * n21 * n34
- + n13 * n24 * n31
- - n14 * n23 * n31
- ) +
- n43 * (
- + n11 * n24 * n32
- - n11 * n22 * n34
- - n14 * n21 * n32
- + n12 * n21 * n34
- + n14 * n22 * n31
- - n12 * n24 * n31
- ) +
- n44 * (
- - n13 * n22 * n31
- - n11 * n23 * n32
- + n11 * n22 * n33
- + n13 * n21 * n32
- - n12 * n21 * n33
- + n12 * n23 * n31
- )
-
- );
-
- },
-
- /**
- * 计算矩阵的逆
- * @param {*} m 将被计算逆的矩阵对象
- * @returns 矩阵的逆矩阵
- * */
- inverse: function(m) {
-
- // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
- const n11 = m[0], n21 = m[1], n31 = m[2], n41 = m[3],
- n12 = m[4], n22 = m[5], n32 = m[6], n42 = m[7],
- n13 = m[8], n23 = m[9], n33 = m[10], n43 = m[11],
- n14 = m[12], n24 = m[13], n34 = m[14], n44 = m[15],
- t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
- t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
- t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
- t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
- const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
- if (det === 0) return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
- const detInv = 1 / det;
- let invMat = [];
- invMat[0] = t11 * detInv;
- invMat[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv;
- invMat[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv;
- invMat[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv;
- invMat[4] = t12 * detInv;
- invMat[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv;
- invMat[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv;
- invMat[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv;
- invMat[8] = t13 * detInv;
- invMat[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv;
- invMat[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv;
- invMat[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv;
- invMat[12] = t14 * detInv;
- invMat[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv;
- invMat[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv;
- invMat[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv;
- return invMat;
- },
-
- /**
- * 构造平移矩阵
- * @param {[Number, Number, Number]} t 平移距离
- * @returns 4x4 的平移矩阵
- */
- makeTranslate: function(t)
- {
- var mat = this.identity();
- mat[12] = t[0];
- mat[13] = t[1];
- mat[14] = t[2];
- return mat;
- },
- /**
- * 指定旋转角和旋转轴计算一个旋转矩阵
- * @param {Number} angle 旋转角(角度制)
- * @param {[Number, Number, Number]} axis 旋转轴(单位向量)
- * @returns 4x4的旋转矩阵
- * */
- makeRotationAxis: function(angle, axis){
- const tAngne = angle * Math.PI / 180;
- // Based on http://www.gamedev.net/reference/articles/article1199.asp
- const c = Math.cos(tAngne);
- const s = Math.sin(tAngne);
- const t = 1 - c;
- const x = axis[0], y = axis[1], z = axis[2];
- const tx = t * x, ty = t * y;
- let rMat = [];
- rMat[0] = tx * x + c; rMat[4] = tx * y - s * z; rMat[8] = tx * z + s * y; rMat[12] =0;
- rMat[1] = tx * y + s * z; rMat[5] = ty * y + c; rMat[9] = ty * z - s * x; rMat[13] =0;
- rMat[2] = tx * z - s * y; rMat[6] = ty * z + s * x; rMat[10] = t * z * z + c; rMat[14] =0;
- rMat[3] = 0; rMat[7] = 0; rMat[11] = 0; rMat[15] =1;
- return rMat;
- },
- }
- })();
- /**
- * 四元素
- * 注:这里四元数对应Player返回的四元数对象,Player返回的四元数的顺序是 [w,x,y,z]
- * 因此这里四元数所有算法也应该遵循Player中的 [w,x,y,z]顺序
- */
- let Quat = (function(){
- return {
- /**
- * 检查a是否是合法的四元数
- * @param {*} a 检查对象
- */
- check: function(a)
- {
- if (!Array.isArray(a))
- return false;
- for(let i = 0; i < 4; ++i)
- if (isNaN(a[i]))
- return false;
- if (Math.abs(a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3] - 1) > 0.01)
- return false;
- return true;
- },
- /**
- * 转换旋转矩阵到四元数
- * @param {*} m 旋转矩阵
- * @returns 旋转四元数
- */
- fromRotationMatrix: function( m)
- {
- m11 = m[ 0 ], m12 = m[ 4 ], m13 = m[ 8 ],
- m21 = m[ 1 ], m22 = m[ 5 ], m23 = m[ 9 ],
- m31 = m[ 2 ], m32 = m[ 6 ], m33 = m[ 10 ],
-
- trace = m11 + m22 + m33;
-
- q = [];
-
- if ( trace > 0 )
- {
-
- const s = 0.5 / Math.sqrt( trace + 1.0 );
- q[0] = 0.25 / s;
- q[1] = ( m32 - m23 ) * s;
- q[2] = ( m13 - m31 ) * s;
- q[3] = ( m21 - m12 ) * s;
-
- }
- else if ( m11 > m22 && m11 > m33 )
- {
-
- const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
-
- q[0] = ( m32 - m23 ) / s;
- q[1] = 0.25 * s;
- q[2] = ( m12 + m21 ) / s;
- q[3] = ( m13 + m31 ) / s;
-
- }
- else if ( m22 > m33 )
- {
-
- const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
-
- q[0] = ( m13 - m31 ) / s;
- q[1] = ( m12 + m21 ) / s;
- q[2] = 0.25 * s;
- q[3] = ( m23 + m32 ) / s;
-
- }
- else
- {
-
- const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
-
- q[0] = ( m21 - m12 ) / s;
- q[1] = ( m13 + m31 ) / s;
- q[2] = ( m23 + m32 ) / s;
- q[3] = 0.25 * s;
-
- }
-
- return q;
- },
- /**
- * 转换四元数到旋转矩阵
- * @param m 旋转四元数
- * @returns 旋转矩阵
- */
- toRotationMatrix: function (q)
- {
- return Matrix4.compose([0, 0, 0], q, [1, 1, 1]);
- },
- }})();
- let EulerAngle = (function () {
- return {
- /**
- * 转换旋转矩阵到欧拉角
- * @param m 旋转矩阵(4x4)
- * @param order 欧拉角顺序, 取值分别为: "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"
- * @returns 欧拉角
- */
- fromRotationMatrix: function (m, order = 'XYZ') {
- var ret = []
- const te = m;
- const m11 = te[0], m12 = te[4], m13 = te[8];
- const m21 = te[1], m22 = te[5], m23 = te[9];
- const m31 = te[2], m32 = te[6], m33 = te[10];
- switch (order) {
- case 'XYZ':
- ret[1] = Math.asin(Math.clamp(m13, - 1, 1));
- if (Math.abs(m13) < 0.9999999) {
- ret[0] = Math.atan2(- m23, m33);
- ret[2] = Math.atan2(- m12, m11);
- } else {
- ret[0] = Math.atan2(m32, m22);
- ret[2] = 0;
- }
- break;
- case 'YXZ':
- ret[0] = Math.asin(- clamp(m23, - 1, 1));
- if (Math.abs(m23) < 0.9999999) {
- ret[1] = Math.atan2(m13, m33);
- ret[2] = Math.atan2(m21, m22);
- } else {
- ret[1] = Math.atan2(- m31, m11);
- ret[2] = 0;
- }
- break;
- case 'ZXY':
- ret[0] = Math.asin(clamp(m32, - 1, 1));
- if (Math.abs(m32) < 0.9999999) {
- ret[1] = Math.atan2(- m31, m33);
- ret[2] = Math.atan2(- m12, m22);
- } else {
- ret[1] = 0;
- ret[2] = Math.atan2(m21, m11);
- }
- break;
- case 'ZYX':
- ret[1] = Math.asin(- clamp(m31, - 1, 1));
- if (Math.abs(m31) < 0.9999999) {
- ret[0] = Math.atan2(m32, m33);
- ret[2] = Math.atan2(m21, m11);
- } else {
- ret[0] = 0;
- ret[2] = Math.atan2(- m12, m22);
- }
- break;
- case 'YZX':
- ret[2] = Math.asin(clamp(m21, - 1, 1));
- if (Math.abs(m21) < 0.9999999) {
- ret[0] = Math.atan2(- m23, m22);
- ret[1] = Math.atan2(- m31, m11);
- } else {
- ret[0] = 0;
- ret[1] = Math.atan2(m13, m33);
- }
- break;
- case 'XZY':
- ret[2] = Math.asin(- clamp(m12, - 1, 1));
- if (Math.abs(m12) < 0.9999999) {
- ret[0] = Math.atan2(m32, m22);
- ret[1] = Math.atan2(m13, m11);
- } else {
- ret[0] = Math.atan2(- m23, m33);
- ret[1] = 0;
- }
- break;
- default:
- console.warn(' unknown order: ' + order);
- }
- //弧度制转角度制
- ret[0] = ret[0] * 180 / Math.PI;
- ret[1] = ret[1] * 180 / Math.PI;
- ret[2] = ret[2] * 180 / Math.PI;
- return ret;
- },
- /**
- * 转换欧拉角到旋转矩阵
- * @param euler 欧拉角
- * @param order 欧拉角顺序, 取值分别为: "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"
- * @returns 4x4旋转矩阵
- */
- toRotationMatrix: function (euler, order = 'XYZ'){
- var ret = [];
- const x = euler[0] * Math.PI / 180;
- const y = euler[1] * Math.PI / 180;
- const z = euler[2] * Math.PI / 180;
- const a = Math.cos(x);
- const b = Math.sin(x);
- const c = Math.cos(y);
- const d = Math.sin(y);
- const e = Math.cos(z);
- const f = Math.sin(z);
- if (order === 'XYZ') {
- const ae = a * e, af = a * f, be = b * e, bf = b * f;
- ret[0] = c * e;
- ret[4] = - c * f;
- ret[8] = d;
- ret[1] = af + be * d;
- ret[5] = ae - bf * d;
- ret[9] = - b * c;
- ret[2] = bf - ae * d;
- ret[6] = be + af * d;
- ret[10] = a * c;
- } else if (order === 'YXZ') {
- const ce = c * e, cf = c * f, de = d * e, df = d * f;
- ret[0] = ce + df * b;
- ret[4] = de * b - cf;
- ret[8] = a * d;
- ret[1] = a * f;
- ret[5] = a * e;
- ret[9] = - b;
- ret[2] = cf * b - de;
- ret[6] = df + ce * b;
- ret[10] = a * c;
- } else if (order === 'ZXY') {
- const ce = c * e, cf = c * f, de = d * e, df = d * f;
- ret[0] = ce - df * b;
- ret[4] = - a * f;
- ret[8] = de + cf * b;
- ret[1] = cf + de * b;
- ret[5] = a * e;
- ret[9] = df - ce * b;
- ret[2] = - a * d;
- ret[6] = b;
- ret[10] = a * c;
- } else if (order === 'ZYX') {
- const ae = a * e, af = a * f, be = b * e, bf = b * f;
- ret[0] = c * e;
- ret[4] = be * d - af;
- ret[8] = ae * d + bf;
- ret[1] = c * f;
- ret[5] = bf * d + ae;
- ret[9] = af * d - be;
- ret[2] = - d;
- ret[6] = b * c;
- ret[10] = a * c;
- } else if (order === 'YZX') {
- const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
- ret[0] = c * e;
- ret[4] = bd - ac * f;
- ret[8] = bc * f + ad;
- ret[1] = f;
- ret[5] = a * e;
- ret[9] = - b * e;
- ret[2] = - d * e;
- ret[6] = ad * f + bc;
- ret[10] = ac - bd * f;
- } else if (order === 'XZY') {
- const ac = a * c, ad = a * d, bc = b * c, bd = b * d;
- ret[0] = c * e;
- ret[4] = - f;
- ret[8] = d * e;
- ret[1] = ac * f + bd;
- ret[5] = a * e;
- ret[9] = ad * f - bc;
- ret[2] = bc * f - ad;
- ret[6] = b * e;
- ret[10] = bd * f + ac;
- }
- // bottom row
- ret[3] = 0;
- ret[7] = 0;
- ret[11] = 0;
- // last column
- ret[12] = 0;
- ret[13] = 0;
- ret[14] = 0;
- ret[15] = 1;
- return ret;
- },
- /**
- * 转换旋转四元数到欧拉角
- * @param q 旋转四元数(wxyz)
- * @param order 欧拉角顺序, 取值分别为: "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"
- * @returns 旋转四元数
- */
- fromQuat: function (q, order = 'XYZ') {
- return EulerAngle.fromRotationMatrix(Quat.toRotationMatrix(q), order);
- },
- /**
- * 转换欧拉角到旋转四元数
- * @param euler 欧拉角
- * @param order 欧拉角顺序, 取值分别为: "XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"
- * @returns 旋转四元数(wxyz)
- */
- toQuat: function (euler, order = 'XYZ') {
- var q = [];
- const x = euler[0] * Math.PI / 180;
- const y = euler[1] * Math.PI / 180;
- const z = euler[2] * Math.PI / 180;
-
- const cos = Math.cos;
- const sin = Math.sin;
- const c1 = cos(x / 2);
- const c2 = cos(y / 2);
- const c3 = cos(z / 2);
- const s1 = sin(x / 2);
- const s2 = sin(y / 2);
- const s3 = sin(z / 2);
- switch (order) {
- case 'XYZ':
- q[1] = s1 * c2 * c3 + c1 * s2 * s3;
- q[2] = c1 * s2 * c3 - s1 * c2 * s3;
- q[3] = c1 * c2 * s3 + s1 * s2 * c3;
- q[0] = c1 * c2 * c3 - s1 * s2 * s3;
- break;
- case 'YXZ':
- q[1] = s1 * c2 * c3 + c1 * s2 * s3;
- q[2] = c1 * s2 * c3 - s1 * c2 * s3;
- q[3] = c1 * c2 * s3 - s1 * s2 * c3;
- q[0] = c1 * c2 * c3 + s1 * s2 * s3;
- break;
- case 'ZXY':
- q[1] = s1 * c2 * c3 - c1 * s2 * s3;
- q[2] = c1 * s2 * c3 + s1 * c2 * s3;
- q[3] = c1 * c2 * s3 + s1 * s2 * c3;
- q[0] = c1 * c2 * c3 - s1 * s2 * s3;
- break;
- case 'ZYX':
- q[1] = s1 * c2 * c3 - c1 * s2 * s3;
- q[2] = c1 * s2 * c3 + s1 * c2 * s3;
- q[3] = c1 * c2 * s3 - s1 * s2 * c3;
- q[0] = c1 * c2 * c3 + s1 * s2 * s3;
- break;
- case 'YZX':
- q[1] = s1 * c2 * c3 + c1 * s2 * s3;
- q[2] = c1 * s2 * c3 + s1 * c2 * s3;
- q[3] = c1 * c2 * s3 - s1 * s2 * c3;
- q[0] = c1 * c2 * c3 - s1 * s2 * s3;
- break;
- case 'XZY':
- q[1] = s1 * c2 * c3 - c1 * s2 * s3;
- q[2] = c1 * s2 * c3 - s1 * c2 * s3;
- q[3] = c1 * c2 * s3 + s1 * s2 * c3;
- q[0] = c1 * c2 * c3 + s1 * s2 * s3;
- break;
- default:
- console.warn('unknown order: ' + order);
- }
- return q;
- }
- };
- })();
- /**
- * 包围盒
- */
- let Aabb = (function () {
- return {
- /**
- * 检查a是否是合法的包围盒
- * @param {*} a 检查对象
- */
- check: function (a) {
- if (!Array.isArray(a))
- return false;
- if (isNaN(a.min) || isNaN(a.max))
- return false;
- for (let i = 0; i < 3; ++i)
- if (isNaN(a.min[i]) || isNaN(a.max[i]))
- return false;
- return true;
- },
- /**
- * map(min、max)解成二维数组
- * @param {[{"min", [Number, Number, Number]}, {"max", [Number, Number, Number]}]} a map a
- */
- deMap: function (a) {
- return [a.min, a.max];
- },
- /**
- * 获取包围盒8个顶点
- * @param a [ [Number, Number, Number],[Number, Number, Number]] a aabb
- */
- vertex8: function (a) {
- return [
- [a[0][0], a[0][1], a[0][2]]
- , [a[0][0], a[1][1], a[0][2]]
- , [a[1][0], a[1][1], a[0][2]]
- , [a[1][0], a[0][1], a[0][2]]
- , [a[1][0], a[1][1], a[1][2]]
- , [a[0][0], a[1][1], a[1][2]]
- , [a[0][0], a[0][1], a[1][2]]
- , [a[1][0], a[0][1], a[1][2]]];
- },
- /**
- * 获取包围盒某个面
- * @param a [ [Number, Number, Number],[Number, Number, Number]] a aabb
- * @param faceName 面名称: X,XN,Y,YN,Z,ZN
- */
- face:function(a, faceName = 'Z')
- {
- let fIdx = [];
- switch (faceName)
- {
- case 'X':
- {
- fIdx = [ 3, 2, 4, 7 ]; //X
- }break;
- case 'XN':
- {
- fIdx = [1, 0, 6, 5 ]; //XN
- }break;
- case 'Y':
- {
- fIdx = [2, 1, 5, 4 ]; //Y
- }break;
- case 'YN':
- {
- fIdx = [0, 3, 7, 6 ]; //YN
- }break;
- case 'Z':
- {
- fIdx = [6, 7, 4, 5 ]; //Z
- }break;
- case 'ZN':
- {
- fIdx = [1, 2, 3, 0 ]; //ZN
- }break;
- default:
- {
- console.warn('unknown face: ' + faceName);
- return [];
- }break;
- }
- const v8 = Aabb.vertex8(a)
- return [v8[fIdx[0]], v8[fIdx[1]], v8[fIdx[2]], v8[fIdx[3]]]
- },
- /**
- * 获取包围盒某个面中心点
- * @param a [ [Number, Number, Number],[Number, Number, Number]] a aabb
- * @param faceName 面名称: X,XN,Y,YN,Z,ZN
- */
- faceCenter:function(a, faceName = 'Z')
- {
- const face = Aabb.face(a, faceName);
- const a0 = Vec3.add(face[0], face[1]);
- const a1 = Vec3.add(a0, face[2]);
- let a2 = Vec3.add(a1, face[3]);
- a2[0] /= 4;
- a2[1] /= 4;
- a2[2] /= 4;
- return a2;
- },
- /**
- * 获取包围盒中心点
- * @param [ [Number, Number, Number],[Number, Number, Number]] a aabb
- */
- center: function(a)
- {
- let cen = Vec3.add(a[0], a[1])
- cen = Vec3.multiplyScalar(cen, 0.5)
- return cen
- }
- }
- })();
- /**
- * 射线 [[Number,Number,Number],[Number,Number,Number]] 第一个数据表示射线端点,第二个数据表示射线防线
- */
- let Ray = (function () {
- return {
- /**
- * @brief 根据参数 t(距离) 获取射线上的点
- * 当 t = 0 时, 结果点为射线原点
- * 当 t > 0 时, 结果点在射线上
- * 当 t < 0 是, 结果点在射线的背面
- */
- at: function(ray, t)
- {
- let pt = Vec3.add(ray[0], Vec3.multiplyScalar(ray[1], t))
- return pt;
- },
- /**
- * @brief 射线与平面相交
- * @param ray 射线对象
- * @param planePosition 平面上的任意一点
- * @param planeNormal 平面发向量
- */
- intersectPlane: function(ray, planePosition, planeNormal)
- {
- let denominator = Vec3.dot(planeNormal, ray[1])
- if (denominator === 0.0)
- {
- let dt = Vec3.dot(planeNormal, ray[0])
- if (dt === 0.0)
- {
- return { bIntersect: true, rayParamT: 0 };
- }
- return { bIntersect: false, rayParamT: -1 };
- }
- let t = Vec3.dot(planeNormal, Vec3.sub(planePosition, ray[0])) / denominator;
- if (t >= 0)
- {
- return { bIntersect: true, rayParamT: t };
- }
- return { bIntersect: false, rayParamT: -1 };
- },
- }
- })();
- /**
- * Player常用函数集合
- */
- let PlayerUtils = (function() {
- return {
- /**
- * 使用Promise封装异步接口调用
- * @param {Function} fun 要调用的函数
- * @param {...any} args 参数
- * @example
- * var info = await PlayerUtils.call(player.Model.getInfo, 'sampler.pr') //使用await
- * PlayerUtils.call(player.Model.getInfo, 'sampler.pr').then((info)=>{ console.log(info) }); //使用then
- */
- call: function(fun, ...args) {
- return new Promise((resolve)=>{
- fun(...args, (ret)=>{
- resolve(ret);
- });
- });
- },
- /**
- * 计算包围盒的视口信息
- * @param {{min:[Number,Number,Number],max:[Number,Number,Number]}} aabb 目标包围盒
- * @param {[Number,Number,Number]} eyeDir 摄像机方向
- * @param {[Number,Number,Number]} upDir 摄像机上方向,不能与eyeDir重合
- * @param {Number} lenScalar 摄像机距离系数,越大越远
- */
- calAabbViewParam: function(aabb, eyeDir, upDir, lenScalar) {
- var target = Vec3.divideScalar(Vec3.add(aabb.min, aabb.max), 2);
- var dir = Vec3.normalize(eyeDir);
- var len = Vec3.length(Vec3.sub(aabb.max, aabb.min)) * lenScalar;
- var eye = Vec3.add(Vec3.multiplyScalar(dir, len), target);
- var up = Vec3.normalize(Vec3.cross(Vec3.cross(dir, upDir), dir));
- return {
- eye: eye,
- target: target,
- up: up
- }
- },
- /**
- * 移动相机看向模型,适用于模型所在高程瓦片已加载完成或禁用地形跟随
- * @param {RemotePlayer} player Player对象
- * @param {String} modelId 模型ID
- * @param {[Number,Number,Number]|Function} eyeDir 摄像机方向,基于模型局部坐标系,或计算相机方向的函数
- * @param {[Number,Number,Number]} upDir 摄像机上方向,不能与eyeDir重合,基于模型局部坐标系
- * @param {Number} lenScalar 摄像机距离系数,越大越远
- * @param {Number} second 摄像机过渡时间
- * @example
- * PlayerUtils.moveToModel(player, "data://models/sampler.pr", [1,0,0], [0,0,1], 2); //[1,0,0]=>从右看向左边
- */
- moveToModel: async function (player, modelId, eyeDir, upDir, lenScalar = 1, second = 1) {
- var info = await PlayerUtils.call(player.Native.Model.getInfo, modelId);
- var mat = await PlayerUtils.call(player.Native.Model.getModelMatrix, modelId);
- if (typeof(eyeDir) == "function") eyeDir = eyeDir(info.srcAabb);
- var param = PlayerUtils.calAabbViewParam(info.srcAabb, eyeDir, upDir, lenScalar);
- param.eye = Matrix4.multiplyPos(mat, param.eye);
- param.target = Matrix4.multiplyPos(mat, param.target);
- param.up = Matrix4.multiplyDir(mat, param.up);
- await PlayerUtils.call(player.Native.Camera.moveTo, param.eye, param.target, param.up, second);
- },
- /**
- * 移动相机看向包围盒
- * @param {RemotePlayer} player Player对象
- * @param {{min:[Number,Number,Number], max:[Number,Number,Number]}} aabb 模型ID
- * @param {[...Number]} mat 包围盒需要运用的矩阵
- * @param {[Number,Number,Number]} eyeDir 摄像机方向,基于模型局部坐标系
- * @param {[Number,Number,Number]} upDir 摄像机上方向,不能与eyeDir重合,基于模型局部坐标系
- * @param {Number} lenScalar 摄像机距离系数,越大越远
- * @param {Number} second 摄像机过渡时间
- * @example
- * PlayerUtils.moveToAabb(player, {min:[-1,-1,-1],max:[1,1,1]}, [1,0,0], [0,0,1], 2); //[1,0,0]=>从右看向左边
- */
- moveToAabb: async function (player, aabb, mat, eyeDir, upDir, lenScalar = 1, second = 1) {
- var param = PlayerUtils.calAabbViewParam(aabb, eyeDir, upDir, lenScalar);
- param.eye = Matrix4.multiplyPos(mat, param.eye);
- param.target = Matrix4.multiplyPos(mat, param.target);
- param.up = Matrix4.multiplyDir(mat, param.up);
- await PlayerUtils.call(player.Native.Camera.moveTo, param.eye, param.target, param.up, second);
- },
-
- /**
- * 添加移动相机看向包围盒任务
- * @param {RemotePlayer} player Player对象
- * @param {{min:[Number,Number,Number], max:[Number,Number,Number]}} aabb 模型ID
- * @param {[...Number]} mat 包围盒需要运用的矩阵
- * @param {[Number,Number,Number]} eyeDir 摄像机方向,基于模型局部坐标系
- * @param {[Number,Number,Number]} upDir 摄像机上方向,不能与eyeDir重合,基于模型局部坐标系
- * @param {Number} lenScalar 摄像机距离系数,越大越远
- * @param {Number} second 摄像机过渡时间
- * @example
- * PlayerUtils.addMoveToAabb(player, {min:[-1,-1,-1],max:[1,1,1]}, [1,0,0], [0,0,1], 2); //[1,0,0]=>从右看向左边
- */
- addMoveToAabb: async function (player, aabb, mat, eyeDir, upDir, lenScalar = 1, second = 1) {
- var param = PlayerUtils.calAabbViewParam(aabb, eyeDir, upDir, lenScalar);
- param.eye = Matrix4.multiplyPos(mat, param.eye);
- param.target = Matrix4.multiplyPos(mat, param.target);
- param.up = Matrix4.multiplyDir(mat, param.up);
- await PlayerUtils.call(player.Native.Camera.addMoveTo, param.eye, param.target, param.up, second);
- }
- }
- })();
|