// Class: openfl.geom.Matrix3D

var $global = typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this

$global.Object.defineProperty(exports, "__esModule", {value: true});

var __map_reserved = {};

// Imports

var $hxClasses = require("./../../hxClasses_stub").default;
var $import = require("./../../import_stub").default;
function openfl_VectorData() {return require("./../../openfl/VectorData");}
function openfl__$Vector_Vector_$Impl_$() {return require("./../../openfl/_Vector/Vector_Impl_");}
function openfl_geom_Vector3D() {return require("./../../openfl/geom/Vector3D");}

// Constructor

var Matrix3D = function(v) {
	if(v != null && v.get_length() == 16) {
		this.rawData = v.concat(null);
	} else {
		this.rawData = (openfl_VectorData().default).ofArray([1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]);
	}
}

// Meta

Matrix3D.__name__ = ["openfl","geom","Matrix3D"];
Matrix3D.prototype = {
	append: function(lhs) {
		var m111 = this.rawData.get(0);
		var m121 = this.rawData.get(4);
		var m131 = this.rawData.get(8);
		var m141 = this.rawData.get(12);
		var m112 = this.rawData.get(1);
		var m122 = this.rawData.get(5);
		var m132 = this.rawData.get(9);
		var m142 = this.rawData.get(13);
		var m113 = this.rawData.get(2);
		var m123 = this.rawData.get(6);
		var m133 = this.rawData.get(10);
		var m143 = this.rawData.get(14);
		var m114 = this.rawData.get(3);
		var m124 = this.rawData.get(7);
		var m134 = this.rawData.get(11);
		var m144 = this.rawData.get(15);
		var m211 = lhs.rawData.get(0);
		var m221 = lhs.rawData.get(4);
		var m231 = lhs.rawData.get(8);
		var m241 = lhs.rawData.get(12);
		var m212 = lhs.rawData.get(1);
		var m222 = lhs.rawData.get(5);
		var m232 = lhs.rawData.get(9);
		var m242 = lhs.rawData.get(13);
		var m213 = lhs.rawData.get(2);
		var m223 = lhs.rawData.get(6);
		var m233 = lhs.rawData.get(10);
		var m243 = lhs.rawData.get(14);
		var m214 = lhs.rawData.get(3);
		var m224 = lhs.rawData.get(7);
		var m234 = lhs.rawData.get(11);
		var m244 = lhs.rawData.get(15);
		this.rawData.set(0,m111 * m211 + m112 * m221 + m113 * m231 + m114 * m241);
		this.rawData.set(1,m111 * m212 + m112 * m222 + m113 * m232 + m114 * m242);
		this.rawData.set(2,m111 * m213 + m112 * m223 + m113 * m233 + m114 * m243);
		this.rawData.set(3,m111 * m214 + m112 * m224 + m113 * m234 + m114 * m244);
		this.rawData.set(4,m121 * m211 + m122 * m221 + m123 * m231 + m124 * m241);
		this.rawData.set(5,m121 * m212 + m122 * m222 + m123 * m232 + m124 * m242);
		this.rawData.set(6,m121 * m213 + m122 * m223 + m123 * m233 + m124 * m243);
		this.rawData.set(7,m121 * m214 + m122 * m224 + m123 * m234 + m124 * m244);
		this.rawData.set(8,m131 * m211 + m132 * m221 + m133 * m231 + m134 * m241);
		this.rawData.set(9,m131 * m212 + m132 * m222 + m133 * m232 + m134 * m242);
		this.rawData.set(10,m131 * m213 + m132 * m223 + m133 * m233 + m134 * m243);
		this.rawData.set(11,m131 * m214 + m132 * m224 + m133 * m234 + m134 * m244);
		this.rawData.set(12,m141 * m211 + m142 * m221 + m143 * m231 + m144 * m241);
		this.rawData.set(13,m141 * m212 + m142 * m222 + m143 * m232 + m144 * m242);
		this.rawData.set(14,m141 * m213 + m142 * m223 + m143 * m233 + m144 * m243);
		this.rawData.set(15,m141 * m214 + m142 * m224 + m143 * m234 + m144 * m244);
	},
	appendRotation: function(degrees,axis,pivotPoint) {
		var tx;
		var ty;
		var tz = 0;
		ty = tz;
		tx = ty;
		if(pivotPoint != null) {
			tx = pivotPoint.x;
			ty = pivotPoint.y;
			tz = pivotPoint.z;
		}
		var radian = degrees * Math.PI / 180;
		var cos = Math.cos(radian);
		var sin = Math.sin(radian);
		var x = axis.x;
		var y = axis.y;
		var z = axis.z;
		var x2 = x * x;
		var y2 = y * y;
		var z2 = z * z;
		var ls = x2 + y2 + z2;
		if(ls != 0) {
			var l = Math.sqrt(ls);
			x /= l;
			y /= l;
			z /= l;
			x2 /= ls;
			y2 /= ls;
			z2 /= ls;
		}
		var ccos = 1 - cos;
		var m = new Matrix3D();
		var d = m.rawData;
		d.set(0,x2 + (y2 + z2) * cos);
		d.set(1,x * y * ccos + z * sin);
		d.set(2,x * z * ccos - y * sin);
		d.set(4,x * y * ccos - z * sin);
		d.set(5,y2 + (x2 + z2) * cos);
		d.set(6,y * z * ccos + x * sin);
		d.set(8,x * z * ccos + y * sin);
		d.set(9,y * z * ccos - x * sin);
		d.set(10,z2 + (x2 + y2) * cos);
		d.set(12,(tx * (y2 + z2) - x * (ty * y + tz * z)) * ccos + (ty * z - tz * y) * sin);
		d.set(13,(ty * (x2 + z2) - y * (tx * x + tz * z)) * ccos + (tz * x - tx * z) * sin);
		d.set(14,(tz * (x2 + y2) - z * (tx * x + ty * y)) * ccos + (tx * y - ty * x) * sin);
		this.append(m);
	},
	appendScale: function(xScale,yScale,zScale) {
		this.append(new Matrix3D((openfl_VectorData().default).ofArray([xScale,0.0,0.0,0.0,0.0,yScale,0.0,0.0,0.0,0.0,zScale,0.0,0.0,0.0,0.0,1.0])));
	},
	appendTranslation: function(x,y,z) {
		var _g = this.rawData;
		_g.set(12,_g.get(12) + x);
		var _g1 = this.rawData;
		_g1.set(13,_g1.get(13) + y);
		var _g2 = this.rawData;
		_g2.set(14,_g2.get(14) + z);
	},
	clone: function() {
		return new Matrix3D(this.rawData.copy());
	},
	copyColumnFrom: function(column,vector3D) {
		switch(column) {
		case 0:
			this.rawData.set(0,vector3D.x);
			this.rawData.set(1,vector3D.y);
			this.rawData.set(2,vector3D.z);
			this.rawData.set(3,vector3D.w);
			break;
		case 1:
			this.rawData.set(4,vector3D.x);
			this.rawData.set(5,vector3D.y);
			this.rawData.set(6,vector3D.z);
			this.rawData.set(7,vector3D.w);
			break;
		case 2:
			this.rawData.set(8,vector3D.x);
			this.rawData.set(9,vector3D.y);
			this.rawData.set(10,vector3D.z);
			this.rawData.set(11,vector3D.w);
			break;
		case 3:
			this.rawData.set(12,vector3D.x);
			this.rawData.set(13,vector3D.y);
			this.rawData.set(14,vector3D.z);
			this.rawData.set(15,vector3D.w);
			break;
		default:
		}
	},
	copyColumnTo: function(column,vector3D) {
		switch(column) {
		case 0:
			vector3D.x = this.rawData.get(0);
			vector3D.y = this.rawData.get(1);
			vector3D.z = this.rawData.get(2);
			vector3D.w = this.rawData.get(3);
			break;
		case 1:
			vector3D.x = this.rawData.get(4);
			vector3D.y = this.rawData.get(5);
			vector3D.z = this.rawData.get(6);
			vector3D.w = this.rawData.get(7);
			break;
		case 2:
			vector3D.x = this.rawData.get(8);
			vector3D.y = this.rawData.get(9);
			vector3D.z = this.rawData.get(10);
			vector3D.w = this.rawData.get(11);
			break;
		case 3:
			vector3D.x = this.rawData.get(12);
			vector3D.y = this.rawData.get(13);
			vector3D.z = this.rawData.get(14);
			vector3D.w = this.rawData.get(15);
			break;
		default:
		}
	},
	copyFrom: function(other) {
		this.rawData = other.rawData.copy();
	},
	copyRawDataFrom: function(vector,index,transpose) {
		if(transpose == null) {
			transpose = false;
		}
		if(index == null) {
			index = 0;
		}
		if(transpose) {
			this.transpose();
		}
		var length = vector.get_length() - index;
		var _g1 = 0;
		var _g = length;
		while(_g1 < _g) {
			var i = _g1++;
			this.rawData.set(i,vector.get(i + index));
		}
		if(transpose) {
			this.transpose();
		}
	},
	copyRawDataTo: function(vector,index,transpose) {
		if(transpose == null) {
			transpose = false;
		}
		if(index == null) {
			index = 0;
		}
		if(transpose) {
			this.transpose();
		}
		var _g1 = 0;
		var _g = this.rawData.get_length();
		while(_g1 < _g) {
			var i = _g1++;
			vector.set(i + index,this.rawData.get(i));
		}
		if(transpose) {
			this.transpose();
		}
	},
	copyRowFrom: function(row,vector3D) {
		switch(row) {
		case 0:
			this.rawData.set(0,vector3D.x);
			this.rawData.set(4,vector3D.y);
			this.rawData.set(8,vector3D.z);
			this.rawData.set(12,vector3D.w);
			break;
		case 1:
			this.rawData.set(1,vector3D.x);
			this.rawData.set(5,vector3D.y);
			this.rawData.set(9,vector3D.z);
			this.rawData.set(13,vector3D.w);
			break;
		case 2:
			this.rawData.set(2,vector3D.x);
			this.rawData.set(6,vector3D.y);
			this.rawData.set(10,vector3D.z);
			this.rawData.set(14,vector3D.w);
			break;
		case 3:
			this.rawData.set(3,vector3D.x);
			this.rawData.set(7,vector3D.y);
			this.rawData.set(11,vector3D.z);
			this.rawData.set(15,vector3D.w);
			break;
		default:
		}
	},
	copyRowTo: function(row,vector3D) {
		switch(row) {
		case 0:
			vector3D.x = this.rawData.get(0);
			vector3D.y = this.rawData.get(4);
			vector3D.z = this.rawData.get(8);
			vector3D.w = this.rawData.get(12);
			break;
		case 1:
			vector3D.x = this.rawData.get(1);
			vector3D.y = this.rawData.get(5);
			vector3D.z = this.rawData.get(9);
			vector3D.w = this.rawData.get(13);
			break;
		case 2:
			vector3D.x = this.rawData.get(2);
			vector3D.y = this.rawData.get(6);
			vector3D.z = this.rawData.get(10);
			vector3D.w = this.rawData.get(14);
			break;
		case 3:
			vector3D.x = this.rawData.get(3);
			vector3D.y = this.rawData.get(7);
			vector3D.z = this.rawData.get(11);
			vector3D.w = this.rawData.get(15);
			break;
		default:
		}
	},
	copyToMatrix3D: function(other) {
		other.rawData = this.rawData.copy();
	},
	decompose: function(orientationStyle) {
		if(orientationStyle == null) {
			orientationStyle = "eulerAngles";
		}
		var vec = (openfl__$Vector_Vector_$Impl_$().default)._new();
		var m = this.clone();
		var mr = m.rawData.copy();
		var pos = new (openfl_geom_Vector3D().default)(mr.get(12),mr.get(13),mr.get(14));
		mr.set(12,0);
		mr.set(13,0);
		mr.set(14,0);
		var scale = new (openfl_geom_Vector3D().default)();
		scale.x = Math.sqrt(mr.get(0) * mr.get(0) + mr.get(1) * mr.get(1) + mr.get(2) * mr.get(2));
		scale.y = Math.sqrt(mr.get(4) * mr.get(4) + mr.get(5) * mr.get(5) + mr.get(6) * mr.get(6));
		scale.z = Math.sqrt(mr.get(8) * mr.get(8) + mr.get(9) * mr.get(9) + mr.get(10) * mr.get(10));
		if(mr.get(0) * (mr.get(5) * mr.get(10) - mr.get(6) * mr.get(9)) - mr.get(1) * (mr.get(4) * mr.get(10) - mr.get(6) * mr.get(8)) + mr.get(2) * (mr.get(4) * mr.get(9) - mr.get(5) * mr.get(8)) < 0) {
			scale.z = -scale.z;
		}
		var _g = mr;
		_g.set(0,_g.get(0) / scale.x);
		var _g1 = mr;
		_g1.set(1,_g1.get(1) / scale.x);
		var _g2 = mr;
		_g2.set(2,_g2.get(2) / scale.x);
		var _g3 = mr;
		_g3.set(4,_g3.get(4) / scale.y);
		var _g4 = mr;
		_g4.set(5,_g4.get(5) / scale.y);
		var _g5 = mr;
		_g5.set(6,_g5.get(6) / scale.y);
		var _g6 = mr;
		_g6.set(8,_g6.get(8) / scale.z);
		var _g7 = mr;
		_g7.set(9,_g7.get(9) / scale.z);
		var _g8 = mr;
		_g8.set(10,_g8.get(10) / scale.z);
		var rot = new (openfl_geom_Vector3D().default)();
		switch(orientationStyle) {
		case "axisAngle":
			rot.w = Math.acos((mr.get(0) + mr.get(5) + mr.get(10) - 1) / 2);
			var len = Math.sqrt((mr.get(6) - mr.get(9)) * (mr.get(6) - mr.get(9)) + (mr.get(8) - mr.get(2)) * (mr.get(8) - mr.get(2)) + (mr.get(1) - mr.get(4)) * (mr.get(1) - mr.get(4)));
			if(len != 0) {
				rot.x = (mr.get(6) - mr.get(9)) / len;
				rot.y = (mr.get(8) - mr.get(2)) / len;
				rot.z = (mr.get(1) - mr.get(4)) / len;
			} else {
				rot.x = rot.y = rot.z = 0;
			}
			break;
		case "eulerAngles":
			rot.y = Math.asin(-mr.get(2));
			if(mr.get(2) != 1 && mr.get(2) != -1) {
				rot.x = Math.atan2(mr.get(6),mr.get(10));
				rot.z = Math.atan2(mr.get(1),mr.get(0));
			} else {
				rot.z = 0;
				rot.x = Math.atan2(mr.get(4),mr.get(5));
			}
			break;
		case "quaternion":
			var tr = mr.get(0) + mr.get(5) + mr.get(10);
			if(tr > 0) {
				rot.w = Math.sqrt(1 + tr) / 2;
				rot.x = (mr.get(6) - mr.get(9)) / (4 * rot.w);
				rot.y = (mr.get(8) - mr.get(2)) / (4 * rot.w);
				rot.z = (mr.get(1) - mr.get(4)) / (4 * rot.w);
			} else if(mr.get(0) > mr.get(5) && mr.get(0) > mr.get(10)) {
				rot.x = Math.sqrt(1 + mr.get(0) - mr.get(5) - mr.get(10)) / 2;
				rot.w = (mr.get(6) - mr.get(9)) / (4 * rot.x);
				rot.y = (mr.get(1) + mr.get(4)) / (4 * rot.x);
				rot.z = (mr.get(8) + mr.get(2)) / (4 * rot.x);
			} else if(mr.get(5) > mr.get(10)) {
				rot.y = Math.sqrt(1 + mr.get(5) - mr.get(0) - mr.get(10)) / 2;
				rot.x = (mr.get(1) + mr.get(4)) / (4 * rot.y);
				rot.w = (mr.get(8) - mr.get(2)) / (4 * rot.y);
				rot.z = (mr.get(6) + mr.get(9)) / (4 * rot.y);
			} else {
				rot.z = Math.sqrt(1 + mr.get(10) - mr.get(0) - mr.get(5)) / 2;
				rot.x = (mr.get(8) + mr.get(2)) / (4 * rot.z);
				rot.y = (mr.get(6) + mr.get(9)) / (4 * rot.z);
				rot.w = (mr.get(1) - mr.get(4)) / (4 * rot.z);
			}
			break;
		}
		vec.push(pos);
		vec.push(rot);
		vec.push(scale);
		return vec;
	},
	deltaTransformVector: function(v) {
		var x = v.x;
		var y = v.y;
		var z = v.z;
		return new (openfl_geom_Vector3D().default)(x * this.rawData.get(0) + y * this.rawData.get(4) + z * this.rawData.get(8) + this.rawData.get(3),x * this.rawData.get(1) + y * this.rawData.get(5) + z * this.rawData.get(9) + this.rawData.get(7),x * this.rawData.get(2) + y * this.rawData.get(6) + z * this.rawData.get(10) + this.rawData.get(11),0);
	},
	identity: function() {
		this.rawData = (openfl_VectorData().default).ofArray([1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0]);
	},
	interpolateTo: function(toMat,percent) {
		var _g = 0;
		while(_g < 16) {
			var i = _g++;
			this.rawData.set(i,this.rawData.get(i) + (toMat.rawData.get(i) - this.rawData.get(i)) * percent);
		}
	},
	invert: function() {
		var d = this.get_determinant();
		var invertable = Math.abs(d) > 0.00000000001;
		if(invertable) {
			d = 1 / d;
			var m11 = this.rawData.get(0);
			var m21 = this.rawData.get(4);
			var m31 = this.rawData.get(8);
			var m41 = this.rawData.get(12);
			var m12 = this.rawData.get(1);
			var m22 = this.rawData.get(5);
			var m32 = this.rawData.get(9);
			var m42 = this.rawData.get(13);
			var m13 = this.rawData.get(2);
			var m23 = this.rawData.get(6);
			var m33 = this.rawData.get(10);
			var m43 = this.rawData.get(14);
			var m14 = this.rawData.get(3);
			var m24 = this.rawData.get(7);
			var m34 = this.rawData.get(11);
			var m44 = this.rawData.get(15);
			this.rawData.set(0,d * (m22 * (m33 * m44 - m43 * m34) - m32 * (m23 * m44 - m43 * m24) + m42 * (m23 * m34 - m33 * m24)));
			this.rawData.set(1,-d * (m12 * (m33 * m44 - m43 * m34) - m32 * (m13 * m44 - m43 * m14) + m42 * (m13 * m34 - m33 * m14)));
			this.rawData.set(2,d * (m12 * (m23 * m44 - m43 * m24) - m22 * (m13 * m44 - m43 * m14) + m42 * (m13 * m24 - m23 * m14)));
			this.rawData.set(3,-d * (m12 * (m23 * m34 - m33 * m24) - m22 * (m13 * m34 - m33 * m14) + m32 * (m13 * m24 - m23 * m14)));
			this.rawData.set(4,-d * (m21 * (m33 * m44 - m43 * m34) - m31 * (m23 * m44 - m43 * m24) + m41 * (m23 * m34 - m33 * m24)));
			this.rawData.set(5,d * (m11 * (m33 * m44 - m43 * m34) - m31 * (m13 * m44 - m43 * m14) + m41 * (m13 * m34 - m33 * m14)));
			this.rawData.set(6,-d * (m11 * (m23 * m44 - m43 * m24) - m21 * (m13 * m44 - m43 * m14) + m41 * (m13 * m24 - m23 * m14)));
			this.rawData.set(7,d * (m11 * (m23 * m34 - m33 * m24) - m21 * (m13 * m34 - m33 * m14) + m31 * (m13 * m24 - m23 * m14)));
			this.rawData.set(8,d * (m21 * (m32 * m44 - m42 * m34) - m31 * (m22 * m44 - m42 * m24) + m41 * (m22 * m34 - m32 * m24)));
			this.rawData.set(9,-d * (m11 * (m32 * m44 - m42 * m34) - m31 * (m12 * m44 - m42 * m14) + m41 * (m12 * m34 - m32 * m14)));
			this.rawData.set(10,d * (m11 * (m22 * m44 - m42 * m24) - m21 * (m12 * m44 - m42 * m14) + m41 * (m12 * m24 - m22 * m14)));
			this.rawData.set(11,-d * (m11 * (m22 * m34 - m32 * m24) - m21 * (m12 * m34 - m32 * m14) + m31 * (m12 * m24 - m22 * m14)));
			this.rawData.set(12,-d * (m21 * (m32 * m43 - m42 * m33) - m31 * (m22 * m43 - m42 * m23) + m41 * (m22 * m33 - m32 * m23)));
			this.rawData.set(13,d * (m11 * (m32 * m43 - m42 * m33) - m31 * (m12 * m43 - m42 * m13) + m41 * (m12 * m33 - m32 * m13)));
			this.rawData.set(14,-d * (m11 * (m22 * m43 - m42 * m23) - m21 * (m12 * m43 - m42 * m13) + m41 * (m12 * m23 - m22 * m13)));
			this.rawData.set(15,d * (m11 * (m22 * m33 - m32 * m23) - m21 * (m12 * m33 - m32 * m13) + m31 * (m12 * m23 - m22 * m13)));
		}
		return invertable;
	},
	pointAt: function(pos,at,up) {
		if(at == null) {
			at = new (openfl_geom_Vector3D().default)(0,0,-1);
		}
		if(up == null) {
			up = new (openfl_geom_Vector3D().default)(0,-1,0);
		}
		var dir = at.subtract(pos);
		var vup = up.clone();
		var right;
		dir.normalize();
		vup.normalize();
		var dir2 = dir.clone();
		dir2.scaleBy(vup.dotProduct(dir));
		vup = vup.subtract(dir2);
		if(vup.get_length() > 0) {
			vup.normalize();
		} else if(dir.x != 0) {
			vup = new (openfl_geom_Vector3D().default)(-dir.y,dir.x,0);
		} else {
			vup = new (openfl_geom_Vector3D().default)(1,0,0);
		}
		right = vup.crossProduct(dir);
		right.normalize();
		this.rawData.set(0,right.x);
		this.rawData.set(4,right.y);
		this.rawData.set(8,right.z);
		this.rawData.set(12,0.0);
		this.rawData.set(1,vup.x);
		this.rawData.set(5,vup.y);
		this.rawData.set(9,vup.z);
		this.rawData.set(13,0.0);
		this.rawData.set(2,dir.x);
		this.rawData.set(6,dir.y);
		this.rawData.set(10,dir.z);
		this.rawData.set(14,0.0);
		this.rawData.set(3,pos.x);
		this.rawData.set(7,pos.y);
		this.rawData.set(11,pos.z);
		this.rawData.set(15,1.0);
	},
	prepend: function(rhs) {
		var m111 = rhs.rawData.get(0);
		var m121 = rhs.rawData.get(4);
		var m131 = rhs.rawData.get(8);
		var m141 = rhs.rawData.get(12);
		var m112 = rhs.rawData.get(1);
		var m122 = rhs.rawData.get(5);
		var m132 = rhs.rawData.get(9);
		var m142 = rhs.rawData.get(13);
		var m113 = rhs.rawData.get(2);
		var m123 = rhs.rawData.get(6);
		var m133 = rhs.rawData.get(10);
		var m143 = rhs.rawData.get(14);
		var m114 = rhs.rawData.get(3);
		var m124 = rhs.rawData.get(7);
		var m134 = rhs.rawData.get(11);
		var m144 = rhs.rawData.get(15);
		var m211 = this.rawData.get(0);
		var m221 = this.rawData.get(4);
		var m231 = this.rawData.get(8);
		var m241 = this.rawData.get(12);
		var m212 = this.rawData.get(1);
		var m222 = this.rawData.get(5);
		var m232 = this.rawData.get(9);
		var m242 = this.rawData.get(13);
		var m213 = this.rawData.get(2);
		var m223 = this.rawData.get(6);
		var m233 = this.rawData.get(10);
		var m243 = this.rawData.get(14);
		var m214 = this.rawData.get(3);
		var m224 = this.rawData.get(7);
		var m234 = this.rawData.get(11);
		var m244 = this.rawData.get(15);
		this.rawData.set(0,m111 * m211 + m112 * m221 + m113 * m231 + m114 * m241);
		this.rawData.set(1,m111 * m212 + m112 * m222 + m113 * m232 + m114 * m242);
		this.rawData.set(2,m111 * m213 + m112 * m223 + m113 * m233 + m114 * m243);
		this.rawData.set(3,m111 * m214 + m112 * m224 + m113 * m234 + m114 * m244);
		this.rawData.set(4,m121 * m211 + m122 * m221 + m123 * m231 + m124 * m241);
		this.rawData.set(5,m121 * m212 + m122 * m222 + m123 * m232 + m124 * m242);
		this.rawData.set(6,m121 * m213 + m122 * m223 + m123 * m233 + m124 * m243);
		this.rawData.set(7,m121 * m214 + m122 * m224 + m123 * m234 + m124 * m244);
		this.rawData.set(8,m131 * m211 + m132 * m221 + m133 * m231 + m134 * m241);
		this.rawData.set(9,m131 * m212 + m132 * m222 + m133 * m232 + m134 * m242);
		this.rawData.set(10,m131 * m213 + m132 * m223 + m133 * m233 + m134 * m243);
		this.rawData.set(11,m131 * m214 + m132 * m224 + m133 * m234 + m134 * m244);
		this.rawData.set(12,m141 * m211 + m142 * m221 + m143 * m231 + m144 * m241);
		this.rawData.set(13,m141 * m212 + m142 * m222 + m143 * m232 + m144 * m242);
		this.rawData.set(14,m141 * m213 + m142 * m223 + m143 * m233 + m144 * m243);
		this.rawData.set(15,m141 * m214 + m142 * m224 + m143 * m234 + m144 * m244);
	},
	prependRotation: function(degrees,axis,pivotPoint) {
		var tx;
		var ty;
		var tz = 0;
		ty = tz;
		tx = ty;
		if(pivotPoint != null) {
			tx = pivotPoint.x;
			ty = pivotPoint.y;
			tz = pivotPoint.z;
		}
		var radian = degrees * Math.PI / 180;
		var cos = Math.cos(radian);
		var sin = Math.sin(radian);
		var x = axis.x;
		var y = axis.y;
		var z = axis.z;
		var x2 = x * x;
		var y2 = y * y;
		var z2 = z * z;
		var ls = x2 + y2 + z2;
		if(ls != 0) {
			var l = Math.sqrt(ls);
			x /= l;
			y /= l;
			z /= l;
			x2 /= ls;
			y2 /= ls;
			z2 /= ls;
		}
		var ccos = 1 - cos;
		var m = new Matrix3D();
		var d = m.rawData;
		d.set(0,x2 + (y2 + z2) * cos);
		d.set(1,x * y * ccos + z * sin);
		d.set(2,x * z * ccos - y * sin);
		d.set(4,x * y * ccos - z * sin);
		d.set(5,y2 + (x2 + z2) * cos);
		d.set(6,y * z * ccos + x * sin);
		d.set(8,x * z * ccos + y * sin);
		d.set(9,y * z * ccos - x * sin);
		d.set(10,z2 + (x2 + y2) * cos);
		d.set(12,(tx * (y2 + z2) - x * (ty * y + tz * z)) * ccos + (ty * z - tz * y) * sin);
		d.set(13,(ty * (x2 + z2) - y * (tx * x + tz * z)) * ccos + (tz * x - tx * z) * sin);
		d.set(14,(tz * (x2 + y2) - z * (tx * x + ty * y)) * ccos + (tx * y - ty * x) * sin);
		this.prepend(m);
	},
	prependScale: function(xScale,yScale,zScale) {
		this.prepend(new Matrix3D((openfl_VectorData().default).ofArray([xScale,0.0,0.0,0.0,0.0,yScale,0.0,0.0,0.0,0.0,zScale,0.0,0.0,0.0,0.0,1.0])));
	},
	prependTranslation: function(x,y,z) {
		var m = new Matrix3D();
		m.set_position(new (openfl_geom_Vector3D().default)(x,y,z));
		this.prepend(m);
	},
	recompose: function(components,orientationStyle) {
		if(components.get_length() < 3 || components.get(2).x == 0 || components.get(2).y == 0 || components.get(2).z == 0) {
			return false;
		}
		if(orientationStyle == null) {
			orientationStyle = "eulerAngles";
		}
		this.identity();
		var scale = [];
		scale[0] = scale[1] = scale[2] = components.get(2).x;
		scale[4] = scale[5] = scale[6] = components.get(2).y;
		scale[8] = scale[9] = scale[10] = components.get(2).z;
		if(orientationStyle == null) {
			var x = components.get(1).x;
			var y = components.get(1).y;
			var z = components.get(1).z;
			var w = components.get(1).w;
			if(orientationStyle == "axisAngle") {
				x *= Math.sin(w / 2);
				y *= Math.sin(w / 2);
				z *= Math.sin(w / 2);
				w = Math.cos(w / 2);
			}
			this.rawData.set(0,(1 - 2 * y * y - 2 * z * z) * scale[0]);
			this.rawData.set(1,(2 * x * y + 2 * w * z) * scale[1]);
			this.rawData.set(2,(2 * x * z - 2 * w * y) * scale[2]);
			this.rawData.set(3,0);
			this.rawData.set(4,(2 * x * y - 2 * w * z) * scale[4]);
			this.rawData.set(5,(1 - 2 * x * x - 2 * z * z) * scale[5]);
			this.rawData.set(6,(2 * y * z + 2 * w * x) * scale[6]);
			this.rawData.set(7,0);
			this.rawData.set(8,(2 * x * z + 2 * w * y) * scale[8]);
			this.rawData.set(9,(2 * y * z - 2 * w * x) * scale[9]);
			this.rawData.set(10,(1 - 2 * x * x - 2 * y * y) * scale[10]);
			this.rawData.set(11,0);
			this.rawData.set(12,components.get(0).x);
			this.rawData.set(13,components.get(0).y);
			this.rawData.set(14,components.get(0).z);
			this.rawData.set(15,1);
		} else if(orientationStyle == "eulerAngles") {
			var cx = Math.cos(components.get(1).x);
			var cy = Math.cos(components.get(1).y);
			var cz = Math.cos(components.get(1).z);
			var sx = Math.sin(components.get(1).x);
			var sy = Math.sin(components.get(1).y);
			var sz = Math.sin(components.get(1).z);
			this.rawData.set(0,cy * cz * scale[0]);
			this.rawData.set(1,cy * sz * scale[1]);
			this.rawData.set(2,-sy * scale[2]);
			this.rawData.set(3,0);
			this.rawData.set(4,(sx * sy * cz - cx * sz) * scale[4]);
			this.rawData.set(5,(sx * sy * sz + cx * cz) * scale[5]);
			this.rawData.set(6,sx * cy * scale[6]);
			this.rawData.set(7,0);
			this.rawData.set(8,(cx * sy * cz + sx * sz) * scale[8]);
			this.rawData.set(9,(cx * sy * sz - sx * cz) * scale[9]);
			this.rawData.set(10,cx * cy * scale[10]);
			this.rawData.set(11,0);
			this.rawData.set(12,components.get(0).x);
			this.rawData.set(13,components.get(0).y);
			this.rawData.set(14,components.get(0).z);
			this.rawData.set(15,1);
		} else {
			var x1 = components.get(1).x;
			var y1 = components.get(1).y;
			var z1 = components.get(1).z;
			var w1 = components.get(1).w;
			if(orientationStyle == "axisAngle") {
				x1 *= Math.sin(w1 / 2);
				y1 *= Math.sin(w1 / 2);
				z1 *= Math.sin(w1 / 2);
				w1 = Math.cos(w1 / 2);
			}
			this.rawData.set(0,(1 - 2 * y1 * y1 - 2 * z1 * z1) * scale[0]);
			this.rawData.set(1,(2 * x1 * y1 + 2 * w1 * z1) * scale[1]);
			this.rawData.set(2,(2 * x1 * z1 - 2 * w1 * y1) * scale[2]);
			this.rawData.set(3,0);
			this.rawData.set(4,(2 * x1 * y1 - 2 * w1 * z1) * scale[4]);
			this.rawData.set(5,(1 - 2 * x1 * x1 - 2 * z1 * z1) * scale[5]);
			this.rawData.set(6,(2 * y1 * z1 + 2 * w1 * x1) * scale[6]);
			this.rawData.set(7,0);
			this.rawData.set(8,(2 * x1 * z1 + 2 * w1 * y1) * scale[8]);
			this.rawData.set(9,(2 * y1 * z1 - 2 * w1 * x1) * scale[9]);
			this.rawData.set(10,(1 - 2 * x1 * x1 - 2 * y1 * y1) * scale[10]);
			this.rawData.set(11,0);
			this.rawData.set(12,components.get(0).x);
			this.rawData.set(13,components.get(0).y);
			this.rawData.set(14,components.get(0).z);
			this.rawData.set(15,1);
		}
		if(components.get(2).x == 0) {
			this.rawData.set(0,1e-15);
		}
		if(components.get(2).y == 0) {
			this.rawData.set(5,1e-15);
		}
		if(components.get(2).z == 0) {
			this.rawData.set(10,1e-15);
		}
		return !(components.get(2).x == 0 || components.get(2).y == 0 || components.get(2).y == 0);
	},
	transformVector: function(v) {
		var x = v.x;
		var y = v.y;
		var z = v.z;
		return new (openfl_geom_Vector3D().default)(x * this.rawData.get(0) + y * this.rawData.get(4) + z * this.rawData.get(8) + this.rawData.get(12),x * this.rawData.get(1) + y * this.rawData.get(5) + z * this.rawData.get(9) + this.rawData.get(13),x * this.rawData.get(2) + y * this.rawData.get(6) + z * this.rawData.get(10) + this.rawData.get(14),x * this.rawData.get(3) + y * this.rawData.get(7) + z * this.rawData.get(11) + this.rawData.get(15));
	},
	transformVectors: function(vin,vout) {
		var i = 0;
		var x;
		var y;
		var z;
		while(i + 3 <= vin.get_length()) {
			x = vin.get(i);
			y = vin.get(i + 1);
			z = vin.get(i + 2);
			vout.set(i,x * this.rawData.get(0) + y * this.rawData.get(4) + z * this.rawData.get(8) + this.rawData.get(12));
			vout.set(i + 1,x * this.rawData.get(1) + y * this.rawData.get(5) + z * this.rawData.get(9) + this.rawData.get(13));
			vout.set(i + 2,x * this.rawData.get(2) + y * this.rawData.get(6) + z * this.rawData.get(10) + this.rawData.get(14));
			i += 3;
		}
	},
	transpose: function() {
		var oRawData = this.rawData.copy();
		this.rawData.set(1,oRawData.get(4));
		this.rawData.set(2,oRawData.get(8));
		this.rawData.set(3,oRawData.get(12));
		this.rawData.set(4,oRawData.get(1));
		this.rawData.set(6,oRawData.get(9));
		this.rawData.set(7,oRawData.get(13));
		this.rawData.set(8,oRawData.get(2));
		this.rawData.set(9,oRawData.get(6));
		this.rawData.set(11,oRawData.get(14));
		this.rawData.set(12,oRawData.get(3));
		this.rawData.set(13,oRawData.get(7));
		this.rawData.set(14,oRawData.get(11));
	},
	get_determinant: function() {
		return (this.rawData.get(0) * this.rawData.get(5) - this.rawData.get(4) * this.rawData.get(1)) * (this.rawData.get(10) * this.rawData.get(15) - this.rawData.get(14) * this.rawData.get(11)) - (this.rawData.get(0) * this.rawData.get(9) - this.rawData.get(8) * this.rawData.get(1)) * (this.rawData.get(6) * this.rawData.get(15) - this.rawData.get(14) * this.rawData.get(7)) + (this.rawData.get(0) * this.rawData.get(13) - this.rawData.get(12) * this.rawData.get(1)) * (this.rawData.get(6) * this.rawData.get(11) - this.rawData.get(10) * this.rawData.get(7)) + (this.rawData.get(4) * this.rawData.get(9) - this.rawData.get(8) * this.rawData.get(5)) * (this.rawData.get(2) * this.rawData.get(15) - this.rawData.get(14) * this.rawData.get(3)) - (this.rawData.get(4) * this.rawData.get(13) - this.rawData.get(12) * this.rawData.get(5)) * (this.rawData.get(2) * this.rawData.get(11) - this.rawData.get(10) * this.rawData.get(3)) + (this.rawData.get(8) * this.rawData.get(13) - this.rawData.get(12) * this.rawData.get(9)) * (this.rawData.get(2) * this.rawData.get(7) - this.rawData.get(6) * this.rawData.get(3));
	},
	get_position: function() {
		return new (openfl_geom_Vector3D().default)(this.rawData.get(12),this.rawData.get(13),this.rawData.get(14));
	},
	set_position: function(val) {
		this.rawData.set(12,val.x);
		this.rawData.set(13,val.y);
		this.rawData.set(14,val.z);
		return val;
	}
};
Matrix3D.prototype.__class__ = $hxClasses["openfl.geom.Matrix3D"] = Matrix3D;

