scripts/path-controller/util/vectormath.js
import * as util from './util.js';
import nstructjs from './struct.js';
export const EulerOrders = {
XYZ: 0,
XZY: 1,
YXZ: 2,
YZX: 3,
ZXY: 4,
ZYX: 5
};
/**
* @param mode one of 'es', 'commonjs', 'rjs'
*/
window.makeCompiledVectormathCode = function (mode = "es") {
let s = "";
let es6exports = mode === "es";
function doExports(name) {
if (es6exports) {
return "export";
} else {
return `var ${name} = exports.${name} =`;
}
}
let classes = [Vector2, Vector3, Vector4, a];
let lens = {
Vector2: 2,
Vector3: 3,
Vector4: 4,
Quat : 4
};
let modecode = "";
let nstructjscode = `
let g = typeof window !== "undefined" ? window : "undefined";
g = g || (typeof global !== "undefined" ? global : "undefined");
g = g || (typeof self !== "undefined" ? self : "undefined");
g = g || (typeof globals !== "undefined" ? globals : "undefined");
if (typeof nstructjs === "undefined") {
//add nstructjs stub
g.nstructjs = {
register : function() {}
}
}
`
if (mode !== "rjs") {
if (mode === "commonjs") {
modecode = `if (typeof module !== "undefined" && typeof exports === "undefined") {
if (module.exports === undefined) {
module.exports = {};
}
g.exports = module.exports;
} else if (typeof module === "undefined") {
g.exports = g.vectormath = {};
}\n`;
}
s += `{
${nstructjscode}
${modecode}
}`;
}
s += `
class cachering extends Array {
constructor(func, size) {
super()
this.cur = 0;
for (var i=0; i<size; i++) {
this.push(func());
}
}
static fromConstructor(cls, size) {
var func = function() {
return new cls();
}
return new cachering(func, size);
}
next() {
var ret = this[this.cur];
this.cur = (this.cur+1)%this.length;
return ret;
}
}
`;
s += `
var M_SQRT2 = Math.sqrt(2.0);
var FLT_EPSILON = 2.22e-16;
var sin=Math.sin, cos=Math.cos, abs=Math.abs, log=Math.log,
asin=Math.asin, exp=Math.exp, acos=Math.acos, fract=Math.fract,
sign=Math.sign, tent=Math.tent, atan2=Math.atan2, atan=Math.atan,
pow=Math.pow, sqrt=Math.sqrt, floor=Math.floor, ceil=Math.ceil,
min=Math.min, max=Math.max, PI=Math.PI, E=2.718281828459045;
var DOT_NORM_SNAP_LIMIT = 0.00000000001;
${doExports("BaseVector")} class BaseVector extends Array {
constructor() {
super();
this.vec = undefined; //for compatibility with old files
}
copy() {
return new this.constructor(this);
}
load(data) {
throw new Error("Implement me!");
}
vectorLength() {
return sqrt(this.dot(this));
}
normalize() {
var l = this.vectorLength();
if (l > 0.00000001) {
this.mulScalar(1.0/l);
}
return this;
}
}
`;
function indent(s, pad = " ") {
let l = s.split("\n");
let s2 = "";
for (let l2 of l) {
s2 += pad + l2 + "\n";
}
return s2;
}
let i = 0;
for (let cls of classes) {
s += doExports(cls.name) + " class " + cls.name + " extends BaseVector {\n";
let keys = Reflect.ownKeys(cls.prototype);
for (let k of keys) {
let v = cls.prototype[k];
if (typeof v !== "function") {
continue;
}
if (typeof k === "symbol") {
k = " [" + k.toString() + "]";
}
v = ("" + v).trim();
if (v.startsWith("function(") || v.startsWith("function (")) {
v = k + v.slice(8, v.length).trim();
} else if (v.startsWith("function")) {
v = v.slice(8, v.length).trim();
}
if (v.endsWith(";}")) {
v = v.slice(0, v.length - 1) + "\n }\n";
}
let zero = "";
let l = lens[cls.name];
for (let j = 0; j < l; j++) {
if (j > 0) {
zero += " = ";
}
zero += `this[${j}]`;
}
zero += " = 0.0";
if (k === "constructor") {
s += ` constructor(data) {
super(${l});
this.vec = undefined; //for compatibility with old files
if (arguments.length > 1) {
throw new Error("unexpected argument");
}
//this.length = ${l};
${zero};
if (data !== undefined) {
this.load(data);
}
}
`;
} else {
s += indent(v);
}
s += "\n";
i++;
}
s += "}\n\n"
s += `${cls.name}.STRUCT = \`${cls.STRUCT}\`;\n`;
s += `nstructjs.register(${cls.name});\n\n`;
}
s += "\n\n" + ("" + internal_matrix).trim() + "\n";
s += "\n" + doExports("Matrix4") + Matrix4;
s += `\n Matrix4.STRUCT = \`${Matrix4.STRUCT}\`;\n`;
s += "nstructjs.register(Matrix4)\n";
s += `
var _quat_vs3_temps = cachering.fromConstructor(Vector3, 64);
var _v3nd4_n1_normalizedDot4 = new Vector3();
var _v3nd4_n2_normalizedDot4 = new Vector3();
var _v3nd_n1_normalizedDot = new Vector3();
var _v3nd_n2_normalizedDot = new Vector3();
var $_v3nd4_n1_normalizedDot4 = new Vector3();
var $_v3nd4_n2_normalizedDot4 = new Vector3();
var $_v3nd_n1_normalizedDot = new Vector3();
var $_v3nd_n2_normalizedDot = new Vector3();
var lookat_cache_vs3 = cachering.fromConstructor(Vector3, 64);
var lookat_cache_vs4 = cachering.fromConstructor(Vector4, 64);
var makenormalcache = cachering.fromConstructor(Vector3, 64);
`;
if (mode === "rjs") {
s = `define([], function() {
"use strict";
let exports = {};
{
${nstructjscode}
}
${indent(s)}
return exports;
});
`;
}
return s;
}
var sin = Math.sin, cos = Math.cos, abs = Math.abs, log = Math.log,
asin = Math.asin, exp = Math.exp, acos = Math.acos, fract = Math.fract,
sign = Math.sign, tent = Math.tent, atan2 = Math.atan2, atan = Math.atan,
pow = Math.pow, sqrt = Math.sqrt, floor = Math.floor, ceil = Math.ceil,
min = Math.min, max = Math.max, PI = Math.PI, E = 2.718281828459045;
var DOT_NORM_SNAP_LIMIT = 0.00000000001;
var M_SQRT2 = Math.sqrt(2.0);
var FLT_EPSILON = 2.22e-16;
var basic_funcs = {
equals : [["b"], "this[X] === b[X]", "&&"],
/*dot is made manually so it's safe for acos
dot : [["b"], "this[X]*b[X]", "+"],
*/
zero : [[], "0.0;"],
negate : [[], "-this[X];"],
combine : [["b", "u", "v"], "this[X]*u + this[X]*v;"],
interp : [["b", "t"], "this[X] + (b[X] - this[X])*t;"],
add : [["b"], "this[X] + b[X];"],
addFac : [["b", "F"], "this[X] + b[X]*F;"],
fract : [[], "Math.fract(this[X]);"],
sub : [["b"], "this[X] - b[X];"],
mul : [["b"], "this[X] * b[X];"],
div : [["b"], "this[X] / b[X];"],
mulScalar: [["b"], "this[X] * b;"],
divScalar: [["b"], "this[X] / b;"],
addScalar: [["b"], "this[X] + b;"],
subScalar: [["b"], "this[X] - b;"],
minScalar: [["b"], "Math.min(this[X], b);"],
maxScalar: [["b"], "Math.max(this[X], b);"],
ceil : [[], "Math.ceil(this[X])"],
floor : [[], "Math.floor(this[X])"],
abs : [[], "Math.abs(this[X])"],
min : [["b"], "Math.min(this[X], b[X])"],
max : [["b"], "Math.max(this[X], b[X])"],
clamp : [["MIN", "MAX"], "min(max(this[X], MAX), MIN)"],
};
function bounded_acos(fac) {
if (fac <= -1.0)
return Math.pi;
else if (fac >= 1.0)
return 0.0;
else
return Math.acos(fac);
}
function make_norm_safe_dot(cls) {
var _dot = cls.prototype.dot;
cls.prototype._dot = _dot;
cls.prototype.dot = function (b) {
var ret = _dot.call(this, b);
if (ret >= 1.0 - DOT_NORM_SNAP_LIMIT && ret <= 1.0 + DOT_NORM_SNAP_LIMIT)
return 1.0;
if (ret >= -1.0 - DOT_NORM_SNAP_LIMIT && ret <= -1.0 + DOT_NORM_SNAP_LIMIT)
return -1.0;
return ret;
}
}
function getBaseVector(parent) {
return class BaseVector extends parent {
constructor() {
super(...arguments);
this.vec = undefined; //for compatibility with old nstructjs-saved files
//this.xyzw = this.init_swizzle(4);
//this.xyz = this.init_swizzle(3);
//this.xy = this.init_swizzle(2);
}
static inherit(cls, vectorsize) {
make_norm_safe_dot(cls);
var f;
var vectorDotDistance = "f = function vectorDotDistance(b) {\n";
for (var i = 0; i < vectorsize; i++) {
vectorDotDistance += " let d" + i + " = this[" + i + "]-b[" + i + "];\n\n ";
}
vectorDotDistance += " return "
for (var i = 0; i < vectorsize; i++) {
if (i > 0)
vectorDotDistance += " + ";
vectorDotDistance += "d" + i + "*d" + i;
}
vectorDotDistance += ";\n"
vectorDotDistance += "};";
cls.prototype.vectorDotDistance = eval(vectorDotDistance);
var f;
var vectorDistance = "f = function vectorDistance(b) {\n";
for (var i = 0; i < vectorsize; i++) {
vectorDistance += ` let d${i} = this[${i}] - (b[${i}]||0);\n\n `;
//vectorDistance += " let d"+i+" = this["+i+"]-(b["+i+"]||0);\n\n ";
}
vectorDistance += " return Math.sqrt("
for (var i = 0; i < vectorsize; i++) {
if (i > 0)
vectorDistance += " + ";
vectorDistance += "d" + i + "*d" + i;
}
vectorDistance += ");\n"
vectorDistance += "};";
cls.prototype.vectorDistance = eval(vectorDistance);
var vectorDistanceSqr = "f = function vectorDistanceSqr(b) {\n";
for (var i = 0; i < vectorsize; i++) {
vectorDistanceSqr += ` let d${i} = this[${i}] - (b[${i}]||0);\n\n `;
//vectorDistanceSqr += " let d"+i+" = this["+i+"]-(b["+i+"]||0);\n\n ";
}
vectorDistanceSqr += " return ("
for (var i = 0; i < vectorsize; i++) {
if (i > 0)
vectorDistanceSqr += " + ";
vectorDistanceSqr += "d" + i + "*d" + i;
}
vectorDistanceSqr += ");\n"
vectorDistanceSqr += "};";
cls.prototype.vectorDistanceSqr = eval(vectorDistanceSqr);
for (var k in basic_funcs) {
var func = basic_funcs[k];
var args = func[0];
var line = func[1];
var f;
var code = "f = function " + k + "("
for (var i = 0; i < args.length; i++) {
if (i > 0)
code += ", ";
line = line.replace(args[i], args[i].toLowerCase());
code += args[i].toLowerCase();
}
code += ") {\n";
if (func.length > 2) {
//make summation
code += " return ";
for (var i = 0; i < vectorsize; i++) {
if (i > 0)
code += func[2];
code += "(" + line.replace(/X/g, "" + i) + ")";
}
code += ";\n";
} else {
for (var i = 0; i < vectorsize; i++) {
var line2 = line.replace(/X/g, "" + i);
code += " this[" + i + "] = " + line2 + ";\n";
}
code += " return this;\n"
}
code += "}\n";
//console.log(code);
var f = eval(code);
cls.prototype[k] = f;
//console.log(k, f);
}
}
copy() {
return new this.constructor(this);
}
load(data) {
throw new Error("Implement me!");
}
init_swizzle(size) {
var ret = {};
var cls = size === 4 ? Vector4 : (size === 3 ? Vector3 : Vector2);
for (var k in cls.prototype) {
var v = cls.prototype[k];
if (typeof v !== "function" && !(v instanceof Function))
continue;
ret[k] = v.bind(this);
}
return ret;
}
vectorLength() {
return sqrt(this.dot(this));
}
swapAxes(axis1, axis2) {
let t = this[axis1];
this[axis1] = this[axis2];
this[axis2] = t;
return this;
}
normalize() {
/*
for (let i=0; i<this.length; i++) {
if (util.isDenormal(this[i])) {
console.error("Denormal error", i, this[i]);
this[i] = 0.0;
}
}
//*/
let l = this.vectorLength();
/*
if (util.isDenormal(l)) {
console.error("Denormal error", l);
}
//*/
if (l > 0.00000001) {
this.mulScalar(1.0/l);
}
return this;
}
}
}
export const BaseVector = getBaseVector(Array);
export const F64BaseVector = getBaseVector(Float64Array);
export const F32BaseVector = getBaseVector(Float32Array);
function myclamp(f, a, b) {
return Math.min(Math.max(f, a), b);
}
export class Vector4 extends BaseVector {
constructor(data) {
super(4);
if (arguments.length > 1) {
throw new Error("unexpected argument");
}
this[0] = this[1] = this[2] = this[3] = 0.0;
if (data !== undefined) {
this.load(data);
}
}
toCSS() {
let r = ~~(this[0]*255);
let g = ~~(this[1]*255);
let b = ~~(this[2]*255);
let a = this[3];
return `rgba(${r},${g},${b},${a})`
}
loadXYZW(x, y, z, w) {
this[0] = x;
this[1] = y;
this[2] = z;
this[3] = w;
return this;
}
loadXYZ(x, y, z) {
this[0] = x;
this[1] = y;
this[2] = z;
return this;
}
load(data) {
if (data === undefined)
return this;
this[0] = data[0];
this[1] = data[1];
this[2] = data[2];
this[3] = data[3];
return this;
}
dot(b) {
return this[0]*b[0] + this[1]*b[1] + this[2]*b[2] + this[3]*b[3];
}
mulVecQuat(q) {
let t0 = -q[1] * this[0] - q[2] * this[1] - q[3] * this[2];
let t1 = q[0] * this[0] + q[2] * this[2] - q[3] * this[1];
let t2 = q[0] * this[1] + q[3] * this[0] - q[1] * this[2];
this[2] = q[0] * this[2] + q[1] * this[1] - q[2] * this[0];
this[0] = t1;
this[1] = t2;
t1 = t0 * -q[1] + this[0] * q[0] - this[1] * q[3] + this[2] * q[2];
t2 = t0 * -q[2] + this[1] * q[0] - this[2] * q[1] + this[0] * q[3];
this[2] = t0 * -q[3] + this[2] * q[0] - this[0] * q[2] + this[1] * q[1];
this[0] = t1;
this[1] = t2;
return this;
}
multVecMatrix(matrix) {
var x = this[0];
var y = this[1];
var z = this[2];
var w = this[3];
this[0] = w*matrix.$matrix.m41 + x*matrix.$matrix.m11 + y*matrix.$matrix.m21 + z*matrix.$matrix.m31;
this[1] = w*matrix.$matrix.m42 + x*matrix.$matrix.m12 + y*matrix.$matrix.m22 + z*matrix.$matrix.m32;
this[2] = w*matrix.$matrix.m43 + x*matrix.$matrix.m13 + y*matrix.$matrix.m23 + z*matrix.$matrix.m33;
this[3] = w*matrix.$matrix.m44 + x*matrix.$matrix.m14 + y*matrix.$matrix.m24 + z*matrix.$matrix.m34;
return this[3];
}
cross(v) {
var x = this[1]*v[2] - this[2]*v[1];
var y = this[2]*v[0] - this[0]*v[2];
var z = this[0]*v[1] - this[1]*v[0];
this[0] = x;
this[1] = y;
this[2] = z;
return this;
}
preNormalizedAngle(v2) {
let th = this.dot(v2)*0.99999;
return Math.acos(th);
}
loadSTRUCT(reader) {
reader(this);
if (typeof this.vec !== "undefined") {
this.load(this.vec);
this.vec = undefined;
}
}
};
Vector4.STRUCT = `
vec4 {
0 : float;
1 : float;
2 : float;
3 : float;
}
`;
nstructjs.manager.add_class(Vector4);
var _v3nd_n1_normalizedDot, _v3nd_n2_normalizedDot;
var _v3nd4_n1_normalizedDot4, _v3nd4_n2_normalizedDot4;
export class Vector3 extends F64BaseVector {
constructor(data) {
super(3);
if (arguments.length > 1) {
throw new Error("unexpected argument");
}
this[0] = this[1] = this[2] = 0.0;
if (data !== undefined) {
this.load(data);
}
if (this.constructor === Vector3) {
Object.preventExtensions(this);
}
}
//normalizedDot4
static normalizedDot4(v1, v2, v3, v4) {
$_v3nd4_n1_normalizedDot4.load(v2).sub(v1).normalize();
$_v3nd4_n2_normalizedDot4.load(v4).sub(v3).normalize();
return $_v3nd4_n1_normalizedDot4.dot($_v3nd4_n2_normalizedDot4);
}
static normalizedDot3(v1, center, v2) {
$_v3nd4_n1_normalizedDot3.load(v1).sub(center).normalize();
$_v3nd4_n2_normalizedDot3.load(v2).sub(center).normalize();
return $_v3nd4_n1_normalizedDot3.dot($_v3nd4_n2_normalizedDot3);
}
toCSS() {
let r = ~~(this[0]*255);
let g = ~~(this[1]*255);
let b = ~~(this[2]*255);
return `rgb(${r},${g},${b})`
}
loadXYZ(x, y, z) {
this[0] = x;
this[1] = y;
this[2] = z;
return this;
}
loadXY(x, y) {
this[0] = x;
this[1] = y;
return this;
}
toJSON() {
return [this[0], this[1], this[2]];
}
loadJSON(obj) {
return this.load(obj);
}
initVector3() {
this.length = 3;
this[0] = this[1] = this[2] = 0;
return this;
}
load(data) {
if (data === undefined)
return this;
//if (isNaN(data[0]) || isNaN(data[1]) || isNaN(data[2])) {
// throw new Error("NaN");
//}
this[0] = data[0];
this[1] = data[1];
this[2] = data[2];
return this;
}
dot(b) {
return this[0]*b[0] + this[1]*b[1] + this[2]*b[2];
}
normalizedDot(v) {
$_v3nd_n1_normalizedDot.load(this);
$_v3nd_n2_normalizedDot.load(v);
$_v3nd_n1_normalizedDot.normalize();
$_v3nd_n2_normalizedDot.normalize();
return $_v3nd_n1_normalizedDot.dot($_v3nd_n2_normalizedDot);
}
mulVecQuat(q) {
let t0 = -q[1] * this[0] - q[2] * this[1] - q[3] * this[2];
let t1 = q[0] * this[0] + q[2] * this[2] - q[3] * this[1];
let t2 = q[0] * this[1] + q[3] * this[0] - q[1] * this[2];
this[2] = q[0] * this[2] + q[1] * this[1] - q[2] * this[0];
this[0] = t1;
this[1] = t2;
t1 = t0 * -q[1] + this[0] * q[0] - this[1] * q[3] + this[2] * q[2];
t2 = t0 * -q[2] + this[1] * q[0] - this[2] * q[1] + this[0] * q[3];
this[2] = t0 * -q[3] + this[2] * q[0] - this[0] * q[2] + this[1] * q[1];
this[0] = t1;
this[1] = t2;
return this;
}
multVecMatrix(matrix, ignore_w) {
if (ignore_w === undefined) {
ignore_w = false;
}
var x = this[0];
var y = this[1];
var z = this[2];
this[0] = matrix.$matrix.m41 + x*matrix.$matrix.m11 + y*matrix.$matrix.m21 + z*matrix.$matrix.m31;
this[1] = matrix.$matrix.m42 + x*matrix.$matrix.m12 + y*matrix.$matrix.m22 + z*matrix.$matrix.m32;
this[2] = matrix.$matrix.m43 + x*matrix.$matrix.m13 + y*matrix.$matrix.m23 + z*matrix.$matrix.m33;
var w = matrix.$matrix.m44 + x*matrix.$matrix.m14 + y*matrix.$matrix.m24 + z*matrix.$matrix.m34;
if (!ignore_w && w !== 1 && w !== 0 && matrix.isPersp) {
this[0] /= w;
this[1] /= w;
this[2] /= w;
}
return w;
}
cross(v) {
var x = this[1]*v[2] - this[2]*v[1];
var y = this[2]*v[0] - this[0]*v[2];
var z = this[0]*v[1] - this[1]*v[0];
this[0] = x;
this[1] = y;
this[2] = z;
return this;
}
//axis is optional, 0
rot2d(A, axis) {
var x = this[0];
var y = this[1];
if (axis === 1) {
this[0] = x*cos(A) + y*sin(A);
this[1] = y*cos(A) - x*sin(A);
} else {
this[0] = x*cos(A) - y*sin(A);
this[1] = y*cos(A) + x*sin(A);
}
return this;
}
preNormalizedAngle(v2) {
let th = this.dot(v2)*0.99999;
return Math.acos(th);
}
loadSTRUCT(reader) {
reader(this);
if (typeof this.vec !== "undefined") {
this.load(this.vec);
this.vec = undefined;
}
}
}
Vector3.STRUCT = `
vec3 {
0 : float;
1 : float;
2 : float;
}
`;
nstructjs.manager.add_class(Vector3);
export class Vector2 extends BaseVector {
constructor(data) {
super(2);
if (arguments.length > 1) {
throw new Error("unexpected argument");
}
this[0] = this[1] = 0.0;
if (data !== undefined) {
this.load(data);
}
}
initVector2(co) {
this.length = 2;
if (co !== undefined) {
this[0] = co[0];
this[1] = co[1];
} else {
this[0] = this[1] = 0.0;
}
return this;
}
loadXY(x, y) {
this[0] = x;
this[1] = y;
return this;
}
toJSON() {
return [this[0], this[1]];
}
loadJSON(obj) {
return this.load(obj);
}
loadXY(x, y) {
this[0] = x;
this[1] = y;
return this;
}
load(data) {
if (data === undefined)
return this;
this[0] = data[0];
this[1] = data[1];
return this;
}
//axis is optional, 0
rot2d(A, axis) {
var x = this[0];
var y = this[1];
if (axis === 1) {
this[0] = x*cos(A) + y*sin(A);
this[1] = y*cos(A) - x*sin(A);
} else {
this[0] = x*cos(A) - y*sin(A);
this[1] = y*cos(A) + x*sin(A);
}
return this;
}
dot(b) {
return this[0]*b[0] + this[1]*b[1];
}
multVecMatrix(matrix) {
var x = this[0];
var y = this[1];
var w = 1.0;
this[0] = w*matrix.$matrix.m41 + x*matrix.$matrix.m11 + y*matrix.$matrix.m21;
this[1] = w*matrix.$matrix.m42 + x*matrix.$matrix.m12 + y*matrix.$matrix.m22;
if (matrix.isPersp) {
let w2 = w*matrix.$matrix.m44 + x*matrix.$matrix.m14 + y*matrix.$matrix.m24;
if (w2 !== 0.0) {
this[0] /= w2;
this[1] /= w2;
}
}
return this;
}
mulVecQuat(q) {
let t0 = -q[1] * this[0] - q[2] * this[1];
let t1 = q[0] * this[0] - q[3] * this[1];
let t2 = q[0] * this[1] + q[3] * this[0];
let z = q[1] * this[1] - q[2] * this[0];
this[0] = t1;
this[1] = t2;
t1 = t0 * -q[1] + this[0] * q[0] - this[1] * q[3] + z * q[2];
t2 = t0 * -q[2] + this[1] * q[0] - z * q[1] + this[0] * q[3];
this[0] = t1;
this[1] = t2;
return this;
}
vectorLengthSqr() {
return this.dot(this);
}
loadSTRUCT(reader) {
reader(this);
if (typeof this.vec !== undefined) {
this.load(this.vec);
this.vec = undefined;
}
}
};
Vector2.STRUCT = `
vec2 {
0 : float;
1 : float;
}
`;
nstructjs.manager.add_class(Vector2);
let _quat_vs3_temps = util.cachering.fromConstructor(Vector3, 64);
export class Quat extends Vector4 {
makeUnitQuat() {
this[0] = 1.0;
this[1] = this[2] = this[3] = 0.0;
}
isZero() {
return (this[0] === 0 && this[1] === 0 && this[2] === 0 && this[3] === 0);
}
mulQuat(qt) {
var a = this[0]*qt[0] - this[1]*qt[1] - this[2]*qt[2] - this[3]*qt[3];
var b = this[0]*qt[1] + this[1]*qt[0] + this[2]*qt[3] - this[3]*qt[2];
var c = this[0]*qt[2] + this[2]*qt[0] + this[3]*qt[1] - this[1]*qt[3];
this[3] = this[0]*qt[3] + this[3]*qt[0] + this[1]*qt[2] - this[2]*qt[1];
this[0] = a;
this[1] = b;
this[2] = c;
}
conjugate() {
this[1] = -this[1];
this[2] = -this[2];
this[3] = -this[3];
}
dotWithQuat(q2) {
return this[0]*q2[0] + this[1]*q2[1] + this[2]*q2[2] + this[3]*q2[3];
}
invert() {
var f = this.dot(this);
if (f === 0.0)
return;
conjugate_qt(q);
this.mulscalar(1.0/f);
}
sub(q2) {
var nq2 = new Quat();
nq2[0] = -q2[0];
nq2[1] = q2[1];
nq2[2] = q2[2];
nq2[3] = q2[3];
this.mul(nq2);
}
mulScalarWithFactor(fac) {
var angle = fac*bounded_acos(this[0]);
var co = Math.cos(angle);
var si = Math.sin(angle);
this[0] = co;
var last3 = Vector3([this[1], this[2], this[3]]);
last3.normalize();
last3.mulScalar(si);
this[1] = last3[0];
this[2] = last3[1];
this[3] = last3[2];
return this;
}
toMatrix(m) {
if (m === undefined) {
m = new Matrix4();
}
var q0 = M_SQRT2*this[0];
var q1 = M_SQRT2*this[1];
var q2 = M_SQRT2*this[2];
var q3 = M_SQRT2*this[3];
var qda = q0*q1;
var qdb = q0*q2;
var qdc = q0*q3;
var qaa = q1*q1;
var qab = q1*q2;
var qac = q1*q3;
var qbb = q2*q2;
var qbc = q2*q3;
var qcc = q3*q3;
m.$matrix.m11 = (1.0 - qbb - qcc);
m.$matrix.m12 = (qdc + qab);
m.$matrix.m13 = (-qdb + qac);
m.$matrix.m14 = 0.0;
m.$matrix.m21 = (-qdc + qab);
m.$matrix.m22 = (1.0 - qaa - qcc);
m.$matrix.m23 = (qda + qbc);
m.$matrix.m24 = 0.0;
m.$matrix.m31 = (qdb + qac);
m.$matrix.m32 = (-qda + qbc);
m.$matrix.m33 = (1.0 - qaa - qbb);
m.$matrix.m34 = 0.0;
m.$matrix.m41 = m.$matrix.m42 = m.$matrix.m43 = 0.0;
m.$matrix.m44 = 1.0;
return m;
}
matrixToQuat(wmat) {
var mat = temp_mats.next();
mat.load(wmat);
mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
mat.$matrix.m44 = 1.0;
var r1 = new Vector3([mat.$matrix.m11, mat.$matrix.m12, mat.$matrix.m13]);
var r2 = new Vector3([mat.$matrix.m21, mat.$matrix.m22, mat.$matrix.m23]);
var r3 = new Vector3([mat.$matrix.m31, mat.$matrix.m32, mat.$matrix.m33]);
r1.normalize();
r2.normalize();
r3.normalize();
mat.$matrix.m11 = r1[0];
mat.$matrix.m12 = r1[1];
mat.$matrix.m13 = r1[2];
mat.$matrix.m21 = r2[0];
mat.$matrix.m22 = r2[1];
mat.$matrix.m23 = r2[2];
mat.$matrix.m31 = r3[0];
mat.$matrix.m32 = r3[1];
mat.$matrix.m33 = r3[2];
var tr = 0.25*(1.0 + mat.$matrix.m11 + mat.$matrix.m22 + mat.$matrix.m33);
var s = 0;
if (tr > FLT_EPSILON) {
s = Math.sqrt(tr);
this[0] = s;
s = 1.0/(4.0*s);
this[1] = ((mat.$matrix.m23 - mat.$matrix.m32)*s);
this[2] = ((mat.$matrix.m31 - mat.$matrix.m13)*s);
this[3] = ((mat.$matrix.m12 - mat.$matrix.m21)*s);
} else {
if (mat.$matrix.m11 > mat.$matrix.m22 && mat.$matrix.m11 > mat.$matrix.m33) {
s = 2.0*Math.sqrt(1.0 + mat.$matrix.m11 - mat.$matrix.m22 - mat.$matrix.m33);
this[1] = (0.25*s);
s = 1.0/s;
this[0] = ((mat.$matrix.m32 - mat.$matrix.m23)*s);
this[2] = ((mat.$matrix.m21 + mat.$matrix.m12)*s);
this[3] = ((mat.$matrix.m31 + mat.$matrix.m13)*s);
} else if (mat.$matrix.m22 > mat.$matrix.m33) {
s = 2.0*Math.sqrt(1.0 + mat.$matrix.m22 - mat.$matrix.m11 - mat.$matrix.m33);
this[2] = (0.25*s);
s = 1.0/s;
this[0] = ((mat.$matrix.m31 - mat.$matrix.m13)*s);
this[1] = ((mat.$matrix.m21 + mat.$matrix.m12)*s);
this[3] = ((mat.$matrix.m32 + mat.$matrix.m23)*s);
} else {
s = 2.0*Math.sqrt(1.0 + mat.$matrix.m33 - mat.$matrix.m11 - mat.$matrix.m22);
this[3] = (0.25*s);
s = 1.0/s;
this[0] = ((mat.$matrix.m21 - mat.$matrix.m12)*s);
this[1] = ((mat.$matrix.m31 + mat.$matrix.m13)*s);
this[2] = ((mat.$matrix.m32 + mat.$matrix.m23)*s);
}
}
this.normalize();
}
normalize() {
var len = Math.sqrt(this.dot(this));
if (len !== 0.0) {
this.mulScalar(1.0/len);
} else {
this[1] = 1.0;
this[0] = this[2] = this[3] = 0.0;
}
return this;
}
axisAngleToQuat(axis, angle) {
let nor = _quat_vs3_temps.next().load(axis);
nor.normalize();
if (nor.dot(nor) !== 0.0) {
var phi = angle/2.0;
var si = Math.sin(phi);
this[0] = Math.cos(phi);
this[1] = nor[0]*si;
this[2] = nor[1]*si;
this[3] = nor[2]*si;
} else {
this.makeUnitQuat();
}
return this;
}
rotationBetweenVecs(v1, v2, fac = 1.0) {
v1 = new Vector3(v1);
v2 = new Vector3(v2);
v1.normalize();
v2.normalize();
if (Math.abs(v1.dot(v2)) > 0.9999) {
this.makeUnitQuat();
return this;
}
let axis = new Vector3(v1);
axis.cross(v2);
let angle = v1.preNormalizedAngle(v2)*fac;
this.axisAngleToQuat(axis, angle);
return this;
}
quatInterp(quat2, t) {
let quat = new Quat();
let cosom = this[0]*quat2[0] + this[1]*quat2[1] + this[2]*quat2[2] + this[3]*quat2[3];
if (cosom < 0.0) {
cosom = -cosom;
quat[0] = -this[0];
quat[1] = -this[1];
quat[2] = -this[2];
quat[3] = -this[3];
} else {
quat[0] = this[0];
quat[1] = this[1];
quat[2] = this[2];
quat[3] = this[3];
}
let omega, sinom, sc1, sc2;
if ((1.0 - cosom) > 0.0001) {
omega = Math.acos(cosom);
sinom = Math.sin(omega);
sc1 = Math.sin((1.0 - t)*omega)/sinom;
sc2 = Math.sin(t*omega)/sinom;
} else {
sc1 = 1.0 - t;
sc2 = t;
}
this[0] = sc1*quat[0] + sc2*quat2[0];
this[1] = sc1*quat[1] + sc2*quat2[1];
this[2] = sc1*quat[2] + sc2*quat2[2];
this[3] = sc1*quat[3] + sc2*quat2[3];
return this;
}
};
Quat.STRUCT = nstructjs.inherit(Quat, Vector4, 'quat') + `
}
`;
nstructjs.register(Quat);
_v3nd4_n1_normalizedDot4 = new Vector3();
_v3nd4_n2_normalizedDot4 = new Vector3();
_v3nd_n1_normalizedDot = new Vector3();
_v3nd_n2_normalizedDot = new Vector3();
BaseVector.inherit(Vector4, 4);
F64BaseVector.inherit(Vector3, 3);
BaseVector.inherit(Vector2, 2);
lookat_cache_vs3 = util.cachering.fromConstructor(Vector3, 64);
lookat_cache_vs4 = util.cachering.fromConstructor(Vector4, 64);
makenormalcache = util.cachering.fromConstructor(Vector3, 64);
var $_v3nd_n1_normalizedDot = new Vector3();
var $_v3nd_n2_normalizedDot = new Vector3();
var $_v3nd4_n1_normalizedDot4 = new Vector3();
var $_v3nd4_n2_normalizedDot4 = new Vector3();
var $_v3nd4_n1_normalizedDot3 = new Vector3();
var $_v3nd4_n2_normalizedDot3 = new Vector3();
var M_SQRT2 = Math.sqrt(2.0);
var FLT_EPSILON = 2.22e-16;
class internal_matrix {
constructor() {
this.m11 = 1.0;
this.m12 = 0.0;
this.m13 = 0.0;
this.m14 = 0.0;
this.m21 = 0.0;
this.m22 = 1.0;
this.m23 = 0.0;
this.m24 = 0.0;
this.m31 = 0.0;
this.m32 = 0.0;
this.m33 = 1.0;
this.m34 = 0.0;
this.m41 = 0.0;
this.m42 = 0.0;
this.m43 = 0.0;
this.m44 = 1.0;
}
}
var lookat_cache_vs3;
var lookat_cache_vs4;
var lookat_cache_ms;
var euler_rotate_mats;
var makenormalcache;
var temp_mats;
let preMultTemp;
export class Matrix4 {
constructor(m) {
this.$matrix = new internal_matrix();
this.isPersp = false;
if (typeof m === 'object') {
if ("length" in m && m.length >= 16) {
this.load(m);
} else if (m instanceof Matrix4) {
this.load(m);
}
}
}
static fromJSON() {
var mat = new Matrix4();
mat.load(json.items);
mat.isPersp = json.isPersp;
return mat;
}
copy() {
return this.clone();
}
clone() {
return new Matrix4(this);
}
addToHashDigest(hash) {
let m = this.$matrix;
hash.add(m.m11);
hash.add(m.m12);
hash.add(m.m13);
hash.add(m.m14);
hash.add(m.m21);
hash.add(m.m22);
hash.add(m.m23);
hash.add(m.m24);
hash.add(m.m31);
hash.add(m.m32);
hash.add(m.m33);
hash.add(m.m34);
hash.add(m.m41);
hash.add(m.m42);
hash.add(m.m43);
hash.add(m.m44);
return this;
}
equals(m) {
let m1 = this.$matrix;
let m2 = m.$matrix;
let ok = 1;
ok = ok && m1.m11 === m2.m11;
ok = ok && m1.m12 === m2.m12;
ok = ok && m1.m13 === m2.m13;
ok = ok && m1.m14 === m2.m14;
ok = ok && m1.m21 === m2.m21;
ok = ok && m1.m22 === m2.m22;
ok = ok && m1.m23 === m2.m23;
ok = ok && m1.m24 === m2.m24;
ok = ok && m1.m31 === m2.m31;
ok = ok && m1.m32 === m2.m32;
ok = ok && m1.m33 === m2.m33;
ok = ok && m1.m34 === m2.m34;
ok = ok && m1.m41 === m2.m41;
ok = ok && m1.m42 === m2.m42;
ok = ok && m1.m43 === m2.m43;
ok = ok && m1.m44 === m2.m44;
return ok;
}
loadColumn(i, vec) {
let m = this.$matrix;
let have4 = vec.length > 3;
switch (i) {
case 0:
m.m11 = vec[0];
m.m21 = vec[1];
m.m31 = vec[2];
if (have4) {
m.m41 = vec[3];
}
break;
case 1:
m.m12 = vec[0];
m.m22 = vec[1];
m.m32 = vec[2];
if (have4) {
m.m42 = vec[3];
}
break;
case 2:
m.m13 = vec[0];
m.m23 = vec[1];
m.m33 = vec[2];
if (have4) {
m.m43 = vec[3];
}
break;
case 3:
m.m14 = vec[0];
m.m24 = vec[1];
m.m34 = vec[2];
if (have4) {
m.m44 = vec[3];
}
break;
}
return this;
}
copyColumnTo(i, vec) {
let m = this.$matrix;
let have4 = vec.length > 3;
switch (i) {
case 0:
vec[0] = m.m11;
vec[1] = m.m21;
vec[2] = m.m31;
if (have4) {
vec[3] = m.m41;
}
break;
case 1:
vec[0] = m.m12;
vec[1] = m.m22;
vec[2] = m.m32;
if (have4) {
vec[3] = m.m42;
}
break;
case 2:
vec[0] = m.m13;
vec[1] = m.m23;
vec[2] = m.m33;
if (have4) {
vec[3] = m.m43;
}
break;
case 3:
vec[0] = m.m14;
vec[1] = m.m24;
vec[2] = m.m34;
if (have4) {
vec[3] = m.m44;
}
break;
}
return vec;
}
copyColumn(i) {
return this.copyColumnTo(i, new Vector3());
}
load() {
if (arguments.length === 1 && typeof arguments[0] === 'object') {
var matrix;
if (arguments[0] instanceof Matrix4) {
matrix = arguments[0].$matrix;
this.isPersp = arguments[0].isPersp;
this.$matrix.m11 = matrix.m11;
this.$matrix.m12 = matrix.m12;
this.$matrix.m13 = matrix.m13;
this.$matrix.m14 = matrix.m14;
this.$matrix.m21 = matrix.m21;
this.$matrix.m22 = matrix.m22;
this.$matrix.m23 = matrix.m23;
this.$matrix.m24 = matrix.m24;
this.$matrix.m31 = matrix.m31;
this.$matrix.m32 = matrix.m32;
this.$matrix.m33 = matrix.m33;
this.$matrix.m34 = matrix.m34;
this.$matrix.m41 = matrix.m41;
this.$matrix.m42 = matrix.m42;
this.$matrix.m43 = matrix.m43;
this.$matrix.m44 = matrix.m44;
return this;
} else
matrix = arguments[0];
if ("length" in matrix && matrix.length >= 16) {
this.$matrix.m11 = matrix[0];
this.$matrix.m12 = matrix[1];
this.$matrix.m13 = matrix[2];
this.$matrix.m14 = matrix[3];
this.$matrix.m21 = matrix[4];
this.$matrix.m22 = matrix[5];
this.$matrix.m23 = matrix[6];
this.$matrix.m24 = matrix[7];
this.$matrix.m31 = matrix[8];
this.$matrix.m32 = matrix[9];
this.$matrix.m33 = matrix[10];
this.$matrix.m34 = matrix[11];
this.$matrix.m41 = matrix[12];
this.$matrix.m42 = matrix[13];
this.$matrix.m43 = matrix[14];
this.$matrix.m44 = matrix[15];
return this;
}
}
this.makeIdentity();
return this;
}
toJSON() {
return {isPersp: this.isPersp, items: this.getAsArray()}
}
getAsArray() {
return [this.$matrix.m11, this.$matrix.m12, this.$matrix.m13, this.$matrix.m14, this.$matrix.m21, this.$matrix.m22,
this.$matrix.m23, this.$matrix.m24, this.$matrix.m31, this.$matrix.m32, this.$matrix.m33, this.$matrix.m34,
this.$matrix.m41, this.$matrix.m42, this.$matrix.m43, this.$matrix.m44];
}
getAsFloat32Array() {
return new Float32Array(this.getAsArray());
}
setUniform(ctx, loc, transpose) {
if (Matrix4.setUniformArray === undefined) {
Matrix4.setUniformWebGLArray = new Float32Array(16);
Matrix4.setUniformArray = new Array(16);
}
Matrix4.setUniformArray[0] = this.$matrix.m11;
Matrix4.setUniformArray[1] = this.$matrix.m12;
Matrix4.setUniformArray[2] = this.$matrix.m13;
Matrix4.setUniformArray[3] = this.$matrix.m14;
Matrix4.setUniformArray[4] = this.$matrix.m21;
Matrix4.setUniformArray[5] = this.$matrix.m22;
Matrix4.setUniformArray[6] = this.$matrix.m23;
Matrix4.setUniformArray[7] = this.$matrix.m24;
Matrix4.setUniformArray[8] = this.$matrix.m31;
Matrix4.setUniformArray[9] = this.$matrix.m32;
Matrix4.setUniformArray[10] = this.$matrix.m33;
Matrix4.setUniformArray[11] = this.$matrix.m34;
Matrix4.setUniformArray[12] = this.$matrix.m41;
Matrix4.setUniformArray[13] = this.$matrix.m42;
Matrix4.setUniformArray[14] = this.$matrix.m43;
Matrix4.setUniformArray[15] = this.$matrix.m44;
Matrix4.setUniformWebGLArray.set(Matrix4.setUniformArray);
ctx.uniformMatrix4fv(loc, transpose, Matrix4.setUniformWebGLArray);
return this;
}
makeIdentity() {
this.$matrix.m11 = 1;
this.$matrix.m12 = 0;
this.$matrix.m13 = 0;
this.$matrix.m14 = 0;
this.$matrix.m21 = 0;
this.$matrix.m22 = 1;
this.$matrix.m23 = 0;
this.$matrix.m24 = 0;
this.$matrix.m31 = 0;
this.$matrix.m32 = 0;
this.$matrix.m33 = 1;
this.$matrix.m34 = 0;
this.$matrix.m41 = 0;
this.$matrix.m42 = 0;
this.$matrix.m43 = 0;
this.$matrix.m44 = 1;
//drop isPersp
this.isPersp = false;
return this;
}
transpose() {
var tmp = this.$matrix.m12;
this.$matrix.m12 = this.$matrix.m21;
this.$matrix.m21 = tmp;
tmp = this.$matrix.m13;
this.$matrix.m13 = this.$matrix.m31;
this.$matrix.m31 = tmp;
tmp = this.$matrix.m14;
this.$matrix.m14 = this.$matrix.m41;
this.$matrix.m41 = tmp;
tmp = this.$matrix.m23;
this.$matrix.m23 = this.$matrix.m32;
this.$matrix.m32 = tmp;
tmp = this.$matrix.m24;
this.$matrix.m24 = this.$matrix.m42;
this.$matrix.m42 = tmp;
tmp = this.$matrix.m34;
this.$matrix.m34 = this.$matrix.m43;
this.$matrix.m43 = tmp;
return this;
}
determinant() {
return this._determinant4x4();
}
invert() {
var det = this._determinant4x4();
if (Math.abs(det) < 1e-08)
return null;
this._makeAdjoint();
this.$matrix.m11 /= det;
this.$matrix.m12 /= det;
this.$matrix.m13 /= det;
this.$matrix.m14 /= det;
this.$matrix.m21 /= det;
this.$matrix.m22 /= det;
this.$matrix.m23 /= det;
this.$matrix.m24 /= det;
this.$matrix.m31 /= det;
this.$matrix.m32 /= det;
this.$matrix.m33 /= det;
this.$matrix.m34 /= det;
this.$matrix.m41 /= det;
this.$matrix.m42 /= det;
this.$matrix.m43 /= det;
this.$matrix.m44 /= det;
return this;
}
translate(x, y, z) {
if (typeof x === 'object' && "length" in x) {
var t = x;
x = t[0];
y = t[1];
z = t[2];
}
x = x === undefined ? 0 : x;
y = y === undefined ? 0 : y;
z = z === undefined ? 0 : z;
var matrix = temp_mats.next().makeIdentity();
matrix.$matrix.m41 = x;
matrix.$matrix.m42 = y;
matrix.$matrix.m43 = z;
this.multiply(matrix);
return this;
}
preTranslate(x, y, z) {
if (typeof x === 'object' && "length" in x) {
var t = x;
x = t[0];
y = t[1];
z = t[2];
}
x = x === undefined ? 0 : x;
y = y === undefined ? 0 : y;
z = z === undefined ? 0 : z;
var matrix = temp_mats.next().makeIdentity();
matrix.$matrix.m41 = x;
matrix.$matrix.m42 = y;
matrix.$matrix.m43 = z;
this.preMultiply(matrix);
return this;
}
scale(x, y, z, w = 1.0) {
if (typeof x === 'object' && "length" in x) {
var t = x;
x = t[0];
y = t[1];
z = t[2];
} else {
if (x === undefined)
x = 1;
if (z === undefined) {
if (y === undefined) {
y = x;
z = x;
} else {
z = x;
}
} else if (y === undefined) {
y = x;
}
}
var matrix = temp_mats.next().makeIdentity();
matrix.$matrix.m11 = x;
matrix.$matrix.m22 = y;
matrix.$matrix.m33 = z;
matrix.$matrix.m44 = w;
this.multiply(matrix);
return this
}
preScale(x, y, z, w = 1.0) {
let mat = temp_mats.next().makeIdentity();
mat.scale(x, y, z, w);
this.preMultiply(mat);
return this
}
/*
on factor;
off period;
c1 := cx; comment: cos(thx);
s1 := sx; comment: sin(thx);
c2 := cy; comment: cos(thy);
s2 := sy; comment: sin(thy);
c3 := cz; comment: cos(thz);
s3 := sz; comment: sin(thz);
cx := cos(thx);
sx := sin(thx);
cy := cos(thy);
sy := sin(thy);
cz := cos(thz);
sz := sin(thz);
imat := mat((1, 0, 0, 0),
(0, 1, 0, 0),
(0, 0, 1, 0),
(0, 0, 0, 1));
xmat :=mat((1, 0, 0, 0),
(0, c1, -s1, 0),
(0, s1, c1, 0),
(0, 0, 0, 0));
ymat :=mat((c2, 0, s2, 0),
(0, 1, 0, 0),
(-s2, 0, c2, 0),
(0, 0, 0, 0));
zmat :=mat(( c3, -s3, 0, 0),
(s3, c3, 0, 0),
( 0, 0, 1, 0),
( 0, 0, 0, 0));
mmat := mat((m11, m21, m31, 0),
(m12, m22, m32, 0),
(m13, m23, m33, 0),
(0, 0, 0, 0));
fmat := zmat * ymat * xmat;
f1 := m11**2 + m12**2 + m13**2 - 1.0;
f2 := m21**2 + m22**2 + m23**2 - 1.0;
f3 := m31**2 + m32**2 + m33**2 - 1.0;
tmat := fmat * mmat;
f1 := tmat(1, 1) - 1.0;
f2 := tmat(2, 2) - 1.0;
f3 := tmat(3, 3) - 1.0;
operator myasin;
fthy := asin(mmat(3, 1));
f1 := mmat(3,1)**2 + mmat(2,1)**2 + mmat(1,1)**2 = 1.0;
fmat2 := sub(thy=fthy, fmat);
fmat3 := fmat2 * (tp mmat);
ffz := solve(fmat2(1, 1) - m11, thz);
ffx := solve(fmat2(3, 3) - m33, thx);
fthz := part(ffz, 1, 2);
fthx := part(ffx, 1, 2);
sub(thx=fthx, thy=fthy, thz=fthz, fmat);
(cos(thy)*cos(thz), cos(thx)*sin(thz)-cos(thz)*sin(thx)*sin(thy), -(cos(thx)*cos(thz)*sin(thy)+sin(thx)*sin(thz)), 0),
(-cos(thy)*sin(thz), cos(thx)*cos(thz) + sin(thx)*sin(thy)*sin(thz), cos(thx)*sin(thy)*sin(thz)-cos(thz)*sin(thx), 0),
(sin(thy), cos(thy)*sin(thx), cos(thx)*cos(thy), 0),
(0,0,0,1))
*/
euler_rotate_order(x, y, z, order = EulerOrders.XYZ) {
if (y === undefined) {
y = 0.0;
}
if (z === undefined) {
z = 0.0;
}
x = -x;
y = -y;
z = -z;
let xmat = euler_rotate_mats.next().makeIdentity();
let m = xmat.$matrix;
let c = Math.cos(x), s = Math.sin(x);
m.m22 = c;
m.m23 = s;
m.m32 = -s;
m.m33 = c;
let ymat = euler_rotate_mats.next().makeIdentity();
c = Math.cos(y);
s = Math.sin(y);
m = ymat.$matrix;
m.m11 = c;
m.m13 = -s;
m.m31 = s;
m.m33 = c;
let zmat = euler_rotate_mats.next().makeIdentity();
c = Math.cos(z);
s = Math.sin(z);
m = zmat.$matrix;
m.m11 = c;
m.m12 = s;
m.m21 = -s;
m.m22 = c;
let a, b;
switch (order) {
case EulerOrders.XYZ:
a = xmat;
b = ymat;
c = zmat;
break;
case EulerOrders.XZY:
a = xmat;
b = zmat;
c = ymat;
break;
case EulerOrders.YXZ:
a = ymat;
b = xmat;
c = zmat;
break;
case EulerOrders.YZX:
a = ymat;
b = zmat;
c = xmat;
break;
case EulerOrders.ZXY:
a = zmat;
b = xmat;
c = ymat;
break;
case EulerOrders.ZYX:
a = zmat;
b = ymat;
c = xmat;
break;
}
b.preMultiply(c);
b.multiply(a);
this.preMultiply(b);
return this;
}
euler_rotate(x, y, z) {
if (y === undefined) {
y = 0.0;
}
if (z === undefined) {
z = 0.0;
}
window.Matrix4 = Matrix4;
var xmat = euler_rotate_mats.next().makeIdentity();
var m = xmat.$matrix;
var c = Math.cos(x), s = Math.sin(x);
m.m22 = c;
m.m23 = s;
m.m32 = -s;
m.m33 = c;
var ymat = euler_rotate_mats.next().makeIdentity();
c = Math.cos(y);
s = Math.sin(y);
var m = ymat.$matrix;
m.m11 = c;
m.m13 = -s;
m.m31 = s;
m.m33 = c;
ymat.multiply(xmat);
var zmat = euler_rotate_mats.next().makeIdentity();
c = Math.cos(z);
s = Math.sin(z);
var m = zmat.$matrix;
m.m11 = c;
m.m12 = s;
m.m21 = -s;
m.m22 = c;
zmat.multiply(ymat);
//console.log(""+ymat);
//this.multiply(zmat);
this.preMultiply(zmat);
return this;
}
toString() {
var s = ""
var m = this.$matrix;
function dec(d) {
var ret = d.toFixed(3);
if (ret[0] !== "-") //make room for negative signs
ret = " " + ret
return ret
}
s = dec(m.m11) + ", " + dec(m.m12) + ", " + dec(m.m13) + ", " + dec(m.m14) + "\n";
s += dec(m.m21) + ", " + dec(m.m22) + ", " + dec(m.m23) + ", " + dec(m.m24) + "\n";
s += dec(m.m31) + ", " + dec(m.m32) + ", " + dec(m.m33) + ", " + dec(m.m34) + "\n";
s += dec(m.m41) + ", " + dec(m.m42) + ", " + dec(m.m43) + ", " + dec(m.m44) + "\n";
return s
}
rotate(angle, x, y, z) {
if (typeof x === 'object' && "length" in x) {
var t = x;
x = t[0];
y = t[1];
z = t[2];
} else {
if (arguments.length === 1) {
x = y = 0;
z = 1;
} else if (arguments.length === 3) {
this.rotate(angle, 1, 0, 0);
this.rotate(x, 0, 1, 0);
this.rotate(y, 0, 0, 1);
return;
}
}
angle /= 2;
var sinA = Math.sin(angle);
var cosA = Math.cos(angle);
var sinA2 = sinA*sinA;
var len = Math.sqrt(x*x + y*y + z*z);
if (len === 0) {
x = 0;
y = 0;
z = 1;
} else if (len !== 1) {
x /= len;
y /= len;
z /= len;
}
var mat = temp_mats.next().makeIdentity();
if (x === 1 && y === 0 && z === 0) {
mat.$matrix.m11 = 1;
mat.$matrix.m12 = 0;
mat.$matrix.m13 = 0;
mat.$matrix.m21 = 0;
mat.$matrix.m22 = 1 - 2*sinA2;
mat.$matrix.m23 = 2*sinA*cosA;
mat.$matrix.m31 = 0;
mat.$matrix.m32 = -2*sinA*cosA;
mat.$matrix.m33 = 1 - 2*sinA2;
mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
mat.$matrix.m44 = 1;
} else if (x === 0 && y === 1 && z === 0) {
mat.$matrix.m11 = 1 - 2*sinA2;
mat.$matrix.m12 = 0;
mat.$matrix.m13 = -2*sinA*cosA;
mat.$matrix.m21 = 0;
mat.$matrix.m22 = 1;
mat.$matrix.m23 = 0;
mat.$matrix.m31 = 2*sinA*cosA;
mat.$matrix.m32 = 0;
mat.$matrix.m33 = 1 - 2*sinA2;
mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
mat.$matrix.m44 = 1;
} else if (x === 0 && y === 0 && z === 1) {
mat.$matrix.m11 = 1 - 2*sinA2;
mat.$matrix.m12 = 2*sinA*cosA;
mat.$matrix.m13 = 0;
mat.$matrix.m21 = -2*sinA*cosA;
mat.$matrix.m22 = 1 - 2*sinA2;
mat.$matrix.m23 = 0;
mat.$matrix.m31 = 0;
mat.$matrix.m32 = 0;
mat.$matrix.m33 = 1;
mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
mat.$matrix.m44 = 1;
} else {
var x2 = x*x;
var y2 = y*y;
var z2 = z*z;
mat.$matrix.m11 = 1 - 2*(y2 + z2)*sinA2;
mat.$matrix.m12 = 2*(x*y*sinA2 + z*sinA*cosA);
mat.$matrix.m13 = 2*(x*z*sinA2 - y*sinA*cosA);
mat.$matrix.m21 = 2*(y*x*sinA2 - z*sinA*cosA);
mat.$matrix.m22 = 1 - 2*(z2 + x2)*sinA2;
mat.$matrix.m23 = 2*(y*z*sinA2 + x*sinA*cosA);
mat.$matrix.m31 = 2*(z*x*sinA2 + y*sinA*cosA);
mat.$matrix.m32 = 2*(z*y*sinA2 - x*sinA*cosA);
mat.$matrix.m33 = 1 - 2*(x2 + y2)*sinA2;
mat.$matrix.m14 = mat.$matrix.m24 = mat.$matrix.m34 = 0;
mat.$matrix.m41 = mat.$matrix.m42 = mat.$matrix.m43 = 0;
mat.$matrix.m44 = 1;
}
this.multiply(mat);
return this;
}
normalize() {
let m = this.$matrix;
let v1 = new Vector4([m.m11, m.m12, m.m13, m.m14]);
let v2 = new Vector4([m.m21, m.m22, m.m23, m.m24]);
let v3 = new Vector4([m.m31, m.m32, m.m33, m.m34]);
let v4 = new Vector4([m.m41, m.m42, m.m43, m.m44]);
v1.normalize();
v2.normalize();
v3.normalize();
let flat = new Array().concat(v1).concat(v2).concat(v3).concat(v4);
this.load(flat);
return this;
}
clearTranslation(set_w_to_one = false) {
let m = this.$matrix;
m.m41 = m.m42 = m.m43 = 0.0;
if (set_w_to_one) {
m.m44 = 1.0;
}
return this;
}
setTranslation(x, y, z, resetW = true) {
if (typeof x === "object") {
y = x[1];
z = x[2];
x = x[0];
}
let m = this.$matrix;
m.m41 = x;
m.m42 = y;
m.m43 = z;
if (resetW) {
m.m44 = 1.0;
}
return this;
}
//this is really like the lookAt method, isn't it.
makeNormalMatrix(normal, up = undefined) {
if (normal === undefined) {
throw new Error("normal cannot be undefined");
}
let n = makenormalcache.next().load(normal).normalize();
if (up === undefined) {
up = makenormalcache.next().zero();
if (Math.abs(n[2]) > 0.95) {
up[1] = 1.0;
} else {
up[2] = 1.0;
}
}
up = makenormalcache.next().load(up);
up.normalize();
if (up.dot(normal) > 0.99) {
this.makeIdentity();
return this;
} else if (up.dot(normal) < -0.99) {
this.makeIdentity();
this.scale(1.0, 1.0, -1.0);
return this;
}
let x = makenormalcache.next();
let y = makenormalcache.next();
x.load(n).cross(up).normalize();
y.load(x).cross(n).normalize();
//y.negate();
this.makeIdentity();
let m = this.$matrix;
m.m11 = x[0];
m.m12 = x[1];
m.m13 = x[2];
m.m21 = y[0];
m.m22 = y[1];
m.m23 = y[2];
m.m31 = n[0];
m.m32 = n[1];
m.m33 = n[2];
m.m44 = 1.0;
return this;
}
preMultiply(mat) {
preMultTemp.load(mat);
preMultTemp.multiply(this);
this.load(preMultTemp);
return this;
}
multiply(mat) {
let mm = this.$matrix;
let mm2 = mat.$matrix;
let m11 = (mm2.m11*mm.m11 + mm2.m12*mm.m21 + mm2.m13*mm.m31 + mm2.m14*mm.m41);
let m12 = (mm2.m11*mm.m12 + mm2.m12*mm.m22 + mm2.m13*mm.m32 + mm2.m14*mm.m42);
let m13 = (mm2.m11*mm.m13 + mm2.m12*mm.m23 + mm2.m13*mm.m33 + mm2.m14*mm.m43);
let m14 = (mm2.m11*mm.m14 + mm2.m12*mm.m24 + mm2.m13*mm.m34 + mm2.m14*mm.m44);
let m21 = (mm2.m21*mm.m11 + mm2.m22*mm.m21 + mm2.m23*mm.m31 + mm2.m24*mm.m41);
let m22 = (mm2.m21*mm.m12 + mm2.m22*mm.m22 + mm2.m23*mm.m32 + mm2.m24*mm.m42);
let m23 = (mm2.m21*mm.m13 + mm2.m22*mm.m23 + mm2.m23*mm.m33 + mm2.m24*mm.m43);
let m24 = (mm2.m21*mm.m14 + mm2.m22*mm.m24 + mm2.m23*mm.m34 + mm2.m24*mm.m44);
let m31 = (mm2.m31*mm.m11 + mm2.m32*mm.m21 + mm2.m33*mm.m31 + mm2.m34*mm.m41);
let m32 = (mm2.m31*mm.m12 + mm2.m32*mm.m22 + mm2.m33*mm.m32 + mm2.m34*mm.m42);
let m33 = (mm2.m31*mm.m13 + mm2.m32*mm.m23 + mm2.m33*mm.m33 + mm2.m34*mm.m43);
let m34 = (mm2.m31*mm.m14 + mm2.m32*mm.m24 + mm2.m33*mm.m34 + mm2.m34*mm.m44);
let m41 = (mm2.m41*mm.m11 + mm2.m42*mm.m21 + mm2.m43*mm.m31 + mm2.m44*mm.m41);
let m42 = (mm2.m41*mm.m12 + mm2.m42*mm.m22 + mm2.m43*mm.m32 + mm2.m44*mm.m42);
let m43 = (mm2.m41*mm.m13 + mm2.m42*mm.m23 + mm2.m43*mm.m33 + mm2.m44*mm.m43);
let m44 = (mm2.m41*mm.m14 + mm2.m42*mm.m24 + mm2.m43*mm.m34 + mm2.m44*mm.m44);
mm.m11 = m11;
mm.m12 = m12;
mm.m13 = m13;
mm.m14 = m14;
mm.m21 = m21;
mm.m22 = m22;
mm.m23 = m23;
mm.m24 = m24;
mm.m31 = m31;
mm.m32 = m32;
mm.m33 = m33;
mm.m34 = m34;
mm.m41 = m41;
mm.m42 = m42;
mm.m43 = m43;
mm.m44 = m44;
return this;
}
divide(divisor) {
this.$matrix.m11 /= divisor;
this.$matrix.m12 /= divisor;
this.$matrix.m13 /= divisor;
this.$matrix.m14 /= divisor;
this.$matrix.m21 /= divisor;
this.$matrix.m22 /= divisor;
this.$matrix.m23 /= divisor;
this.$matrix.m24 /= divisor;
this.$matrix.m31 /= divisor;
this.$matrix.m32 /= divisor;
this.$matrix.m33 /= divisor;
this.$matrix.m34 /= divisor;
this.$matrix.m41 /= divisor;
this.$matrix.m42 /= divisor;
this.$matrix.m43 /= divisor;
this.$matrix.m44 /= divisor;
return this;
}
ortho(left, right, bottom, top, near, far) {
console.warn("Matrix4.ortho() is deprecated, use .orthographic() instead");
var tx = (left + right)/(left - right);
var ty = (top + bottom)/(top - bottom);
var tz = (far + near)/(far - near);
var matrix = temp_mats.next().makeIdentity();
matrix.$matrix.m11 = 2/(left - right);
matrix.$matrix.m12 = 0;
matrix.$matrix.m13 = 0;
matrix.$matrix.m14 = 0;
matrix.$matrix.m21 = 0;
matrix.$matrix.m22 = 2/(top - bottom);
matrix.$matrix.m23 = 0;
matrix.$matrix.m24 = 0;
matrix.$matrix.m31 = 0;
matrix.$matrix.m32 = 0;
matrix.$matrix.m33 = -2/(far - near);
matrix.$matrix.m34 = 0;
matrix.$matrix.m41 = tx;
matrix.$matrix.m42 = ty;
matrix.$matrix.m43 = tz;
matrix.$matrix.m44 = 1;
this.multiply(matrix);
return this;
}
frustum(left, right, bottom, top, near, far) {
var matrix = temp_mats.next().makeIdentity();
var A = (right + left)/(right - left);
var B = (top + bottom)/(top - bottom);
var C = -(far + near)/(far - near);
var D = -(2*far*near)/(far - near);
matrix.$matrix.m11 = (2*near)/(right - left);
matrix.$matrix.m12 = 0;
matrix.$matrix.m13 = 0;
matrix.$matrix.m14 = 0;
matrix.$matrix.m21 = 0;
matrix.$matrix.m22 = 2*near/(top - bottom);
matrix.$matrix.m23 = 0;
matrix.$matrix.m24 = 0;
matrix.$matrix.m31 = A;
matrix.$matrix.m32 = B;
matrix.$matrix.m33 = C;
matrix.$matrix.m34 = -1;
matrix.$matrix.m41 = 0;
matrix.$matrix.m42 = 0;
matrix.$matrix.m43 = D;
matrix.$matrix.m44 = 0;
this.isPersp = true;
this.multiply(matrix);
return this;
}
orthographic(scale, aspect, near, far) {
let mat = temp_mats.next().makeIdentity();
let zscale = far - near;
mat.scale(2.0/aspect, 2.0, -1.0/scale/zscale, 1.0/scale);
mat.translate(0.0, 0.0, 0.5*zscale - near);
this.isPersp = true; //we still make use of auto homogenous divide in BaseVector.multVecMatrix
this.multiply(mat);
return mat;
}
perspective(fovy, aspect, zNear, zFar) {
var top = Math.tan(fovy*Math.PI/360)*zNear;
var bottom = -top;
var left = aspect*bottom;
var right = aspect*top;
this.frustum(left, right, bottom, top, zNear, zFar);
return this;
}
lookat(pos, target, up) {
var matrix = lookat_cache_ms.next();
matrix.makeIdentity();
var vec = lookat_cache_vs3.next().load(pos).sub(target);
var len = vec.vectorLength();
vec.normalize();
var zvec = vec;
var yvec = lookat_cache_vs3.next().load(up).normalize();
var xvec = lookat_cache_vs3.next().load(yvec).cross(zvec).normalize();
let mm = matrix.$matrix;
mm.m11 = xvec[0];
mm.m12 = yvec[0];
mm.m13 = zvec[0];
mm.m14 = 0;
mm.m21 = xvec[1];
mm.m22 = yvec[1];
mm.m23 = zvec[1];
mm.m24 = 0;
mm.m31 = xvec[2];
mm.m32 = yvec[2];
mm.m33 = zvec[2];
//*
mm.m11 = xvec[0];
mm.m12 = xvec[1];
mm.m13 = xvec[2];
mm.m14 = 0;
mm.m21 = yvec[0];
mm.m22 = yvec[1];
mm.m23 = yvec[2];
mm.m24 = 0;
mm.m31 = zvec[0];
mm.m32 = zvec[1];
mm.m33 = zvec[2];
mm.m34 = 0;
mm.m41 = pos[0];
mm.m42 = pos[1];
mm.m43 = pos[2];
mm.m44 = 1;
//*/
this.multiply(matrix);
return this;
}
makeRotationOnly() {
var m = this.$matrix;
m.m41 = m.m42 = m.m43 = 0.0;
m.m44 = 1.0;
let l1 = Math.sqrt(m.m11*m.m11 + m.m12*m.m12 + m.m13*m.m13);
let l2 = Math.sqrt(m.m21*m.m21 + m.m22*m.m22 + m.m23*m.m23);
let l3 = Math.sqrt(m.m31*m.m31 + m.m32*m.m32 + m.m33*m.m33);
if (l1) {
m.m11 /= l1;
m.m12 /= l1;
m.m13 /= l1;
}
if (l2) {
m.m21 /= l2;
m.m22 /= l2;
m.m23 /= l2;
}
if (l3) {
m.m31 /= l3;
m.m32 /= l3;
m.m33 /= l3;
}
return this;
}
alignAxis(axis, vec) {
vec = new Vector3(vec);
vec.normalize();
let mat = this.inputs.transformMatrix.getValue();
let m = mat.$matrix;
let mat2 = new Matrix4(mat);
let loc = new Vector3(), scale = new Vector3(), rot = new Vector3();
//we don't use rot
mat2.decompose(loc, rot, scale);
mat2.makeRotationOnly();
let axes = mat2.getAsVecs();
let axis2 = (axis + 1) % 3;
let axis3 = (axis + 2) % 3;
axes[axis].load(vec)
axes[axis2].cross(axes[axis]).cross(axes[axis])
axes[axis3].load(axes[axis]).cross(axes[axis2])
axes[0][3] = 1.0;
axes[1][3] = 1.0;
axes[2][3] = 1.0;
axes[0].normalize();
axes[1].normalize();
axes[2].normalize();
this.loadFromVecs(axes);
this.scale(scale[0], scale[1], scale[2]);
m.m41 = loc[0];
m.m42 = loc[1];
m.m43 = loc[2];
return this;
}
decompose(_translate, _rotate, _scale, _skew, _perspective, order = EulerOrders.XYZ) {
if (this.$matrix.m44 === 0)
return false;
let mat = temp_mats.next().load(this);
let m = mat.$matrix;
let t = _translate, r = _rotate, s = _scale;
if (t) {
t[0] = m.m41;
t[1] = m.m42;
t[2] = m.m43;
}
let l1 = Math.sqrt(m.m11*m.m11 + m.m12*m.m12 + m.m13*m.m13);
let l2 = Math.sqrt(m.m21*m.m21 + m.m22*m.m22 + m.m23*m.m23);
let l3 = Math.sqrt(m.m31*m.m31 + m.m32*m.m32 + m.m33*m.m33);
if (l1) {
m.m11 /= l1;
m.m12 /= l1;
m.m13 /= l1;
}
if (l2) {
m.m21 /= l2;
m.m22 /= l2;
m.m23 /= l2;
}
if (l3) {
m.m31 /= l3;
m.m32 /= l3;
m.m33 /= l3;
}
if (s) {
s[0] = l1;
s[1] = l2;
s[2] = l3;
}
if (r) { //THREE.js code
let clamp = myclamp;
let rmat = temp_mats.next().load(this);
rmat.normalize();
m = rmat.$matrix;
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
let m11 = m.m11, m12 = m.m12, m13 = m.m13, m14 = m.m14;
let m21 = m.m21, m22 = m.m22, m23 = m.m23, m24 = m.m24;
let m31 = m.m31, m32 = m.m32, m33 = m.m33, m34 = m.m34;
//let m41 = m.m41, m42 = m.m42, m43 = m.m43, m44 = m.m44;
if (order === EulerOrders.XYZ) {
r[1] = Math.asin(clamp(m13, -1, 1));
if (Math.abs(m13) < 0.9999999) {
r[0] = Math.atan2(-m23, m33);
r[2] = Math.atan2(-m12, m11);
} else {
r[0] = Math.atan2(m32, m22);
r[2] = 0;
}
} else if (order === EulerOrders.YXZ) {
r[0] = Math.asin(-clamp(m23, -1, 1));
if (Math.abs(m23) < 0.9999999) {
r[1] = Math.atan2(m13, m33);
r[2] = Math.atan2(m21, m22);
} else {
r[1] = Math.atan2(-m31, m11);
r[2] = 0;
}
} else if (order === EulerOrders.ZXY) {
r[0] = Math.asin(clamp(m32, -1, 1));
if (Math.abs(m32) < 0.9999999) {
r[1] = Math.atan2(-m31, m33);
r[2] = Math.atan2(-m12, m22);
} else {
r[1] = 0;
r[2] = Math.atan2(m21, m11);
}
} else if (order === EulerOrders.ZYX) {
r[1] = Math.asin(-clamp(m31, -1, 1));
if (Math.abs(m31) < 0.9999999) {
r[0] = Math.atan2(m32, m33);
r[2] = Math.atan2(m21, m11);
} else {
r[0] = 0;
r[2] = Math.atan2(-m12, m22);
}
} else if (order === EulerOrders.YZX) {
r[2] = Math.asin(clamp(m21, -1, 1));
if (Math.abs(m21) < 0.9999999) {
r[0] = Math.atan2(-m23, m22);
r[1] = Math.atan2(-m31, m11);
} else {
r[0] = 0;
r[1] = Math.atan2(m13, m33);
}
} else if (order === EulerOrders.XZY) {
r[2] = Math.asin(-clamp(m12, -1, 1));
if (Math.abs(m12) < 0.9999999) {
r[0] = Math.atan2(m32, m22);
r[1] = Math.atan2(m13, m11);
} else {
r[0] = Math.atan2(-m23, m33);
r[1] = 0;
}
} else {
console.warn('unsupported euler order:', order);
}
//r[0] = Math.atan2(m.m23, m.m33);
//r[1] = Math.atan2(-m.m13, Math.sqrt(m.m23*m.m23 + m.m33*m.m33));
//r[2] = Math.atan2(m.m12, m.m11);
}
}
_determinant2x2(a, b, c, d) {
return a*d - b*c;
}
_determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3) {
return a1*this._determinant2x2(b2, b3, c2, c3) - b1*this._determinant2x2(a2, a3, c2, c3) + c1*this._determinant2x2(a2, a3, b2, b3);
}
determinant() {
return this._determinant4x4();
}
_determinant4x4() {
var a1 = this.$matrix.m11;
var b1 = this.$matrix.m12;
var c1 = this.$matrix.m13;
var d1 = this.$matrix.m14;
var a2 = this.$matrix.m21;
var b2 = this.$matrix.m22;
var c2 = this.$matrix.m23;
var d2 = this.$matrix.m24;
var a3 = this.$matrix.m31;
var b3 = this.$matrix.m32;
var c3 = this.$matrix.m33;
var d3 = this.$matrix.m34;
var a4 = this.$matrix.m41;
var b4 = this.$matrix.m42;
var c4 = this.$matrix.m43;
var d4 = this.$matrix.m44;
return a1*this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4) - b1*this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4) + c1*this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4) - d1*this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
}
_makeAdjoint() {
var a1 = this.$matrix.m11;
var b1 = this.$matrix.m12;
var c1 = this.$matrix.m13;
var d1 = this.$matrix.m14;
var a2 = this.$matrix.m21;
var b2 = this.$matrix.m22;
var c2 = this.$matrix.m23;
var d2 = this.$matrix.m24;
var a3 = this.$matrix.m31;
var b3 = this.$matrix.m32;
var c3 = this.$matrix.m33;
var d3 = this.$matrix.m34;
var a4 = this.$matrix.m41;
var b4 = this.$matrix.m42;
var c4 = this.$matrix.m43;
var d4 = this.$matrix.m44;
this.$matrix.m11 = this._determinant3x3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
this.$matrix.m21 = -this._determinant3x3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
this.$matrix.m31 = this._determinant3x3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
this.$matrix.m41 = -this._determinant3x3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
this.$matrix.m12 = -this._determinant3x3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
this.$matrix.m22 = this._determinant3x3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
this.$matrix.m32 = -this._determinant3x3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
this.$matrix.m42 = this._determinant3x3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
this.$matrix.m13 = this._determinant3x3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
this.$matrix.m23 = -this._determinant3x3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
this.$matrix.m33 = this._determinant3x3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
this.$matrix.m43 = -this._determinant3x3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
this.$matrix.m14 = -this._determinant3x3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
this.$matrix.m24 = this._determinant3x3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
this.$matrix.m34 = -this._determinant3x3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
this.$matrix.m44 = this._determinant3x3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
}
loadSTRUCT(reader) {
reader(this);
this.load(this.mat);
this.__mat = this.mat;
//delete this.mat;
}
}
Matrix4.STRUCT = `
mat4 {
mat : array(float) | this.getAsArray();
isPersp : int | this.isPersp;
}
`;
nstructjs.register(Matrix4);
preMultTemp = new Matrix4();
window.testmat = (x = 0, y = 0, z = Math.PI*0.5) => {
let m1 = new Matrix4();
m1.euler_rotate(x, y, z);
//m1.scale(2.0, 0.5, 3.0);
let t = [0, 0, 0], r = [0, 0, 0], s = [0, 0, 0]
m1.decompose(t, r, s);
window.console.log("\n");
window.console.log(t);
window.console.log(r);
window.console.log(s);
let mat = m1.clone();
mat.transpose();
mat.multiply(m1);
console.log(mat.toString());
return r;
}
lookat_cache_ms = util.cachering.fromConstructor(Matrix4, 64);
euler_rotate_mats = util.cachering.fromConstructor(Matrix4, 64);
temp_mats = util.cachering.fromConstructor(Matrix4, 64);