import {FloatUtil} from '../common/lang/FloatUtil'; import {Matrix4} from './Matrix4'; //========================================================== // 三维矩阵。 // // @struct // @author maocy // @version 141231 //========================================================== export class Matrix3d extends Matrix4 { // @attribute protected _dirty = false; // @attribute public tx = 0; public ty = 0; public tz = 0; public rx = 0; public ry = 0; public rz = 0; public sx = 1; public sy = 1; public sz = 1; //============================================================ // 构造处理。 // // @method //============================================================ public constructor() { super(); this.identity(); } // //============================================================ // // 是否为单位化数据。 // // // // @method // // @return 是否单位化 // //============================================================ // public isIdentity(): boolean { // if ((this.tx != 0) || (this.ty != 0) || (this.tz != 0)) { // return false; // } // if ((this.rx != 0) || (this.ry != 0) || (this.rz != 0)) { // return false; // } // if ((this.sx != 1) || (this.sy != 1) || (this.sz != 1)) { // return false; // } // return this.isIdentityData(); // } // //============================================================ // // 单位化处理。 // // // // @method // //============================================================ // public identity() { // this.tx = this.ty = this.tz = 0; // this.rx = this.ry = this.rz = 0; // this.sx = this.sy = this.sz = 1; // // return this.identityData(); // } // //============================================================ // // 设置平移内容。 // // // // @method // // @param x:Float X坐标 // // @param y:Float Y坐标 // // @param z:Float Z坐标 // //============================================================ // public setTranslate(x, y, z) { // this.tx = x; // this.ty = y; // this.tz = z; // this._dirty = true; // } // //============================================================ // // 设置旋转内容。 // // // // @method // // @param x:Float X旋转 // // @param y:Float Y旋转 // // @param z:Float Z旋转 // //============================================================ // public setRotation(x, y, z) { // this.rx = x; // this.ry = y; // this.rz = z; // this._dirty = true; // } // //============================================================ // // 设置缩放内容。 // // // // @method // // @param x:Float X缩放 // // @param y:Float Y缩放 // // @param z:Float Z缩放 // //============================================================ // public setScale(x, y, z) { // this.sx = x; // this.sy = y; // this.sz = z; // this._dirty = true; // } // //============================================================ // // 设置全部缩放内容。 // // // // @method // // @param p:value:Float 缩放 // //============================================================ // public setScaleAll(p) { // this.sz = this.sy = this.sx = p; // this._dirty = true; // } // //============================================================ // // 设置内容。 // // // // @method // // @param pt:SPoint3 坐标 // // @param pr:SVector3 旋转 // // @param ps:SVector3 缩放 // //============================================================ // public set(pt, pr, ps) { // this.tx = pt.x; // this.ty = pt.y; // this.tz = pt.z; // this.rx = pr.x; // this.ry = pr.y; // this.rz = pr.z; // this.sx = ps.x; // this.sy = ps.y; // this.sz = ps.z; // this._dirty = true; // } // //============================================================ // // 设置内容。 // // // // @method // // @param ptx:Float X坐标 // // @param pty:Float Y坐标 // // @param ptz:Float Z坐标 // // @param prx:Float X旋转 // // @param pry:Float Y旋转 // // @param prz:Float Z旋转 // // @param psx:Float X缩放 // // @param psy:Float Y缩放 // // @param psz:Float Z缩放 // //============================================================ // public setAll(tx, ty, tz, rx, ry, rz, sx, sy, sz) { // this.tx = tx; // this.ty = ty; // this.tz = tz; // this.rx = rx; // this.ry = ry; // this.rz = rz; // this.sx = sx; // this.sy = sy; // this.sz = sz; // this._dirty = true; // } // //============================================================ // // 判断是否相等。 // // // // @method // // @param p:matrix:SMatrix3d 矩阵 // // @return Boolean 是否相等 // //============================================================ // public equals(p) { // // return this.equalsData(p._data); // } // //============================================================ // // 接收一个矩阵。 // // // // @method // // @param p:matrix:SMatrix3d 矩阵 // //============================================================ // public assign(p) { // this.tx = p.tx; // this.ty = p.ty; // this.tz = p.tz; // this.rx = p.rx; // this.ry = p.ry; // this.rz = p.rz; // this.sx = p.sx; // this.sy = p.sy; // this.sz = p.sz; // // return this.assignData(p._data); // } // //============================================================ // // 接收一个矩阵,返回是否修改。 // // // // @method // // @param p:matrix:SMatrix3d 矩阵 // //============================================================ // public attach(p) { // this.tx = p.tx; // this.ty = p.ty; // this.tz = p.tz; // this.rx = p.rx; // this.ry = p.ry; // this.rz = p.rz; // this.sx = p.sx; // this.sy = p.sy; // this.sz = p.sz; // // return this.attachData(p._data); // } // //============================================================ // // 追加一个矩阵。 // // // // @method // // @param p:value:SMatrix3d 矩阵 // //============================================================ // public append(p) { // // this.appendData(p._data); // } // //============================================================ // // 强制更新数据。 // // // // @method // //============================================================ // public updateForce() { // var data = this.data; // var rsx = Math.sin(this.rx); // var rcx = Math.cos(this.rx); // var rsy = Math.sin(this.ry); // var rcy = Math.cos(this.ry); // var rsz = Math.sin(this.rz); // var rcz = Math.cos(this.rz); // data[0] = rcy * rcz * this.sx; // data[1] = rcy * rsz * this.sx; // data[2] = -rsy * this.sx; // data[3] = 0; // data[4] = (rsx * rsy * rcz - rcx * rsz) * this.sy; // data[5] = (rsx * rsy * rsz + rcx * rcz) * this.sy; // data[6] = rsx * rcy * this.sy; // data[7] = 0; // data[8] = (rcx * rsy * rcz + rsx * rsz) * this.sz; // data[9] = (rcx * rsy * rsz - rsx * rcz) * this.sz; // data[10] = rcx * rcy * this.sz; // data[11] = 0; // data[12] = this.tx; // data[13] = this.ty; // data[14] = this.tz; // data[15] = 1; // } // //============================================================ // // 更新数据。 // // // // @method // //============================================================ // public update() { // if (this._dirty) { // this.updateForce(); // this._dirty = false; // } // } // //============================================================ // // 合并数据。 // // // // @method // //============================================================ // public merge(bm, am) { // this.tx = bm.tx + am.tx; // this.ty = bm.ty + am.ty; // this.tz = bm.tz + am.tz; // this.rx = bm.rx + am.rx; // this.ry = bm.ry + am.ry; // this.rz = bm.rz + am.rz; // this.sx = bm.sx * am.sx; // this.sy = bm.sy * am.sy; // this.sz = bm.sz * am.sz; // this.updateForce(); // } // /* // public my_create() { // var out = new Float32Array(16); // out[0] = 1; // out[1] = 0; // out[2] = 0; // out[3] = 0; // out[4] = 0; // out[5] = 1; // out[6] = 0; // out[7] = 0; // out[8] = 0; // out[9] = 0; // out[10] = 1; // out[11] = 0; // out[12] = 0; // out[13] = 0; // out[14] = 0; // out[15] = 1; // return out; // }; // public my_normalize(out, mat) { // var m44 = mat[15] // // Cannot normalize. // if (m44 === 0) // return false // var scale = 1 / m44 // for (var i = 0; i < 16; i++) // out[i] = mat[i] * scale // return true // } // public my_clone(a) { // var out = new Float32Array(16); // out[0] = a[0]; // out[1] = a[1]; // out[2] = a[2]; // out[3] = a[3]; // out[4] = a[4]; // out[5] = a[5]; // out[6] = a[6]; // out[7] = a[7]; // out[8] = a[8]; // out[9] = a[9]; // out[10] = a[10]; // out[11] = a[11]; // out[12] = a[12]; // out[13] = a[13]; // out[14] = a[14]; // out[15] = a[15]; // return out; // }; // public my_determinant(a) { // var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], // a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], // a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], // a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], // b00 = a00 * a11 - a01 * a10, // b01 = a00 * a12 - a02 * a10, // b02 = a00 * a13 - a03 * a10, // b03 = a01 * a12 - a02 * a11, // b04 = a01 * a13 - a03 * a11, // b05 = a02 * a13 - a03 * a12, // b06 = a20 * a31 - a21 * a30, // b07 = a20 * a32 - a22 * a30, // b08 = a20 * a33 - a23 * a30, // b09 = a21 * a32 - a22 * a31, // b10 = a21 * a33 - a23 * a31, // b11 = a22 * a33 - a23 * a32; // // Calculate the determinant // return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; // }; // public my_invert(out, a) { // var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], // a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], // a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], // a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], // b00 = a00 * a11 - a01 * a10, // b01 = a00 * a12 - a02 * a10, // b02 = a00 * a13 - a03 * a10, // b03 = a01 * a12 - a02 * a11, // b04 = a01 * a13 - a03 * a11, // b05 = a02 * a13 - a03 * a12, // b06 = a20 * a31 - a21 * a30, // b07 = a20 * a32 - a22 * a30, // b08 = a20 * a33 - a23 * a30, // b09 = a21 * a32 - a22 * a31, // b10 = a21 * a33 - a23 * a31, // b11 = a22 * a33 - a23 * a32, // // Calculate the determinant // det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; // if (!det) { // return null; // } // det = 1.0 / det; // out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; // out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; // out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; // out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; // out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; // out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; // out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; // out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; // out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; // out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; // out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; // out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; // out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; // out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; // out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; // out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; // return out; // }; // public my_transpose(out, a) { // // If we are transposing ourselves we can skip a few steps but have to cache some values // if (out === a) { // var a01 = a[1], a02 = a[2], a03 = a[3], // a12 = a[6], a13 = a[7], // a23 = a[11]; // out[1] = a[4]; // out[2] = a[8]; // out[3] = a[12]; // out[4] = a01; // out[6] = a[9]; // out[7] = a[13]; // out[8] = a02; // out[9] = a12; // out[11] = a[14]; // out[12] = a03; // out[13] = a13; // out[14] = a23; // } else { // out[0] = a[0]; // out[1] = a[4]; // out[2] = a[8]; // out[3] = a[12]; // out[4] = a[1]; // out[5] = a[5]; // out[6] = a[9]; // out[7] = a[13]; // out[8] = a[2]; // out[9] = a[6]; // out[10] = a[10]; // out[11] = a[14]; // out[12] = a[3]; // out[13] = a[7]; // out[14] = a[11]; // out[15] = a[15]; // } // return out; // }; // public my_vec4multMat4(out, a, m) { // var x = a[0], y = a[1], z = a[2], w = a[3]; // out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; // out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; // out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; // out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; // return out; // } // //gets upper-left of a 4x4 matrix into a 3x3 of vectors // public my_mat3from4(out, mat4x4) { // out[0][0] = mat4x4[0]; // out[0][1] = mat4x4[1]; // out[0][2] = mat4x4[2]; // out[1][0] = mat4x4[4]; // out[1][1] = mat4x4[5]; // out[1][2] = mat4x4[6]; // out[2][0] = mat4x4[8]; // out[2][1] = mat4x4[9]; // out[2][2] = mat4x4[10]; // } // public my_combine(out, a, b, scale1, scale2) { // out[0] = a[0] * scale1 + b[0] * scale2; // out[1] = a[1] * scale1 + b[1] * scale2; // out[2] = a[2] * scale1 + b[2] * scale2; // } // var vec3 = { // length: function length(a) { // var x = a[0], y = a[1], z = a[2]; // return Math.sqrt(x * x + y * y + z * z) // }, // normalize: function normalize(out, a) { // var x = a[0], y = a[1], z = a[2]; // var len = x * x + y * y + z * z // if (len > 0) { // len = 1 / Math.sqrt(len) // out[0] = a[0] * len // out[1] = a[1] * len // out[2] = a[2] * len // } // return out // }, // dot: function dot(a, b) { // return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; // }, // cross: function cross(out, a, b) { // var ax = a[0], ay = a[1], az = a[2], bx = b[0], by = b[1], bz = b[2]; // out[0] = ay * bz - az * by; // out[1] = az * bx - ax * bz; // out[2] = ax * by - ay * bx; // return out // } // } // var tmp = my_create() // var perspectiveMatrix = my_create(); // var tmpVec4 = [0, 0, 0, 0]; // var row = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]; // var pdum3 = [0, 0, 0]; // public parse(translation, scale, skew, perspective, quaternion){ // var o = this; // if (!translation) translation = [0, 0, 0]; // if (!scale) scale = [0, 0, 0]; // if (!skew) skew = [0, 0, 0]; // if (!perspective) perspective = [0, 0, 0, 1]; // if (!quaternion) quaternion = [0, 0, 0, 1]; // //normalize, if not possible then bail out early // if (!my_normalize(tmp, o._data)) { // return false // } // // perspectiveMatrix is used to solve for perspective, but it also provides // // an easy way to test for singularity of the upper 3x3 component. // my_clone(perspectiveMatrix, tmp); // perspectiveMatrix[3] = 0 // perspectiveMatrix[7] = 0 // perspectiveMatrix[11] = 0 // perspectiveMatrix[15] = 1 // // If the perspectiveMatrix is not invertible, we are also unable to // // decompose, so we'll bail early. Constant taken from SkMatrix44::invert. // if (Math.abs(my_determinant(perspectiveMatrix) < 1e-8)) { // return false // } // var a03 = tmp[3], a13 = tmp[7], a23 = tmp[11], a30 = tmp[12], a31 = tmp[13], a32 = tmp[14], a33 = tmp[15]; // // First, isolate perspective. // if (a03 !== 0 || a13 !== 0 || a23 !== 0) { // tmpVec4[0] = a03 // tmpVec4[1] = a13 // tmpVec4[2] = a23 // tmpVec4[3] = a33 // // Solve the equation by inverting perspectiveMatrix and multiplying // // rightHandSide by the inverse. // // resuing the perspectiveMatrix here since it's no longer needed // var ret = my_invert(perspectiveMatrix, perspectiveMatrix); // if (!ret) { // return false // } // my_transpose(perspectiveMatrix, perspectiveMatrix); // //multiply by transposed inverse perspective matrix, into perspective vec4 // my_vec4multMat4(perspective, tmpVec4, perspectiveMatrix); // } else { // //no perspective // perspective[0] = perspective[1] = perspective[2] = 0 // perspective[3] = 1 // } // // Next take care of translation // translation[0] = a30; // translation[1] = a31; // translation[2] = a32; // // Now get scale and shear. 'row' is a 3 element array of 3 component vectors // my_mat3from4(row, tmp); // // Compute X scale factor and normalize first row. // scale[0] = vec3.length(row[0]); // vec3.normalize(row[0], row[0]); // // Compute XY shear factor and make 2nd row orthogonal to 1st. // skew[0] = vec3.dot(row[0], row[1]); // my_combine(row[1], row[1], row[0], 1.0, -skew[0]) // // Now, compute Y scale and normalize 2nd row. // scale[1] = vec3.length(row[1]) // vec3.normalize(row[1], row[1]) // skew[0] /= scale[1] // // Compute XZ and YZ shears, orthogonalize 3rd row // skew[1] = vec3.dot(row[0], row[2]) // my_combine(row[2], row[2], row[0], 1.0, -skew[1]) // skew[2] = vec3.dot(row[1], row[2]) // my_combine(row[2], row[2], row[1], 1.0, -skew[2]) // // Next, get Z scale and normalize 3rd row. // scale[2] = vec3.length(row[2]) // vec3.normalize(row[2], row[2]) // skew[1] /= scale[2] // skew[2] /= scale[2] // // At this point, the matrix (in rows) is orthonormal. // // Check for a coordinate system flip. If the determinant // // is -1, then negate the matrix and the scaling factors. // vec3.cross(pdum3, row[1], row[2]); // if (vec3.dot(row[0], pdum3) < 0) { // for (var i = 0; i < 3; i++) { // scale[i] *= -1; // row[i][0] *= -1; // row[i][1] *= -1; // row[i][2] *= -1; // } // } // // Now, get the rotations out // quaternion[0] = 0.5 * Math.sqrt(Math.max(1 + row[0][0] - row[1][1] - row[2][2], 0)) // quaternion[1] = 0.5 * Math.sqrt(Math.max(1 - row[0][0] + row[1][1] - row[2][2], 0)) // quaternion[2] = 0.5 * Math.sqrt(Math.max(1 - row[0][0] - row[1][1] + row[2][2], 0)) // quaternion[3] = 0.5 * Math.sqrt(Math.max(1 + row[0][0] + row[1][1] + row[2][2], 0)) // if (row[2][1] > row[1][2]) // quaternion[0] = -quaternion[0] // if (row[0][2] > row[2][0]) // quaternion[1] = -quaternion[1] // if (row[1][0] > row[0][1]) // quaternion[2] = -quaternion[2] // var qx = quaternion[0]; // var qy = quaternion[1]; // var qz = quaternion[2]; // var qw = quaternion[3]; // o.rx = Math.atan2((qw * qx + qy * qz) * 2, 1 - 2 * (qx * qx + qy * qy)); // o.ry = Math.asin(2 * (qw * qy - qz * qx)); // o.rz = Math.atan2((qw * qz + qx * qy) * 2, 1 - 2 * (qy * qy + qz * qz)); // return true // }*/ // //========================================================== // // 序列化数据到输出流里。 // // // // @param output 数据流 // //========================================================== // public serialize(output) { // output.writeFloat(this.tx); // output.writeFloat(this.ty); // output.writeFloat(this.tz); // output.writeFloat(this.rx); // output.writeFloat(this.ry); // output.writeFloat(this.rz); // output.writeFloat(this.sx); // output.writeFloat(this.sy); // output.writeFloat(this.sz); // } // //========================================================== // // 从输入流里反序列化数据。 // // // // @param input 数据流 // //========================================================== // public unserialize(input) { // this.tx = input.readFloat(); // this.ty = input.readFloat(); // this.tz = input.readFloat(); // this.rx = input.readFloat(); // this.ry = input.readFloat(); // this.rz = input.readFloat(); // this.sx = input.readFloat(); // this.sy = input.readFloat(); // this.sz = input.readFloat(); // this.updateForce(); // } // //========================================================== // // 数据内容存储到配置节点中。 // // // // @param config 配置节点 // //========================================================== // public saveConfig(config) { // config.set('tx', FloatUtil.format(this.tx)); // config.set('ty', FloatUtil.format(this.ty)); // config.set('tz', FloatUtil.format(this.tz)); // config.set('rx', FloatUtil.format(this.rx)); // config.set('ry', FloatUtil.format(this.ry)); // config.set('rz', FloatUtil.format(this.rz)); // config.set('sx', FloatUtil.format(this.sx)); // config.set('sy', FloatUtil.format(this.sy)); // config.set('sz', FloatUtil.format(this.sz)); // } }