// Init

Object.defineProperties(Matrix3D.prototype,{ "determinant" : { get : function () { return this.get_determinant (); }, set : function (v) { return this.set_determinant (v); }}, "position" : { get : function () { return this.get_position (); }, set : function (v) { return this.set_position (v); }}});

// Statics

Matrix3D.create2D = function(x,y,scale,rotation) {
	if(rotation == null) {
		rotation = 0;
	}
	if(scale == null) {
		scale = 1;
	}
	var theta = rotation * Math.PI / 180.0;
	var c = Math.cos(theta);
	var s = Math.sin(theta);
	return new Matrix3D((openfl_VectorData().default).ofArray([c * scale,-s * scale,0,0,s * scale,c * scale,0,0,0,0,1,0,x,y,0,1]));
}
Matrix3D.createABCD = function(a,b,c,d,tx,ty) {
	return new Matrix3D((openfl_VectorData().default).ofArray([a,b,0,0,c,d,0,0,0,0,1,0,tx,ty,0,1]));
}
Matrix3D.createOrtho = function(x0,x1,y0,y1,zNear,zFar) {
	var sx = 1.0 / (x1 - x0);
	var sy = 1.0 / (y1 - y0);
	var sz = 1.0 / (zFar - zNear);
	return new Matrix3D((openfl_VectorData().default).ofArray([2.0 * sx,0,0,0,0,2.0 * sy,0,0,0,0,-2.0 * sz,0,-(x0 + x1) * sx,-(y0 + y1) * sy,-(zNear + zFar) * sz,1]));
}
Matrix3D.interpolate = function(thisMat,toMat,percent) {
	var m = new Matrix3D();
	var _g = 0;
	while(_g < 16) {
		var i = _g++;
		m.rawData.set(i,thisMat.rawData.get(i) + (toMat.rawData.get(i) - thisMat.rawData.get(i)) * percent);
	}
	return m;
}
Matrix3D.__getAxisRotation = function(x,y,z,degrees) {
	var m = new Matrix3D();
	var a1 = new (openfl_geom_Vector3D().default)(x,y,z);
	var rad = -degrees * (Math.PI / 180);
	var c = Math.cos(rad);
	var s = Math.sin(rad);
	var t = 1.0 - c;
	m.rawData.set(0,c + a1.x * a1.x * t);
	m.rawData.set(5,c + a1.y * a1.y * t);
	m.rawData.set(10,c + a1.z * a1.z * t);
	var tmp1 = a1.x * a1.y * t;
	var tmp2 = a1.z * s;
	m.rawData.set(4,tmp1 + tmp2);
	m.rawData.set(1,tmp1 - tmp2);
	tmp1 = a1.x * a1.z * t;
	tmp2 = a1.y * s;
	m.rawData.set(8,tmp1 - tmp2);
	m.rawData.set(2,tmp1 + tmp2);
	tmp1 = a1.y * a1.z * t;
	tmp2 = a1.x * s;
	m.rawData.set(9,tmp1 + tmp2);
	m.rawData.set(6,tmp1 - tmp2);
	return m;
}


// Export

exports.default = Matrix3D;