import {FloatUtil} from '../common/lang/FloatUtil';
import {StringBuffer} from '../common/lang/StringBuffer';
import {MathUtil} from './MathUtil';
import {Point3} from './Point3';
//==========================================================
// 三维矩阵。
//
// @struct
// @author maocy
// @version 150207
//==========================================================
export class Matrix3x3 {
// 数据
public _data = new Array(9);
//============================================================
// 获得数据。
//
// @method
// @return Float32Array 数据
//============================================================
public data() {
return this._data;
}
//============================================================
// 判断数据内容是否相等。
//
// @method
// @param p:data:Array 数据
// @return Boolean 是否相等
//============================================================
public equalsData(p) {
var d = this._data;
for (var i = 0; i < 9; i++) {
if (d[i] != p[i]) {
return false;
}
}
return true;
}
//============================================================
// 接收一个数据内容。
//
// @method
// @param valueData:Array 数据
//============================================================
public assignData(valueData) {
var o = this;
var data = o._data;
for (var n = 0; n < 9; n++) {
data[n] = valueData[n];
}
return o;
}
//============================================================
// 接收一个数据内容。
//
// @method
// @param value:SMatrix4x4 四维矩阵
//============================================================
public assign4x4(value) {
var o = this;
var data = o._data;
var valueData = value.data();
data[0] = valueData[0];
data[1] = valueData[1];
data[2] = valueData[2];
data[3] = valueData[4];
data[4] = valueData[5];
data[5] = valueData[6];
data[6] = valueData[8];
data[7] = valueData[9];
data[8] = valueData[10];
return o;
}
//============================================================
// 追加一个数据内容。
//
// @method
// @param p:data:Array 数据
//============================================================
public appendData(p) {
var d = this._data;
// 矩阵计算
var v0 = (d[0] * p[0]) + (d[1] * p[3]) + (d[2] * p[6]);
var v1 = (d[0] * p[1]) + (d[1] * p[4]) + (d[2] * p[7]);
var v2 = (d[0] * p[2]) + (d[1] * p[5]) + (d[2] * p[8]);
var v3 = (d[3] * p[0]) + (d[4] * p[3]) + (d[5] * p[6]);
var v4 = (d[3] * p[1]) + (d[4] * p[4]) + (d[5] * p[7]);
var v5 = (d[3] * p[2]) + (d[4] * p[5]) + (d[5] * p[8]);
var v6 = (d[6] * p[0]) + (d[7] * p[3]) + (d[8] * p[6]);
var v7 = (d[6] * p[1]) + (d[7] * p[4]) + (d[8] * p[7]);
var v8 = (d[6] * p[2]) + (d[7] * p[5]) + (d[8] * p[8]);
// 复制内容
d[0] = v0;
d[1] = v1;
d[2] = v2;
d[3] = v3;
d[4] = v4;
d[5] = v5;
d[6] = v6;
d[7] = v7;
d[8] = v8;
}
//============================================================
// X轴旋转内容。
// 1 0 0 0
// 0 cos sin 0
// 0 -sin cos 0
// 0 0 0 1
//
// @method
// @param p:value:Float 弧度
//============================================================
public rotationX(p) {
// 计算旋转
var rs = Math.sin(p);
var rc = Math.cos(p);
// 追加内容
var v = MathUtil.VALUE_9;
v[0] = 1;
v[1] = 0;
v[2] = 0;
v[3] = 0;
v[4] = rc;
v[5] = rs;
v[6] = 0;
v[7] = -rs;
v[8] = rc;
this.appendData(v);
}
//============================================================
// Y轴旋转内容。
// cos 0 sin 0
// 0 1 0 0
// -sin 0 cos 0
// 0 0 0 1
//
// @method
// @param p:value:Float 弧度
//============================================================
public rotationY(p) {
// 计算旋转
var rs = Math.sin(p);
var rc = Math.cos(p);
// 追加内容
var v = MathUtil.VALUE_9;
v[0] = rc;
v[1] = 0;
v[2] = rs;
v[3] = 0;
v[4] = 1;
v[5] = 0;
v[6] = -rs;
v[7] = 0;
v[8] = rc;
this.appendData(v);
}
//============================================================
// Z轴旋转内容。
// cos sin 0 0
// -sin cos 1 0
// 0 0 1 0
// 0 0 0 1
//
// @method
// @param p:value:Float 弧度
//============================================================
public rotationZ(p) {
// 计算旋转
var rs = Math.sin(p);
var rc = Math.cos(p);
// 追加内容
var v = MathUtil.VALUE_9;
v[0] = rc;
v[1] = rs;
v[2] = 0;
v[3] = -rs;
v[4] = rc;
v[5] = 1;
v[6] = 0;
v[7] = 0;
v[8] = 1;
this.appendData(v);
}
//============================================================
// 设置旋转内容。
// 1 0 0 0
// 0 cos sin 0
// 0 -sin cos 0
// 0 0 0 1
//
// @method
// @param x:Float X弧度
// @param y:Float Y弧度
// @param z:Float Z弧度
//============================================================
public rotation(x, y, z) {
// 计算旋转
var rsx = Math.sin(x);
var rcx = Math.cos(x);
var rsy = Math.sin(y);
var rcy = Math.cos(y);
var rsz = Math.sin(z);
var rcz = Math.cos(z);
// 追加内容
var v = MathUtil.VALUE_9;
v[0] = rcy * rcz;
v[1] = rcy * rsz;
v[2] = -rsy;
v[3] = rsx * rsy * rcz - rcx * rsz;
v[4] = rsx * rsy * rsz + rcx * rcz;
v[5] = rsx * rcy;
v[6] = rcx * rsy * rcz + rsx * rsz;
v[7] = rcx * rsy * rsz - rsx * rcx;
v[8] = rcx * rcy;
this.appendData(v);
}
//============================================================
// 计算逆矩阵。
//
// @method
// @return Boolean 是否成功
//============================================================
public invert() {
var o = this;
var d = o._data;
var v = MathUtil.VALUE_9;
// 计算矩阵
v[0] = (d[4] * d[8]) - (d[5] * d[7]);
v[1] = (d[2] * d[7]) - (d[1] * d[8]);
v[2] = (d[1] * d[5]) - (d[2] * d[4]);
v[3] = (d[5] * d[6]) - (d[3] * d[8]);
v[4] = (d[0] * d[8]) - (d[2] * d[6]);
v[5] = (d[2] * d[3]) - (d[0] * d[5]);
v[6] = (d[3] * d[7]) - (d[4] * d[6]);
v[7] = (d[1] * d[6]) - (d[0] * d[7]);
v[8] = (d[0] * d[4]) - (d[1] * d[3]);
// 计算内容
var r = (d[0] * v[0]) + (d[1] * v[3]) + (d[2] * v[6]);
if (r == 0) {
return false;
}
r = 1 / r;
// 设置内容
for (var i = 0; i < 9; i++) {
d[i] = v[i] * r;
}
return true;
}
//==========================================================
// 变换顶点数据。
//
// @method
// @param po:outputData:Array 输出数据
// @param pi:inputData:Array 输入数据
// @param pc:count:Integer 个数
//==========================================================
public transform(po, pi, pc) {
var d = this._data;
for (var i = 0; i < pc; i++) {
var n = (i << 1) + i;
po[n] = (pi[n] * d[0]) + (pi[n + 1] * d[3]) + (pi[n + 2] * d[6]);
po[n + 1] = (pi[n] * d[1]) + (pi[n + 1] * d[4]) + (pi[n + 2] * d[7]);
po[n + 2] = (pi[n] * d[2]) + (pi[n + 1] * d[5]) + (pi[n + 2] * d[8]);
}
}
//==========================================================
// 变换顶点数据。
//
// @method
// @param inputPoint:SPoint3 输入顶点
// @param outputPoint:SPoint3 输出顶点
//==========================================================
public transformPoint3(inputPoint, outputPoint) {
var d = this._data;
// 计算内容
var x = (inputPoint.x * d[0]) + (inputPoint.y * d[3]) + (inputPoint.z * d[6]);
var y = (inputPoint.x * d[1]) + (inputPoint.y * d[4]) + (inputPoint.z * d[7]);
var z = (inputPoint.x * d[2]) + (inputPoint.y * d[5]) + (inputPoint.z * d[8]);
// 输出结果
var value = null;
if (outputPoint) {
value = outputPoint;
} else {
value = new Point3();
}
value.set(x, y, z);
return value;
}
//============================================================
// 构建一个矩阵。
//
// @method
// @param t:translation:SPoint3 位移
// @param r:quaternion:SQuaternion 旋转
// @param s:scale:SVector3 缩放
//============================================================
public build(r) {
var d = this._data;
var x2 = r.x * r.x;
var y2 = r.y * r.y;
var z2 = r.z * r.z;
var xy = r.x * r.y;
var xz = r.x * r.z;
var yz = r.y * r.z;
var wx = r.w * r.x;
var wy = r.w * r.y;
var wz = r.w * r.z;
d[0] = 1 - 2 * (y2 + z2);
d[1] = 2 * (xy - wz);
d[2] = 2 * (xz + wy);
d[3] = 2 * (xy + wz);
d[4] = 1 - 2 * (x2 + z2);
d[5] = 2 * (yz - wx);
d[6] = 2 * (xz - wy);
d[7] = 2 * (yz + wx);
d[8] = 1 - 2 * (x2 + y2);
}
//==========================================================
// 写入数据。
//
// @method
// @param d:data:Array 数组
// @param i:offset:Integer 索引位置
//==========================================================
public writeData(d, i) {
var o = this;
var pd = o._data;
d[i++] = pd[0];
d[i++] = pd[3];
d[i++] = pd[6];
d[i++] = pd[1];
d[i++] = pd[4];
d[i++] = pd[7];
d[i++] = pd[2];
d[i++] = pd[5];
d[i++] = pd[8];
}
//==========================================================
// 获得字符串。
//
// @method
// @return String 字符串
//==========================================================
public toString() {
var d = this._data;
var r = new StringBuffer();
for (var y = 0; y < 3; y++) {
if (y > 0) {
r.append('|');
}
for (var x = 0; x < 3; x++) {
var i = y * 3 + x;
var v = d[i];
if (x > 0) {
r.append(',');
}
r.append(FloatUtil.format(v, 0, null, 3, null));
}
}
return r.flush();
}
}