forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
44
leenkx/Sources/iron/math/Mat3.hx
Normal file
44
leenkx/Sources/iron/math/Mat3.hx
Normal file
@ -0,0 +1,44 @@
|
||||
package iron.math;
|
||||
|
||||
import kha.FastFloat;
|
||||
|
||||
class Mat3 {
|
||||
|
||||
public var self: kha.math.FastMatrix3;
|
||||
|
||||
public inline function new(_00: FastFloat, _10: FastFloat, _20: FastFloat,
|
||||
_01: FastFloat, _11: FastFloat, _21: FastFloat,
|
||||
_02: FastFloat, _12: FastFloat, _22: FastFloat) {
|
||||
self = new kha.math.FastMatrix3(_00, _10, _20, _01, _11, _21, _02, _12, _22);
|
||||
}
|
||||
|
||||
public static inline function identity(): Mat3 {
|
||||
return new Mat3(
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1
|
||||
);
|
||||
}
|
||||
|
||||
public inline function setFrom4(m: Mat4) {
|
||||
_00 = m._00;
|
||||
_01 = m._01;
|
||||
_02 = m._02;
|
||||
_10 = m._10;
|
||||
_11 = m._11;
|
||||
_12 = m._12;
|
||||
_20 = m._20;
|
||||
_21 = m._21;
|
||||
_22 = m._22;
|
||||
}
|
||||
|
||||
public var _00(get, set): FastFloat; inline function get__00(): FastFloat { return self._00; } inline function set__00(f: FastFloat): FastFloat { return self._00 = f; }
|
||||
public var _01(get, set): FastFloat; inline function get__01(): FastFloat { return self._01; } inline function set__01(f: FastFloat): FastFloat { return self._01 = f; }
|
||||
public var _02(get, set): FastFloat; inline function get__02(): FastFloat { return self._02; } inline function set__02(f: FastFloat): FastFloat { return self._02 = f; }
|
||||
public var _10(get, set): FastFloat; inline function get__10(): FastFloat { return self._10; } inline function set__10(f: FastFloat): FastFloat { return self._10 = f; }
|
||||
public var _11(get, set): FastFloat; inline function get__11(): FastFloat { return self._11; } inline function set__11(f: FastFloat): FastFloat { return self._11 = f; }
|
||||
public var _12(get, set): FastFloat; inline function get__12(): FastFloat { return self._12; } inline function set__12(f: FastFloat): FastFloat { return self._12 = f; }
|
||||
public var _20(get, set): FastFloat; inline function get__20(): FastFloat { return self._20; } inline function set__20(f: FastFloat): FastFloat { return self._20 = f; }
|
||||
public var _21(get, set): FastFloat; inline function get__21(): FastFloat { return self._21; } inline function set__21(f: FastFloat): FastFloat { return self._21 = f; }
|
||||
public var _22(get, set): FastFloat; inline function get__22(): FastFloat { return self._22; } inline function set__22(f: FastFloat): FastFloat { return self._22 = f; }
|
||||
}
|
619
leenkx/Sources/iron/math/Mat4.hx
Normal file
619
leenkx/Sources/iron/math/Mat4.hx
Normal file
@ -0,0 +1,619 @@
|
||||
package iron.math;
|
||||
|
||||
import kha.FastFloat;
|
||||
|
||||
class Mat4 {
|
||||
|
||||
public var self: kha.math.FastMatrix4;
|
||||
static var helpVec = new Vec4();
|
||||
static var helpMat = Mat4.identity();
|
||||
|
||||
public inline function new(_00: FastFloat, _10: FastFloat, _20: FastFloat, _30: FastFloat,
|
||||
_01: FastFloat, _11: FastFloat, _21: FastFloat, _31: FastFloat,
|
||||
_02: FastFloat, _12: FastFloat, _22: FastFloat, _32: FastFloat,
|
||||
_03: FastFloat, _13: FastFloat, _23: FastFloat, _33: FastFloat) {
|
||||
self = new kha.math.FastMatrix4(_00, _10, _20, _30, _01, _11, _21, _31, _02, _12, _22, _32, _03, _13, _23, _33);
|
||||
}
|
||||
|
||||
/**
|
||||
Set the transform from a location, rotation and scale.
|
||||
@param loc The location to use.
|
||||
@param quat The rotation to use.
|
||||
@param sc The scale to use.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function compose(loc: Vec4, quat: Quat, sc: Vec4): Mat4 {
|
||||
fromQuat(quat);
|
||||
scale(sc);
|
||||
setLoc(loc);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Decompose this matrix into its location, rotation and scale components.
|
||||
Additional transforms (skew, projection) will be ignored.
|
||||
@param loc A vector to write the location to.
|
||||
@param quat A quaternion to write the rotation to.
|
||||
@param scale A vector to write the scale to.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function decompose(loc: Vec4, quat: Quat, scale: Vec4): Mat4 {
|
||||
loc.x = _30; loc.y = _31; loc.z = _32;
|
||||
scale.x = helpVec.set(_00, _01, _02).length();
|
||||
scale.y = helpVec.set(_10, _11, _12).length();
|
||||
scale.z = helpVec.set(_20, _21, _22).length();
|
||||
if (self.determinant() < 0.0) scale.x = -scale.x;
|
||||
var invs = 1.0 / scale.x; // Scale the rotation part
|
||||
helpMat._00 = _00 * invs;
|
||||
helpMat._01 = _01 * invs;
|
||||
helpMat._02 = _02 * invs;
|
||||
invs = 1.0 / scale.y;
|
||||
helpMat._10 = _10 * invs;
|
||||
helpMat._11 = _11 * invs;
|
||||
helpMat._12 = _12 * invs;
|
||||
invs = 1.0 / scale.z;
|
||||
helpMat._20 = _20 * invs;
|
||||
helpMat._21 = _21 * invs;
|
||||
helpMat._22 = _22 * invs;
|
||||
quat.fromRotationMat(helpMat);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the location component of this matrix.
|
||||
@param v The location to use.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function setLoc(v: Vec4): Mat4 {
|
||||
_30 = v.x;
|
||||
_31 = v.y;
|
||||
_32 = v.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the transform to a rotation from a quaternion. Other existing
|
||||
transforms will be removed.
|
||||
@param q The rotation to use.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function fromQuat(q: Quat): Mat4 {
|
||||
var x = q.x; var y = q.y; var z = q.z; var w = q.w;
|
||||
var x2 = x + x; var y2 = y + y; var z2 = z + z;
|
||||
var xx = x * x2; var xy = x * y2; var xz = x * z2;
|
||||
var yy = y * y2; var yz = y * z2; var zz = z * z2;
|
||||
var wx = w * x2; var wy = w * y2; var wz = w * z2;
|
||||
|
||||
_00 = 1.0 - (yy + zz);
|
||||
_10 = xy - wz;
|
||||
_20 = xz + wy;
|
||||
|
||||
_01 = xy + wz;
|
||||
_11 = 1.0 - (xx + zz);
|
||||
_21 = yz - wx;
|
||||
|
||||
_02 = xz - wy;
|
||||
_12 = yz + wx;
|
||||
_22 = 1.0 - (xx + yy);
|
||||
|
||||
_03 = 0.0;
|
||||
_13 = 0.0;
|
||||
_23 = 0.0;
|
||||
_30 = 0.0;
|
||||
_31 = 0.0;
|
||||
_32 = 0.0;
|
||||
_33 = 1.0;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Set all components of this matrix from an array.
|
||||
@param a The 16-component array to use. Components should be in the
|
||||
same order as for `Mat4.new()`.
|
||||
@param offset An offset index to the start of the data in the array.
|
||||
Defaults to 0.
|
||||
@return A new matrix.
|
||||
**/
|
||||
public static inline function fromFloat32Array(a: kha.arrays.Float32Array, offset = 0): Mat4 {
|
||||
return new Mat4(
|
||||
a[0 + offset], a[1 + offset], a[2 + offset], a[3 + offset],
|
||||
a[4 + offset], a[5 + offset], a[6 + offset], a[7 + offset],
|
||||
a[8 + offset], a[9 + offset], a[10 + offset], a[11 + offset],
|
||||
a[12 + offset], a[13 + offset], a[14 + offset], a[15 + offset]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Create a matrix that represents no transform - located at the origin,
|
||||
zero rotation, and a uniform scale of 1.
|
||||
@return A new matrix.
|
||||
**/
|
||||
public static inline function identity(): Mat4 {
|
||||
return new Mat4(
|
||||
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
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Set this matrix to the identity (see `identity()`).
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function setIdentity(): Mat4 {
|
||||
_00 = 1.0; _01 = 0.0; _02 = 0.0; _03 = 0.0;
|
||||
_10 = 0.0; _11 = 1.0; _12 = 0.0; _13 = 0.0;
|
||||
_20 = 0.0; _21 = 0.0; _22 = 1.0; _23 = 0.0;
|
||||
_30 = 0.0; _31 = 0.0; _32 = 0.0; _33 = 1.0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Reset this matrix to the identity and set its location.
|
||||
@param x The x location.
|
||||
@param y The y location.
|
||||
@param z The z location.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function initTranslate(x: FastFloat = 0.0, y: FastFloat = 0.0, z: FastFloat = 0.0): Mat4 {
|
||||
_00 = 1.0; _01 = 0.0; _02 = 0.0; _03 = 0.0;
|
||||
_10 = 0.0; _11 = 1.0; _12 = 0.0; _13 = 0.0;
|
||||
_20 = 0.0; _21 = 0.0; _22 = 1.0; _23 = 0.0;
|
||||
_30 = x; _31 = y; _32 = z; _33 = 1.0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Apply an additional translation to this matrix.
|
||||
@param x The distance to move in the x direction.
|
||||
@param y The distance to move in the x direction.
|
||||
@param z The distance to move in the x direction.
|
||||
@return This matrix
|
||||
**/
|
||||
public inline function translate(x: FastFloat, y: FastFloat, z: FastFloat): Mat4 {
|
||||
_00 += x * _03; _01 += y * _03; _02 += z * _03;
|
||||
_10 += x * _13; _11 += y * _13; _12 += z * _13;
|
||||
_20 += x * _23; _21 += y * _23; _22 += z * _23;
|
||||
_30 += x * _33; _31 += y * _33; _32 += z * _33;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Apply an additional scale to this matrix.
|
||||
@param v The vector to scale by.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function scale(v: Vec4): Mat4 {
|
||||
var x = v.x; var y = v.y; var z = v.z;
|
||||
_00 *= x;
|
||||
_01 *= x;
|
||||
_02 *= x;
|
||||
_03 *= x;
|
||||
_10 *= y;
|
||||
_11 *= y;
|
||||
_12 *= y;
|
||||
_13 *= y;
|
||||
_20 *= z;
|
||||
_21 *= z;
|
||||
_22 *= z;
|
||||
_23 *= z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function multmats3x4(a: Mat4, b: Mat4): Mat4 {
|
||||
var a00 = a._00; var a01 = a._01; var a02 = a._02; var a03 = a._03;
|
||||
var a10 = a._10; var a11 = a._11; var a12 = a._12; var a13 = a._13;
|
||||
var a20 = a._20; var a21 = a._21; var a22 = a._22; var a23 = a._23;
|
||||
var a30 = a._30; var a31 = a._31; var a32 = a._32; var a33 = a._33;
|
||||
|
||||
var b0 = b._00; var b1 = b._10; var b2 = b._20; var b3 = b._30;
|
||||
_00 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_10 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_20 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_30 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
b0 = b._01; b1 = b._11; b2 = b._21; b3 = b._31;
|
||||
_01 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_11 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_21 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_31 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
b0 = b._02; b1 = b._12; b2 = b._22; b3 = b._32;
|
||||
_02 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_12 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_22 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_32 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
_03 = 0;
|
||||
_13 = 0;
|
||||
_23 = 0;
|
||||
_33 = 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function multmats(b: Mat4, a: Mat4): Mat4 {
|
||||
var a00 = a._00; var a01 = a._01; var a02 = a._02; var a03 = a._03;
|
||||
var a10 = a._10; var a11 = a._11; var a12 = a._12; var a13 = a._13;
|
||||
var a20 = a._20; var a21 = a._21; var a22 = a._22; var a23 = a._23;
|
||||
var a30 = a._30; var a31 = a._31; var a32 = a._32; var a33 = a._33;
|
||||
|
||||
var b0 = b._00; var b1 = b._10; var b2 = b._20; var b3 = b._30;
|
||||
_00 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_10 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_20 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_30 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
b0 = b._01; b1 = b._11; b2 = b._21; b3 = b._31;
|
||||
_01 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_11 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_21 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_31 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
b0 = b._02; b1 = b._12; b2 = b._22; b3 = b._32;
|
||||
_02 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_12 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_22 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_32 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
b0 = b._03; b1 = b._13; b2 = b._23; b3 = b._33;
|
||||
_03 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_13 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_23 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_33 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function multmat(m: Mat4): Mat4 {
|
||||
var a00 = _00; var a01 = _01; var a02 = _02; var a03 = _03;
|
||||
var a10 = _10; var a11 = _11; var a12 = _12; var a13 = _13;
|
||||
var a20 = _20; var a21 = _21; var a22 = _22; var a23 = _23;
|
||||
var a30 = _30; var a31 = _31; var a32 = _32; var a33 = _33;
|
||||
|
||||
var b0 = m._00; var b1 = m._10; var b2 = m._20; var b3 = m._30;
|
||||
_00 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_10 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_20 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_30 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
b0 = m._01; b1 = m._11; b2 = m._21; b3 = m._31;
|
||||
_01 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_11 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_21 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_31 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
b0 = m._02; b1 = m._12; b2 = m._22; b3 = m._32;
|
||||
_02 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_12 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_22 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_32 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
b0 = m._03; b1 = m._13; b2 = m._23; b3 = m._33;
|
||||
_03 = a00 * b0 + a01 * b1 + a02 * b2 + a03 * b3;
|
||||
_13 = a10 * b0 + a11 * b1 + a12 * b2 + a13 * b3;
|
||||
_23 = a20 * b0 + a21 * b1 + a22 * b2 + a23 * b3;
|
||||
_33 = a30 * b0 + a31 * b1 + a32 * b2 + a33 * b3;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Invert a matrix and store the result in this one.
|
||||
@param m The matrix to invert.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function getInverse(m: Mat4): Mat4 {
|
||||
var a00 = m._00; var a01 = m._01; var a02 = m._02; var a03 = m._03;
|
||||
var a10 = m._10; var a11 = m._11; var a12 = m._12; var a13 = m._13;
|
||||
var a20 = m._20; var a21 = m._21; var a22 = m._22; var a23 = m._23;
|
||||
var a30 = m._30; var a31 = m._31; var a32 = m._32; var a33 = m._33;
|
||||
var b00 = a00 * a11 - a01 * a10;
|
||||
var b01 = a00 * a12 - a02 * a10;
|
||||
var b02 = a00 * a13 - a03 * a10;
|
||||
var b03 = a01 * a12 - a02 * a11;
|
||||
var b04 = a01 * a13 - a03 * a11;
|
||||
var b05 = a02 * a13 - a03 * a12;
|
||||
var b06 = a20 * a31 - a21 * a30;
|
||||
var b07 = a20 * a32 - a22 * a30;
|
||||
var b08 = a20 * a33 - a23 * a30;
|
||||
var b09 = a21 * a32 - a22 * a31;
|
||||
var b10 = a21 * a33 - a23 * a31;
|
||||
var b11 = a22 * a33 - a23 * a32;
|
||||
|
||||
var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
||||
if (det == 0.0) return setIdentity();
|
||||
det = 1.0 / det;
|
||||
|
||||
_00 = (a11 * b11 - a12 * b10 + a13 * b09) * det;
|
||||
_01 = (a02 * b10 - a01 * b11 - a03 * b09) * det;
|
||||
_02 = (a31 * b05 - a32 * b04 + a33 * b03) * det;
|
||||
_03 = (a22 * b04 - a21 * b05 - a23 * b03) * det;
|
||||
_10 = (a12 * b08 - a10 * b11 - a13 * b07) * det;
|
||||
_11 = (a00 * b11 - a02 * b08 + a03 * b07) * det;
|
||||
_12 = (a32 * b02 - a30 * b05 - a33 * b01) * det;
|
||||
_13 = (a20 * b05 - a22 * b02 + a23 * b01) * det;
|
||||
_20 = (a10 * b10 - a11 * b08 + a13 * b06) * det;
|
||||
_21 = (a01 * b08 - a00 * b10 - a03 * b06) * det;
|
||||
_22 = (a30 * b04 - a31 * b02 + a33 * b00) * det;
|
||||
_23 = (a21 * b02 - a20 * b04 - a23 * b00) * det;
|
||||
_30 = (a11 * b07 - a10 * b09 - a12 * b06) * det;
|
||||
_31 = (a00 * b09 - a01 * b07 + a02 * b06) * det;
|
||||
_32 = (a31 * b01 - a30 * b03 - a32 * b00) * det;
|
||||
_33 = (a20 * b03 - a21 * b01 + a22 * b00) * det;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Transpose this matrix.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function transpose(): Mat4 {
|
||||
var f = _01; _01 = _10; _10 = f;
|
||||
f = _02; _02 = _20; _20 = f;
|
||||
f = _03; _03 = _30; _30 = f;
|
||||
f = _12; _12 = _21; _21 = f;
|
||||
f = _13; _13 = _31; _31 = f;
|
||||
f = _23; _23 = _32; _32 = f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function transpose3x3(): Mat4 {
|
||||
var f = _01; _01 = _10; _10 = f;
|
||||
f = _02; _02 = _20; _20 = f;
|
||||
f = _12; _12 = _21; _21 = f;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Create a copy of this matrix.
|
||||
@return A new matrix.
|
||||
**/
|
||||
public inline function clone(): Mat4 {
|
||||
return new Mat4(
|
||||
_00, _10, _20, _30,
|
||||
_01, _11, _21, _31,
|
||||
_02, _12, _22, _32,
|
||||
_03, _13, _23, _33
|
||||
);
|
||||
}
|
||||
|
||||
public inline function setF32(a: kha.arrays.Float32Array, offset = 0): Mat4 {
|
||||
_00 = a[0 + offset]; _10 = a[1 + offset]; _20 = a[2 + offset]; _30 = a[3 + offset];
|
||||
_01 = a[4 + offset]; _11 = a[5 + offset]; _21 = a[6 + offset]; _31 = a[7 + offset];
|
||||
_02 = a[8 + offset]; _12 = a[9 + offset]; _22 = a[10 + offset]; _32 = a[11 + offset];
|
||||
_03 = a[12 + offset]; _13 = a[13 + offset]; _23 = a[14 + offset]; _33 = a[15 + offset];
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function setFrom(m: Mat4): Mat4 {
|
||||
_00 = m._00; _01 = m._01; _02 = m._02; _03 = m._03;
|
||||
_10 = m._10; _11 = m._11; _12 = m._12; _13 = m._13;
|
||||
_20 = m._20; _21 = m._21; _22 = m._22; _23 = m._23;
|
||||
_30 = m._30; _31 = m._31; _32 = m._32; _33 = m._33;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the location component.
|
||||
@return A new vector.
|
||||
**/
|
||||
public inline function getLoc(): Vec4 {
|
||||
return new Vec4(_30, _31, _32, _33);
|
||||
}
|
||||
|
||||
/**
|
||||
Get the scale component.
|
||||
@return A new vector.
|
||||
**/
|
||||
public inline function getScale(): Vec4 {
|
||||
return new Vec4(
|
||||
Math.sqrt(_00 * _00 + _10 * _10 + _20 * _20),
|
||||
Math.sqrt(_01 * _01 + _11 * _11 + _21 * _21),
|
||||
Math.sqrt(_02 * _02 + _12 * _12 + _22 * _22)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Multiply this vector by a scalar.
|
||||
@param s The value to multiply by.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function mult(s: FastFloat): Mat4 {
|
||||
_00 *= s; _10 *= s; _20 *= s; _30 *= s;
|
||||
_01 *= s; _11 *= s; _21 *= s; _31 *= s;
|
||||
_02 *= s; _12 *= s; _22 *= s; _32 *= s;
|
||||
_03 *= s; _13 *= s; _23 *= s; _33 *= s;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert this matrix to a rotation matrix, and discard location and
|
||||
scale information.
|
||||
@return This matrix.
|
||||
**/
|
||||
public inline function toRotation(): Mat4 {
|
||||
var scale = 1.0 / helpVec.set(_00, _01, _02).length();
|
||||
_00 = _00 * scale;
|
||||
_01 = _01 * scale;
|
||||
_02 = _02 * scale;
|
||||
scale = 1.0 / helpVec.set(_10, _11, _12).length();
|
||||
_10 = _10 * scale;
|
||||
_11 = _11 * scale;
|
||||
_12 = _12 * scale;
|
||||
scale = 1.0 / helpVec.set(_20, _21, _22).length();
|
||||
_20 = _20 * scale;
|
||||
_21 = _21 * scale;
|
||||
_22 = _22 * scale;
|
||||
_03 = 0.0;
|
||||
_13 = 0.0;
|
||||
_23 = 0.0;
|
||||
_30 = 0.0;
|
||||
_31 = 0.0;
|
||||
_32 = 0.0;
|
||||
_33 = 1.0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Create a new perspective projection matrix.
|
||||
@param fovY The vertical field of view.
|
||||
@param aspect The aspect ratio.
|
||||
@param zn The depth of the near floor of the frustum.
|
||||
@param zf The depth of the far floor of the frustum.
|
||||
@return A new matrix.
|
||||
**/
|
||||
public static inline function persp(fovY: FastFloat, aspect: FastFloat, zn: FastFloat, zf: FastFloat): Mat4 {
|
||||
var uh = 1.0 / Math.tan(fovY / 2);
|
||||
var uw = uh / aspect;
|
||||
return new Mat4(
|
||||
uw, 0, 0, 0,
|
||||
0, uh, 0, 0,
|
||||
0, 0, (zf + zn) / (zn - zf), 2 * zf * zn / (zn - zf),
|
||||
0, 0, -1, 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Create a new orthographic projection matrix.
|
||||
@param left The left of the box.
|
||||
@param right The right of the box.
|
||||
@param bottom The bottom of the box.
|
||||
@param top The top of the box.
|
||||
@param near The depth of the near floor of the box.
|
||||
@param far The depth of the far floor of the box.
|
||||
@return A new matrix.
|
||||
**/
|
||||
public static inline function ortho(left: FastFloat, right: FastFloat, bottom: FastFloat, top: FastFloat, near: FastFloat, far: FastFloat): Mat4 {
|
||||
var rl = right - left;
|
||||
var tb = top - bottom;
|
||||
var fn = far - near;
|
||||
var tx = -(right + left) / (rl);
|
||||
var ty = -(top + bottom) / (tb);
|
||||
var tz = -(far + near) / (fn);
|
||||
return new Mat4(
|
||||
2 / rl, 0, 0, tx,
|
||||
0, 2 / tb, 0, ty,
|
||||
0, 0, -2 / fn, tz,
|
||||
0, 0, 0, 1
|
||||
);
|
||||
}
|
||||
|
||||
public inline function setLookAt(eye: Vec4, center: Vec4, up: Vec4): Mat4 {
|
||||
var f0 = center.x - eye.x;
|
||||
var f1 = center.y - eye.y;
|
||||
var f2 = center.z - eye.z;
|
||||
var n = 1.0 / Math.sqrt(f0 * f0 + f1 * f1 + f2 * f2);
|
||||
f0 *= n;
|
||||
f1 *= n;
|
||||
f2 *= n;
|
||||
|
||||
var s0 = f1 * up.z - f2 * up.y;
|
||||
var s1 = f2 * up.x - f0 * up.z;
|
||||
var s2 = f0 * up.y - f1 * up.x;
|
||||
n = 1.0 / Math.sqrt(s0 * s0 + s1 * s1 + s2 * s2);
|
||||
s0 *= n;
|
||||
s1 *= n;
|
||||
s2 *= n;
|
||||
|
||||
var u0 = s1 * f2 - s2 * f1;
|
||||
var u1 = s2 * f0 - s0 * f2;
|
||||
var u2 = s0 * f1 - s1 * f0;
|
||||
var d0 = -eye.x * s0 - eye.y * s1 - eye.z * s2;
|
||||
var d1 = -eye.x * u0 - eye.y * u1 - eye.z * u2;
|
||||
var d2 = eye.x * f0 + eye.y * f1 + eye.z * f2;
|
||||
|
||||
_00 = s0;
|
||||
_10 = s1;
|
||||
_20 = s2;
|
||||
_30 = d0;
|
||||
_01 = u0;
|
||||
_11 = u1;
|
||||
_21 = u2;
|
||||
_31 = d1;
|
||||
_02 = -f0;
|
||||
_12 = -f1;
|
||||
_22 = -f2;
|
||||
_32 = d2;
|
||||
_03 = 0.0;
|
||||
_13 = 0.0;
|
||||
_23 = 0.0;
|
||||
_33 = 1.0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Apply an additional rotation to this matrix.
|
||||
@param q The quaternion to rotate by.
|
||||
**/
|
||||
public inline function applyQuat(q: Quat) {
|
||||
helpMat.fromQuat(q);
|
||||
multmat(helpMat);
|
||||
}
|
||||
|
||||
/**
|
||||
@return The right vector; the positive x axis of the space defined by
|
||||
this matrix.
|
||||
**/
|
||||
public inline function right(): Vec4 {
|
||||
return new Vec4(_00, _01, _02);
|
||||
}
|
||||
/**
|
||||
@return The look vector; the positive y axis of the space defined by
|
||||
this matrix.
|
||||
**/
|
||||
public inline function look(): Vec4 {
|
||||
return new Vec4(_10, _11, _12);
|
||||
}
|
||||
/**
|
||||
@return The up vector; the positive z axis of the space defined by
|
||||
this matrix.
|
||||
**/
|
||||
public inline function up(): Vec4 {
|
||||
return new Vec4(_20, _21, _22);
|
||||
}
|
||||
|
||||
public var _00(get, set): FastFloat; inline function get__00(): FastFloat { return self._00; } inline function set__00(f: FastFloat): FastFloat { return self._00 = f; }
|
||||
public var _01(get, set): FastFloat; inline function get__01(): FastFloat { return self._01; } inline function set__01(f: FastFloat): FastFloat { return self._01 = f; }
|
||||
public var _02(get, set): FastFloat; inline function get__02(): FastFloat { return self._02; } inline function set__02(f: FastFloat): FastFloat { return self._02 = f; }
|
||||
public var _03(get, set): FastFloat; inline function get__03(): FastFloat { return self._03; } inline function set__03(f: FastFloat): FastFloat { return self._03 = f; }
|
||||
public var _10(get, set): FastFloat; inline function get__10(): FastFloat { return self._10; } inline function set__10(f: FastFloat): FastFloat { return self._10 = f; }
|
||||
public var _11(get, set): FastFloat; inline function get__11(): FastFloat { return self._11; } inline function set__11(f: FastFloat): FastFloat { return self._11 = f; }
|
||||
public var _12(get, set): FastFloat; inline function get__12(): FastFloat { return self._12; } inline function set__12(f: FastFloat): FastFloat { return self._12 = f; }
|
||||
public var _13(get, set): FastFloat; inline function get__13(): FastFloat { return self._13; } inline function set__13(f: FastFloat): FastFloat { return self._13 = f; }
|
||||
public var _20(get, set): FastFloat; inline function get__20(): FastFloat { return self._20; } inline function set__20(f: FastFloat): FastFloat { return self._20 = f; }
|
||||
public var _21(get, set): FastFloat; inline function get__21(): FastFloat { return self._21; } inline function set__21(f: FastFloat): FastFloat { return self._21 = f; }
|
||||
public var _22(get, set): FastFloat; inline function get__22(): FastFloat { return self._22; } inline function set__22(f: FastFloat): FastFloat { return self._22 = f; }
|
||||
public var _23(get, set): FastFloat; inline function get__23(): FastFloat { return self._23; } inline function set__23(f: FastFloat): FastFloat { return self._23 = f; }
|
||||
public var _30(get, set): FastFloat; inline function get__30(): FastFloat { return self._30; } inline function set__30(f: FastFloat): FastFloat { return self._30 = f; }
|
||||
public var _31(get, set): FastFloat; inline function get__31(): FastFloat { return self._31; } inline function set__31(f: FastFloat): FastFloat { return self._31 = f; }
|
||||
public var _32(get, set): FastFloat; inline function get__32(): FastFloat { return self._32; } inline function set__32(f: FastFloat): FastFloat { return self._32 = f; }
|
||||
public var _33(get, set): FastFloat; inline function get__33(): FastFloat { return self._33; } inline function set__33(f: FastFloat): FastFloat { return self._33 = f; }
|
||||
|
||||
public function toString(): String {
|
||||
return '[[$_00, $_10, $_20, $_30], [$_01, $_11, $_21, $_31], [$_02, $_12, $_22, $_32], [$_03, $_13, $_23, $_33]]';
|
||||
}
|
||||
|
||||
public function toFloat32Array(): kha.arrays.Float32Array {
|
||||
var array = new kha.arrays.Float32Array(16);
|
||||
array[0] = _00;
|
||||
array[1] = _10;
|
||||
array[2] = _20;
|
||||
array[3] = _30;
|
||||
array[4] = _01;
|
||||
array[5] = _11;
|
||||
array[6] = _21;
|
||||
array[7] = _31;
|
||||
array[8] = _02;
|
||||
array[9] = _12;
|
||||
array[10] = _22;
|
||||
array[11] = _32;
|
||||
array[12] = _03;
|
||||
array[13] = _13;
|
||||
array[14] = _23;
|
||||
array[15] = _33;
|
||||
return array;
|
||||
}
|
||||
}
|
499
leenkx/Sources/iron/math/Quat.hx
Normal file
499
leenkx/Sources/iron/math/Quat.hx
Normal file
@ -0,0 +1,499 @@
|
||||
package iron.math;
|
||||
|
||||
import kha.FastFloat;
|
||||
|
||||
class Quat {
|
||||
|
||||
public var x: FastFloat;
|
||||
public var y: FastFloat;
|
||||
public var z: FastFloat;
|
||||
public var w: FastFloat;
|
||||
|
||||
static var helpVec0 = new Vec4();
|
||||
static var helpVec1 = new Vec4();
|
||||
static var helpVec2 = new Vec4();
|
||||
static var helpMat = Mat4.identity();
|
||||
static var xAxis = Vec4.xAxis();
|
||||
static var yAxis = Vec4.yAxis();
|
||||
|
||||
static inline var SQRT2: FastFloat = 1.4142135623730951;
|
||||
|
||||
public inline function new(x: FastFloat = 0.0, y: FastFloat = 0.0, z: FastFloat = 0.0, w: FastFloat = 1.0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
public inline function set(x: FastFloat, y: FastFloat, z: FastFloat, w: FastFloat): Quat {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function add(q: Quat): Quat {
|
||||
this.x += q.x;
|
||||
this.y += q.y;
|
||||
this.z += q.z;
|
||||
this.w += q.w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function addquat(a: Quat, b: Quat): Quat {
|
||||
this.x = a.x + b.x;
|
||||
this.y = a.y + b.y;
|
||||
this.z = a.z + b.z;
|
||||
this.w = a.w + b.w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function sub(q: Quat): Quat {
|
||||
this.x -= q.x;
|
||||
this.y -= q.y;
|
||||
this.z -= q.z;
|
||||
this.w -= q.w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function subquat(a: Quat, b: Quat): Quat {
|
||||
this.x = a.x - b.x;
|
||||
this.y = a.y - b.y;
|
||||
this.z = a.z - b.z;
|
||||
this.w = a.w - b.w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function fromAxisAngle(axis: Vec4, angle: FastFloat): Quat {
|
||||
var s: FastFloat = Math.sin(angle * 0.5);
|
||||
x = axis.x * s;
|
||||
y = axis.y * s;
|
||||
z = axis.z * s;
|
||||
w = Math.cos(angle * 0.5);
|
||||
return normalize();
|
||||
}
|
||||
|
||||
public inline function toAxisAngle(axis: Vec4): FastFloat {
|
||||
normalize();
|
||||
var angle = 2 * Math.acos(w);
|
||||
var s = Math.sqrt(1 - w * w);
|
||||
if (s < 0.001) {
|
||||
axis.x = this.x;
|
||||
axis.y = this.y;
|
||||
axis.z = this.z;
|
||||
}
|
||||
else {
|
||||
axis.x = this.x / s;
|
||||
axis.y = this.y / s;
|
||||
axis.z = this.z / s;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
public inline function fromMat(m: Mat4): Quat {
|
||||
helpMat.setFrom(m);
|
||||
helpMat.toRotation();
|
||||
return fromRotationMat(helpMat);
|
||||
}
|
||||
|
||||
public inline function fromRotationMat(m: Mat4): Quat {
|
||||
// Assumes the upper 3x3 is a pure rotation matrix
|
||||
var m11 = m._00; var m12 = m._10; var m13 = m._20;
|
||||
var m21 = m._01; var m22 = m._11; var m23 = m._21;
|
||||
var m31 = m._02; var m32 = m._12; var m33 = m._22;
|
||||
var tr = m11 + m22 + m33;
|
||||
var s = 0.0;
|
||||
|
||||
if (tr > 0) {
|
||||
s = 0.5 / Math.sqrt(tr + 1.0);
|
||||
this.w = 0.25 / s;
|
||||
this.x = (m32 - m23) * s;
|
||||
this.y = (m13 - m31) * s;
|
||||
this.z = (m21 - m12) * s;
|
||||
}
|
||||
else if (m11 > m22 && m11 > m33) {
|
||||
s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
|
||||
this.w = (m32 - m23) / s;
|
||||
this.x = 0.25 * s;
|
||||
this.y = (m12 + m21) / s;
|
||||
this.z = (m13 + m31) / s;
|
||||
}
|
||||
else if (m22 > m33) {
|
||||
s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
|
||||
this.w = (m13 - m31) / s;
|
||||
this.x = (m12 + m21) / s;
|
||||
this.y = 0.25 * s;
|
||||
this.z = (m23 + m32) / s;
|
||||
}
|
||||
else {
|
||||
s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
|
||||
this.w = (m21 - m12) / s;
|
||||
this.x = (m13 + m31) / s;
|
||||
this.y = (m23 + m32) / s;
|
||||
this.z = 0.25 * s;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// Multiply this quaternion by float
|
||||
public inline function scale(scale: FastFloat): Quat {
|
||||
this.x *= scale;
|
||||
this.y *= scale;
|
||||
this.z *= scale;
|
||||
this.w *= scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function scalequat(q: Quat, scale: FastFloat): Quat {
|
||||
q.x *= scale;
|
||||
q.y *= scale;
|
||||
q.z *= scale;
|
||||
q.w *= scale;
|
||||
return q;
|
||||
}
|
||||
|
||||
/**
|
||||
Multiply this quaternion by another.
|
||||
@param q The quaternion to multiply this one with.
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function mult(q: Quat): Quat {
|
||||
return multquats(this, q);
|
||||
}
|
||||
|
||||
/**
|
||||
Multiply two other quaternions and store the result in this one.
|
||||
@param q1 The first operand.
|
||||
@param q2 The second operand.
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function multquats(q1: Quat, q2: Quat): Quat {
|
||||
var q1x = q1.x; var q1y = q1.y; var q1z = q1.z; var q1w = q1.w;
|
||||
var q2x = q2.x; var q2y = q2.y; var q2z = q2.z; var q2w = q2.w;
|
||||
x = q1x * q2w + q1w * q2x + q1y * q2z - q1z * q2y;
|
||||
y = q1w * q2y - q1x * q2z + q1y * q2w + q1z * q2x;
|
||||
z = q1w * q2z + q1x * q2y - q1y * q2x + q1z * q2w;
|
||||
w = q1w * q2w - q1x * q2x - q1y * q2y - q1z * q2z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function module(): FastFloat {
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
||||
}
|
||||
|
||||
/**
|
||||
Scale this quaternion to have a magnitude of 1.
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function normalize(): Quat {
|
||||
var l = Math.sqrt(x * x + y * y + z * z + w * w);
|
||||
if (l == 0.0) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
w = 0;
|
||||
}
|
||||
else {
|
||||
l = 1.0 / l;
|
||||
x *= l;
|
||||
y *= l;
|
||||
z *= l;
|
||||
w *= l;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Invert the given quaternion and store the result in this one.
|
||||
@param q Quaternion to invert.
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function inverse(q: Quat): Quat {
|
||||
var sqsum = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
|
||||
sqsum = -1 / sqsum;
|
||||
x = q.x * sqsum;
|
||||
y = q.y * sqsum;
|
||||
z = q.z * sqsum;
|
||||
w = -q.w * sqsum;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Copy the rotation of another quaternion to this one.
|
||||
@param q A quaternion to copy.
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function setFrom(q: Quat): Quat {
|
||||
x = q.x;
|
||||
y = q.y;
|
||||
z = q.z;
|
||||
w = q.w;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert this quaternion to a YZX Euler (note: XZY in blender order terms).
|
||||
@return A new YZX Euler that represents the same rotation as this
|
||||
quaternion.
|
||||
**/
|
||||
public inline function getEuler(): Vec4 {
|
||||
var a = -2 * (x * z - w * y);
|
||||
var b = w * w + x * x - y * y - z * z;
|
||||
var c = 2 * (x * y + w * z);
|
||||
var d = -2 * (y * z - w * x);
|
||||
var e = w * w - x * x + y * y - z * z;
|
||||
return new Vec4(Math.atan2(d, e), Math.atan2(a, b), Math.asin(c));
|
||||
}
|
||||
|
||||
/**
|
||||
Set this quaternion to the rotation represented by a YZX Euler (XZY in blender terms).
|
||||
@param x The Euler's x component.
|
||||
@param y The Euler's y component.
|
||||
@param z The Euler's z component.
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function fromEuler(x: FastFloat, y: FastFloat, z: FastFloat): Quat {
|
||||
var f = x / 2;
|
||||
var c1 = Math.cos(f);
|
||||
var s1 = Math.sin(f);
|
||||
f = y / 2;
|
||||
var c2 = Math.cos(f);
|
||||
var s2 = Math.sin(f);
|
||||
f = z / 2;
|
||||
var c3 = Math.cos(f);
|
||||
var s3 = Math.sin(f);
|
||||
// YZX
|
||||
this.x = s1 * c2 * c3 + c1 * s2 * s3;
|
||||
this.y = c1 * s2 * c3 + s1 * c2 * s3;
|
||||
this.z = c1 * c2 * s3 - s1 * s2 * c3;
|
||||
this.w = c1 * c2 * c3 - s1 * s2 * s3;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert this quaternion to an Euler of arbitrary order.
|
||||
@param the order of the euler to obtain
|
||||
(in blender order, opposite from mathematical order)
|
||||
can be "XYZ", "XZY", "YXZ", "YZX", "ZXY", or "ZYX".
|
||||
@return A new YZX Euler that represents the same rotation as this
|
||||
quaternion.
|
||||
**/
|
||||
// this method use matrices as a middle ground
|
||||
// (and is copied from blender's internal code in mathutils)
|
||||
// note: there are two possible eulers for the same rotation, blender defines the 'best' as the one with the smallest sum of absolute components
|
||||
// should we actually make that choice, or is just getting one of them randomly good?
|
||||
// note2: it seems that this engine transforms a vector by using vector×matrix instead of matrix×vector, meaning that the outer transformations are on the RIGHT.
|
||||
// (…Except for quaternions, where the outer quaternions are on the LEFT.)
|
||||
// anywho, the way the elements of the matrix are ordered makes sense (first digit-> row ID, second digit->column ID) in this system.
|
||||
public inline function toEulerOrdered(p: String): Vec4{
|
||||
// normalize quat ?
|
||||
|
||||
var q0: FastFloat = SQRT2 * this.w;
|
||||
var q1: FastFloat = SQRT2 * this.x;
|
||||
var q2: FastFloat = SQRT2 * this.y;
|
||||
var q3: FastFloat = SQRT2 * this.z;
|
||||
|
||||
var qda: FastFloat = q0 * q1;
|
||||
var qdb: FastFloat = q0 * q2;
|
||||
var qdc: FastFloat = q0 * q3;
|
||||
var qaa: FastFloat = q1 * q1;
|
||||
var qab: FastFloat = q1 * q2;
|
||||
var qac: FastFloat = q1 * q3;
|
||||
var qbb: FastFloat = q2 * q2;
|
||||
var qbc: FastFloat = q2 * q3;
|
||||
var qcc: FastFloat = q3 * q3;
|
||||
|
||||
var m = new Mat3(
|
||||
// OK, *this* matrix is transposed with respect to what leenkx expects.
|
||||
// it is transposed again in the next step though
|
||||
|
||||
(1.0 - qbb - qcc),
|
||||
(qdc + qab),
|
||||
(-qdb + qac),
|
||||
|
||||
(-qdc + qab),
|
||||
(1.0 - qaa - qcc),
|
||||
(qda + qbc),
|
||||
|
||||
(qdb + qac),
|
||||
(-qda + qbc),
|
||||
(1.0 - qaa - qbb)
|
||||
);
|
||||
|
||||
// now define what is necessary to perform look-ups in that matrix
|
||||
var ml: Array<Array<FastFloat>> = [[m._00, m._10, m._20],
|
||||
[m._01, m._11, m._21],
|
||||
[m._02, m._12, m._22]];
|
||||
var eull: Array<FastFloat> = [0, 0, 0];
|
||||
|
||||
var i: Int = p.charCodeAt(0) - "X".charCodeAt(0);
|
||||
var j: Int = p.charCodeAt(1) - "X".charCodeAt(0);
|
||||
var k: Int = p.charCodeAt(2) - "X".charCodeAt(0);
|
||||
|
||||
// now the dumber version (isolating code)
|
||||
if (p.charAt(0) == "X") i = 0;
|
||||
else if (p.charAt(0) == "Y") i = 1;
|
||||
else i = 2;
|
||||
if (p.charAt(1) == "X") j = 0;
|
||||
else if (p.charAt(1) == "Y") j = 1;
|
||||
else j = 2;
|
||||
if (p.charAt(2) == "X") k = 0;
|
||||
else if (p.charAt(2) == "Y") k = 1;
|
||||
else k = 2;
|
||||
|
||||
var cy: FastFloat = Math.sqrt(ml[i][i] * ml[i][i] + ml[i][j] * ml[i][j]);
|
||||
|
||||
var eul1 = new Vec4();
|
||||
|
||||
if (cy > 16.0 * 1e-3) {
|
||||
eull[i] = Math.atan2(ml[j][k], ml[k][k]);
|
||||
eull[j] = Math.atan2(-ml[i][k], cy);
|
||||
eull[k] = Math.atan2(ml[i][j], ml[i][i]);
|
||||
}
|
||||
else {
|
||||
eull[i] = Math.atan2(-ml[k][j], ml[j][j]);
|
||||
eull[j] = Math.atan2(-ml[i][k], cy);
|
||||
eull[k] = 0; // 2 * Math.PI;
|
||||
}
|
||||
eul1.x = eull[0];
|
||||
eul1.y = eull[1];
|
||||
eul1.z = eull[2];
|
||||
|
||||
if (p == "XZY" || p == "YXZ" || p == "ZYX") {
|
||||
eul1.x *= -1;
|
||||
eul1.y *= -1;
|
||||
eul1.z *= -1;
|
||||
}
|
||||
return eul1;
|
||||
}
|
||||
|
||||
/**
|
||||
Set this quaternion to the rotation represented by an Euler.
|
||||
@param x The Euler's x component.
|
||||
@param y The Euler's y component.
|
||||
@param z The Euler's z component.
|
||||
@param order: the (blender) order of the euler
|
||||
(which is the OPPOSITE of the mathematical order)
|
||||
can be "XYZ", "XZY", "YXZ", "YZX", "ZXY", or "ZYX".
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function fromEulerOrdered(e: Vec4, order: String): Quat {
|
||||
var c1 = Math.cos(e.x / 2);
|
||||
var c2 = Math.cos(e.y / 2);
|
||||
var c3 = Math.cos(e.z / 2);
|
||||
var s1 = Math.sin(e.x / 2);
|
||||
var s2 = Math.sin(e.y / 2);
|
||||
var s3 = Math.sin(e.z / 2);
|
||||
|
||||
var qx = new Quat(s1, 0, 0, c1);
|
||||
var qy = new Quat(0, s2, 0, c2);
|
||||
var qz = new Quat(0, 0, s3, c3);
|
||||
|
||||
if (order.charAt(2) == 'X')
|
||||
this.setFrom(qx);
|
||||
else if (order.charAt(2) == 'Y')
|
||||
this.setFrom(qy);
|
||||
else
|
||||
this.setFrom(qz);
|
||||
if (order.charAt(1) == 'X')
|
||||
this.mult(qx);
|
||||
else if (order.charAt(1) == 'Y')
|
||||
this.mult(qy);
|
||||
else
|
||||
this.mult(qz);
|
||||
if (order.charAt(0) == 'X')
|
||||
this.mult(qx);
|
||||
else if (order.charAt(0) == 'Y')
|
||||
this.mult(qy);
|
||||
else
|
||||
this.mult(qz);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
Linearly interpolate between two other quaterions, and store the
|
||||
result in this one. This is not a so-called slerp operation.
|
||||
@param from The quaterion to interpolate from.
|
||||
@param to The quaterion to interpolate to.
|
||||
@param s The amount to interpolate, with 0 being `from` and 1 being
|
||||
`to`, and 0.5 being half way between the two.
|
||||
@return This quaternion.
|
||||
**/
|
||||
public inline function lerp(from: Quat, to: Quat, s: FastFloat): Quat {
|
||||
var fromx = from.x;
|
||||
var fromy = from.y;
|
||||
var fromz = from.z;
|
||||
var fromw = from.w;
|
||||
var dot: FastFloat = from.dot(to);
|
||||
if (dot < 0.0) {
|
||||
fromx = -fromx;
|
||||
fromy = -fromy;
|
||||
fromz = -fromz;
|
||||
fromw = -fromw;
|
||||
}
|
||||
x = fromx + (to.x - fromx) * s;
|
||||
y = fromy + (to.y - fromy) * s;
|
||||
z = fromz + (to.z - fromz) * s;
|
||||
w = fromw + (to.w - fromw) * s;
|
||||
return normalize();
|
||||
}
|
||||
|
||||
// Slerp is shorthand for spherical linear interpolation
|
||||
public inline function slerp(from: Quat, to: Quat, t: FastFloat): Quat {
|
||||
var epsilon: Float = 0.0005;
|
||||
|
||||
var dot = from.dot(to);
|
||||
if (dot > 1 - epsilon) {
|
||||
var result: Quat = to.add((from.sub(to)).scale(t));
|
||||
result.normalize();
|
||||
return result;
|
||||
}
|
||||
if (dot < 0) dot = 0;
|
||||
if (dot > 1) dot = 1;
|
||||
|
||||
var theta0: Float = Math.acos(dot);
|
||||
var theta: Float = theta0 * t;
|
||||
var q2: Quat = to.sub(scale(dot));
|
||||
q2.normalize();
|
||||
var result: Quat = scale(Math.cos(theta)).add(q2.scale(Math.sin(theta)));
|
||||
result.normalize();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Find the dot product of this quaternion with another.
|
||||
@param q The other quaternion.
|
||||
@return The dot product.
|
||||
**/
|
||||
public inline function dot(q: Quat): FastFloat {
|
||||
return (x * q.x) + (y * q.y) + (z * q.z) + (w * q.w);
|
||||
}
|
||||
|
||||
public inline function fromTo(v1: Vec4, v2: Vec4): Quat {
|
||||
// Rotation formed by direction vectors
|
||||
// v1 and v2 should be normalized first
|
||||
var a = helpVec0;
|
||||
var dot = v1.dot(v2);
|
||||
if (dot < -0.999999) {
|
||||
a.crossvecs(xAxis, v1);
|
||||
if (a.length() < 0.000001) a.crossvecs(yAxis, v1);
|
||||
a.normalize();
|
||||
fromAxisAngle(a, Math.PI);
|
||||
}
|
||||
else if (dot > 0.999999) {
|
||||
set(0, 0, 0, 1);
|
||||
}
|
||||
else {
|
||||
a.crossvecs(v1, v2);
|
||||
set(a.x, a.y, a.z, 1 + dot);
|
||||
normalize();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public function toString(): String {
|
||||
return this.x + ", " + this.y + ", " + this.z + ", " + this.w;
|
||||
}
|
||||
}
|
222
leenkx/Sources/iron/math/Ray.hx
Normal file
222
leenkx/Sources/iron/math/Ray.hx
Normal file
@ -0,0 +1,222 @@
|
||||
package iron.math;
|
||||
|
||||
import kha.FastFloat;
|
||||
|
||||
class Ray {
|
||||
|
||||
public var origin: Vec4;
|
||||
public var direction: Vec4;
|
||||
|
||||
public function new(origin: Vec4 = null, direction: Vec4 = null) {
|
||||
this.origin = origin == null ? new Vec4() : origin;
|
||||
this.direction = direction == null ? new Vec4() : direction;
|
||||
}
|
||||
|
||||
public function at(t: FastFloat): Vec4 {
|
||||
var result = new Vec4();
|
||||
return result.setFrom(direction).mult(t).add(origin);
|
||||
}
|
||||
|
||||
public function distanceToPoint(point: Vec4): FastFloat {
|
||||
var v1 = new Vec4();
|
||||
var directionDistance = v1.subvecs(point, this.origin).dot(this.direction);
|
||||
|
||||
// Point behind the ray
|
||||
if (directionDistance < 0) {
|
||||
return this.origin.distanceTo(point);
|
||||
}
|
||||
|
||||
v1.setFrom(this.direction).mult(directionDistance).add(this.origin);
|
||||
|
||||
return v1.distanceTo(point);
|
||||
}
|
||||
|
||||
public function intersectsSphere(sphereCenter: Vec4, sphereRadius: FastFloat): Bool {
|
||||
return distanceToPoint(sphereCenter) <= sphereRadius;
|
||||
}
|
||||
|
||||
public function intersectsPlane(plane: Plane): Bool {
|
||||
// Check if the ray lies on the plane first
|
||||
var distToPoint = plane.distanceToPoint(this.origin);
|
||||
if (distToPoint == 0) return true;
|
||||
|
||||
var denominator = plane.normal.dot(this.direction);
|
||||
if (denominator * distToPoint < 0) return true;
|
||||
|
||||
// Ray origin is behind the plane (and is pointing behind it)
|
||||
return false;
|
||||
}
|
||||
|
||||
public function distanceToPlane(plane: Plane): FastFloat {
|
||||
var denominator = plane.normal.dot(this.direction);
|
||||
if (denominator == 0) {
|
||||
// Line is coplanar, return origin
|
||||
if (plane.distanceToPoint(this.origin) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Null is preferable to undefined since undefined means.... it is undefined
|
||||
return -1;
|
||||
}
|
||||
|
||||
var t = -(this.origin.dot(plane.normal) + plane.constant) / denominator;
|
||||
|
||||
// Return if the ray never intersects the plane
|
||||
return t >= 0 ? t : -1;
|
||||
}
|
||||
|
||||
public function intersectPlane(plane: Plane): Vec4 {
|
||||
var t = this.distanceToPlane(plane);
|
||||
if (t == -1) return null;
|
||||
return this.at(t);
|
||||
}
|
||||
|
||||
public function intersectsBox(center: Vec4, dim: Vec4): Bool {
|
||||
return this.intersectBox(center, dim) != null;
|
||||
}
|
||||
|
||||
public function intersectBox(center: Vec4, dim: Vec4): Vec4 {
|
||||
// http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/
|
||||
var tmin, tmax, tymin, tymax, tzmin, tzmax;
|
||||
|
||||
var halfX = dim.x / 2;
|
||||
var halfY = dim.y / 2;
|
||||
var halfZ = dim.z / 2;
|
||||
var boxMinX = center.x - halfX;
|
||||
var boxMinY = center.y - halfY;
|
||||
var boxMinZ = center.z - halfZ;
|
||||
var boxMaxX = center.x + halfX;
|
||||
var boxMaxY = center.y + halfY;
|
||||
var boxMaxZ = center.z + halfZ;
|
||||
|
||||
var invdirx = 1 / this.direction.x;
|
||||
var invdiry = 1 / this.direction.y;
|
||||
var invdirz = 1 / this.direction.z;
|
||||
|
||||
var origin = this.origin;
|
||||
|
||||
if (invdirx >= 0) {
|
||||
tmin = (boxMinX - origin.x) * invdirx;
|
||||
tmax = (boxMaxX - origin.x) * invdirx;
|
||||
}
|
||||
else {
|
||||
tmin = (boxMaxX - origin.x) * invdirx;
|
||||
tmax = (boxMinX - origin.x) * invdirx;
|
||||
}
|
||||
|
||||
if (invdiry >= 0) {
|
||||
tymin = (boxMinY - origin.y) * invdiry;
|
||||
tymax = (boxMaxY - origin.y) * invdiry;
|
||||
}
|
||||
else {
|
||||
tymin = (boxMaxY - origin.y) * invdiry;
|
||||
tymax = (boxMinY - origin.y) * invdiry;
|
||||
}
|
||||
|
||||
if ((tmin > tymax) || (tymin > tmax)) return null;
|
||||
|
||||
// These lines also handle the case where tmin or tmax is NaN
|
||||
// (result of 0 * Infinity). x !== x returns true if x is NaN
|
||||
if (tymin > tmin || tmin != tmin) tmin = tymin;
|
||||
if (tymax < tmax || tmax != tmax) tmax = tymax;
|
||||
|
||||
if (invdirz >= 0) {
|
||||
tzmin = (boxMinZ - origin.z) * invdirz;
|
||||
tzmax = (boxMaxZ - origin.z) * invdirz;
|
||||
}
|
||||
else {
|
||||
tzmin = (boxMaxZ - origin.z) * invdirz;
|
||||
tzmax = (boxMinZ - origin.z) * invdirz;
|
||||
}
|
||||
|
||||
if ((tmin > tzmax) || (tzmin > tmax)) return null;
|
||||
if (tzmin > tmin || tmin != tmin ) tmin = tzmin;
|
||||
if (tzmax < tmax || tmax != tmax ) tmax = tzmax;
|
||||
|
||||
// Return point closest to the ray (positive side)
|
||||
if (tmax < 0) return null;
|
||||
|
||||
return this.at(tmin >= 0 ? tmin : tmax);
|
||||
}
|
||||
|
||||
public function intersectTriangle(a: Vec4, b: Vec4, c: Vec4, backfaceCulling: Bool): Vec4 {
|
||||
// Compute the offset origin, edges, and normal
|
||||
var diff = new Vec4();
|
||||
var edge1 = new Vec4();
|
||||
var edge2 = new Vec4();
|
||||
var normal = new Vec4();
|
||||
|
||||
// from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrRay3Triangle3.cpp
|
||||
edge1.subvecs(b, a);
|
||||
edge2.subvecs(c, a);
|
||||
normal.crossvecs(edge1, edge2);
|
||||
|
||||
// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
|
||||
// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by
|
||||
// |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
|
||||
// |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
|
||||
// |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
|
||||
var DdN = this.direction.dot(normal);
|
||||
var sign;
|
||||
|
||||
if (DdN > 0) {
|
||||
if (backfaceCulling) return null;
|
||||
sign = 1;
|
||||
}
|
||||
else if (DdN < 0) {
|
||||
sign = -1;
|
||||
DdN = -DdN;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
|
||||
diff.subvecs(this.origin, a);
|
||||
var DdQxE2 = sign * this.direction.dot(edge2.crossvecs(diff, edge2));
|
||||
|
||||
// b1 < 0, no intersection
|
||||
if (DdQxE2 < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var DdE1xQ = sign * this.direction.dot(edge1.cross(diff));
|
||||
|
||||
// b2 < 0, no intersection
|
||||
if (DdE1xQ < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// b1+b2 > 1, no intersection
|
||||
if (DdQxE2 + DdE1xQ > DdN) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Line intersects triangle, check if ray does.
|
||||
var QdN = -sign * diff.dot(normal);
|
||||
|
||||
// t < 0, no intersection
|
||||
if (QdN < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Ray intersects triangle.
|
||||
return this.at(QdN / DdN);
|
||||
}
|
||||
}
|
||||
|
||||
class Plane {
|
||||
public var normal = new Vec4(1.0, 0.0, 0.0);
|
||||
public var constant = 0.0;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function distanceToPoint(point: Vec4): FastFloat {
|
||||
return normal.dot(point) + constant;
|
||||
}
|
||||
|
||||
public function set(normal: Vec4, point: Vec4): Plane {
|
||||
this.normal.setFrom(normal);
|
||||
constant = -point.dot(this.normal);
|
||||
return this;
|
||||
}
|
||||
}
|
178
leenkx/Sources/iron/math/RayCaster.hx
Normal file
178
leenkx/Sources/iron/math/RayCaster.hx
Normal file
@ -0,0 +1,178 @@
|
||||
package iron.math;
|
||||
|
||||
import kha.FastFloat;
|
||||
import iron.object.CameraObject;
|
||||
import iron.object.MeshObject;
|
||||
import iron.object.Transform;
|
||||
import iron.object.Object;
|
||||
import iron.math.Ray;
|
||||
|
||||
class RayCaster {
|
||||
|
||||
static var VPInv = Mat4.identity();
|
||||
static var PInv = Mat4.identity();
|
||||
static var VInv = Mat4.identity();
|
||||
|
||||
static var loc = new Vec4();
|
||||
static var nor = new Vec4();
|
||||
static var m = Mat4.identity();
|
||||
|
||||
public static function getRay(inputX: FastFloat, inputY: FastFloat, camera: CameraObject): Ray {
|
||||
var start = new Vec4();
|
||||
var end = new Vec4();
|
||||
getDirection(start, end, inputX, inputY, camera);
|
||||
|
||||
// Find direction from start to end
|
||||
end.sub(start);
|
||||
end.normalize();
|
||||
end.x *= camera.data.raw.far_plane;
|
||||
end.y *= camera.data.raw.far_plane;
|
||||
end.z *= camera.data.raw.far_plane;
|
||||
|
||||
return new Ray(start, end);
|
||||
}
|
||||
|
||||
public static function getDirection(start: Vec4, end: Vec4, inputX: FastFloat, inputY: FastFloat, camera: CameraObject) {
|
||||
// Get 3D point form screen coords
|
||||
// Set two vectors with opposing z values
|
||||
start.x = (inputX / iron.App.w()) * 2.0 - 1.0;
|
||||
start.y = -((inputY / iron.App.h()) * 2.0 - 1.0);
|
||||
start.z = -1.0;
|
||||
end.x = start.x;
|
||||
end.y = start.y;
|
||||
end.z = 1.0;
|
||||
|
||||
PInv.getInverse(camera.P);
|
||||
VInv.getInverse(camera.V);
|
||||
VPInv.multmats(VInv, PInv);
|
||||
start.applyproj(VPInv);
|
||||
end.applyproj(VPInv);
|
||||
}
|
||||
|
||||
public static function boxIntersect(transform: Transform, inputX: FastFloat, inputY: FastFloat, camera: CameraObject): Vec4 {
|
||||
var ray = getRay(inputX, inputY, camera);
|
||||
|
||||
var t = transform;
|
||||
var c = new Vec4(t.worldx(), t.worldy(), t.worldz());
|
||||
var s = new Vec4(t.dim.x, t.dim.y, t.dim.z);
|
||||
return ray.intersectBox(c, s);
|
||||
}
|
||||
|
||||
public static function boxIntersectObject(o: Object, inputX: FastFloat, inputY: FastFloat, camera: CameraObject): Vec4 {
|
||||
var ray = getRay(inputX, inputY, camera);
|
||||
|
||||
var t = o.transform;
|
||||
var c = new Vec4(t.worldx(), t.worldy(), t.worldz());
|
||||
var s = new Vec4(t.dim.x, t.dim.y, t.dim.z);
|
||||
return ray.intersectBox(c, s);
|
||||
}
|
||||
|
||||
public static function closestBoxIntersect(transforms: Array<Transform>, inputX: FastFloat, inputY: FastFloat, camera: CameraObject): Transform {
|
||||
var intersects: Array<Transform> = [];
|
||||
|
||||
// Get intersects
|
||||
for (t in transforms) {
|
||||
var intersect = boxIntersect(t, inputX, inputY, camera);
|
||||
if (intersect != null) intersects.push(t);
|
||||
}
|
||||
|
||||
// No intersects
|
||||
if (intersects.length == 0) return null;
|
||||
|
||||
// Get closest intersect
|
||||
var closest: Transform = null;
|
||||
var minDist = Math.POSITIVE_INFINITY;
|
||||
for (t in intersects) {
|
||||
var dist = Vec4.distance(t.loc, camera.transform.loc);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
closest = t;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
public static function closestBoxIntersectObject(objects: Array<Object>, inputX: FastFloat, inputY: FastFloat, camera: CameraObject): Object {
|
||||
var intersects: Array<Object> = [];
|
||||
|
||||
// Get intersects
|
||||
for (o in objects) {
|
||||
var intersect = boxIntersectObject(o, inputX, inputY, camera);
|
||||
if (intersect != null) intersects.push(o);
|
||||
}
|
||||
|
||||
// No intersects
|
||||
if (intersects.length == 0) return null;
|
||||
|
||||
// Get closest intersect
|
||||
var closest: Object = null;
|
||||
var minDist = Math.POSITIVE_INFINITY;
|
||||
for (t in intersects) {
|
||||
var dist = Vec4.distance(t.transform.loc, camera.transform.loc);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
closest = t;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
public static function planeIntersect(normal: Vec4, a: Vec4, inputX: FastFloat, inputY: FastFloat, camera: CameraObject): Vec4 {
|
||||
var ray = getRay(inputX, inputY, camera);
|
||||
|
||||
var plane = new Plane();
|
||||
plane.set(normal, a);
|
||||
|
||||
return ray.intersectPlane(plane);
|
||||
}
|
||||
|
||||
// Project screen-space point onto 3D plane
|
||||
public static function getPlaneUV(obj: MeshObject, screenX: FastFloat, screenY: FastFloat, camera: CameraObject): Vec2 {
|
||||
nor = obj.transform.up(); // Transformed normal
|
||||
|
||||
// Plane intersection
|
||||
loc.set(obj.transform.worldx(), obj.transform.worldy(), obj.transform.worldz());
|
||||
var hit = RayCaster.planeIntersect(nor, loc, screenX, screenY, camera);
|
||||
|
||||
// Convert to uv
|
||||
if (hit != null) {
|
||||
var normals = obj.data.geom.normals.values;
|
||||
nor.set(normals[0], normals[1], normals[2]); // Raw normal
|
||||
|
||||
var a = nor.x;
|
||||
var b = nor.y;
|
||||
var c = nor.z;
|
||||
var e = 0.0001;
|
||||
var u = a >= e && b >= e ? new Vec4(b, -a, 0) : new Vec4(c, -a, 0);
|
||||
u.normalize();
|
||||
|
||||
var v = nor.clone();
|
||||
v.cross(u);
|
||||
|
||||
m.setFrom(obj.transform.world);
|
||||
m.getInverse(m);
|
||||
m.transpose3x3();
|
||||
m._30 = m._31 = m._32 = 0;
|
||||
u.applymat(m);
|
||||
u.normalize();
|
||||
v.applymat(m);
|
||||
v.normalize();
|
||||
|
||||
hit.sub(loc); // Center
|
||||
var ucoord = u.dot(hit);
|
||||
var vcoord = v.dot(hit);
|
||||
|
||||
var dim = obj.transform.dim;
|
||||
var size = dim.x > dim.y ? dim.x / 2 : dim.y / 2;
|
||||
|
||||
// Screen space
|
||||
var ix = ucoord / size * -0.5 + 0.5;
|
||||
var iy = vcoord / size * -0.5 + 0.5;
|
||||
|
||||
return new Vec2(ix, iy);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
138
leenkx/Sources/iron/math/Vec2.hx
Normal file
138
leenkx/Sources/iron/math/Vec2.hx
Normal file
@ -0,0 +1,138 @@
|
||||
package iron.math;
|
||||
|
||||
import kha.FastFloat;
|
||||
|
||||
class Vec2 {
|
||||
public var x: FastFloat;
|
||||
public var y: FastFloat;
|
||||
|
||||
public inline function new(x: FastFloat = 0.0, y: FastFloat = 0.0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public inline function cross(v: Vec2): FastFloat {
|
||||
return x * v.y - y * v.x;
|
||||
}
|
||||
|
||||
public inline function set(x: FastFloat, y: FastFloat): Vec2{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function add(v: Vec2): Vec2 {
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function addf(x: FastFloat, y: FastFloat): Vec2 {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function addvecs(a: Vec2, b: Vec2): Vec2 {
|
||||
x = a.x + b.x;
|
||||
y = a.y + b.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function subvecs(a: Vec2, b: Vec2): Vec2 {
|
||||
x = a.x - b.x;
|
||||
y = a.y - b.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function normalize(): Vec2 {
|
||||
var a = this.x;
|
||||
var b = this.y;
|
||||
var l = a * a + b * b;
|
||||
if (l > 0.0) {
|
||||
l = 1.0 / Math.sqrt(l);
|
||||
this.x = a * l;
|
||||
this.y = b * l;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function mult(f: FastFloat): Vec2 {
|
||||
x *= f;
|
||||
y *= f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function dot(v: Vec2): FastFloat {
|
||||
return x * v.x + y * v.y;
|
||||
}
|
||||
|
||||
public inline function setFrom(v: Vec2): Vec2 {
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function clone(): Vec2 {
|
||||
return new Vec2(x, y);
|
||||
}
|
||||
|
||||
public inline function lerp(from: Vec2, to: Vec2, s: FastFloat): Vec2 {
|
||||
x = from.x + (to.x - from.x) * s;
|
||||
y = from.y + (to.y - from.y) * s;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function equals(v: Vec2): Bool {
|
||||
return x == v.x && y == v.y;
|
||||
}
|
||||
|
||||
public inline function length(): FastFloat {
|
||||
return Math.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public inline function sub(v: Vec2): Vec2 {
|
||||
x -= v.x;
|
||||
y -= v.y;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function exp(v: Vec2): Vec2 {
|
||||
x = Math.exp(v.x);
|
||||
y = Math.exp(v.y);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static inline function distance(v1: Vec2, v2: Vec2): FastFloat {
|
||||
return distancef(v1.x, v1.y, v2.x, v2.y);
|
||||
}
|
||||
|
||||
public static inline function distancef(v1x: FastFloat, v1y: FastFloat, v2x: FastFloat, v2y: FastFloat): FastFloat {
|
||||
var vx = v1x - v2x;
|
||||
var vy = v1y - v2y;
|
||||
return Math.sqrt(vx * vx + vy * vy);
|
||||
}
|
||||
|
||||
public inline function distanceTo(p: Vec2): FastFloat {
|
||||
return Math.sqrt((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y));
|
||||
}
|
||||
|
||||
public inline function clamp(min: FastFloat, max: FastFloat): Vec2 {
|
||||
var l = length();
|
||||
if (l < min) normalize().mult(min);
|
||||
else if (l > max) normalize().mult(max);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static inline function xAxis(): Vec2 {
|
||||
return new Vec2(1.0, 0.0);
|
||||
}
|
||||
|
||||
public static inline function yAxis(): Vec2 {
|
||||
return new Vec2(0.0, 1.0);
|
||||
}
|
||||
|
||||
public function toString(): String {
|
||||
return "(" + this.x + ", " + this.y + ")";
|
||||
}
|
||||
}
|
181
leenkx/Sources/iron/math/Vec3.hx
Normal file
181
leenkx/Sources/iron/math/Vec3.hx
Normal file
@ -0,0 +1,181 @@
|
||||
package iron.math;
|
||||
|
||||
import kha.FastFloat;
|
||||
|
||||
class Vec3 {
|
||||
public var x: FastFloat;
|
||||
public var y: FastFloat;
|
||||
public var z: FastFloat;
|
||||
|
||||
public inline function new(x: FastFloat = 0.0, y: FastFloat = 0.0, z: FastFloat = 0.0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public inline function cross(v: Vec3): Vec3 {
|
||||
var ax = x; var ay = y; var az = z;
|
||||
var vx = v.x; var vy = v.y; var vz = v.z;
|
||||
x = ay * vz - az * vy;
|
||||
y = az * vx - ax * vz;
|
||||
z = ax * vy - ay * vx;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function crossvecs(a: Vec3, b: Vec3): Vec3 {
|
||||
var ax = a.x; var ay = a.y; var az = a.z;
|
||||
var bx = b.x; var by = b.y; var bz = b.z;
|
||||
x = ay * bz - az * by;
|
||||
y = az * bx - ax * bz;
|
||||
z = ax * by - ay * bx;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function set(x: FastFloat, y: FastFloat, z: FastFloat): Vec3{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function add(v: Vec3): Vec3 {
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
z += v.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function addf(x: FastFloat, y: FastFloat, z: FastFloat): Vec3 {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.z += z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function addvecs(a: Vec3, b: Vec3): Vec3 {
|
||||
x = a.x + b.x;
|
||||
y = a.y + b.y;
|
||||
z = a.z + b.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function subvecs(a: Vec3, b: Vec3): Vec3 {
|
||||
x = a.x - b.x;
|
||||
y = a.y - b.y;
|
||||
z = a.z - b.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function normalize(): Vec3 {
|
||||
var n = length();
|
||||
if (n > 0.0) {
|
||||
var invN = 1.0 / n;
|
||||
this.x *= invN; this.y *= invN; this.z *= invN;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function mult(f: FastFloat): Vec3 {
|
||||
x *= f;
|
||||
y *= f;
|
||||
z *= f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function dot(v: Vec3): FastFloat {
|
||||
return x * v.x + y * v.y + z * v.z;
|
||||
}
|
||||
|
||||
public inline function setFrom(v: Vec3): Vec3 {
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
z = v.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function clone(): Vec3 {
|
||||
return new Vec3(x, y, z);
|
||||
}
|
||||
|
||||
public inline function lerp(from: Vec3, to: Vec3, s: FastFloat): Vec3 {
|
||||
x = from.x + (to.x - from.x) * s;
|
||||
y = from.y + (to.y - from.y) * s;
|
||||
z = from.z + (to.z - from.z) * s;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function applyproj(m: Mat4): Vec3 {
|
||||
var x = this.x; var y = this.y; var z = this.z;
|
||||
var d = 1.0 / (m._03 * x + m._13 * y + m._23 * z + m._33); // Perspective divide
|
||||
this.x = (m._00 * x + m._10 * y + m._20 * z + m._30) * d;
|
||||
this.y = (m._01 * x + m._11 * y + m._21 * z + m._31) * d;
|
||||
this.z = (m._02 * x + m._12 * y + m._22 * z + m._32) * d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function applymat(m: Mat4): Vec3 {
|
||||
var x = this.x; var y = this.y; var z = this.z;
|
||||
this.x = m._00 * x + m._10 * y + m._20 * z + m._30;
|
||||
this.y = m._01 * x + m._11 * y + m._21 * z + m._31;
|
||||
this.z = m._02 * x + m._12 * y + m._22 * z + m._32;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function equals(v: Vec3): Bool {
|
||||
return x == v.x && y == v.y && z == v.z;
|
||||
}
|
||||
|
||||
public inline function length(): FastFloat {
|
||||
return Math.sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
public inline function sub(v: Vec3): Vec3 {
|
||||
x -= v.x; y -= v.y; z -= v.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function exp(v: Vec3): Vec3 {
|
||||
x = Math.exp(v.x);
|
||||
y = Math.exp(v.y);
|
||||
z = Math.exp(v.z);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static inline function distance(v1: Vec3, v2: Vec3): FastFloat {
|
||||
return distancef(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);
|
||||
}
|
||||
|
||||
public static inline function distancef(v1x: FastFloat, v1y: FastFloat, v1z: FastFloat, v2x: FastFloat, v2y: FastFloat, v2z: FastFloat): FastFloat {
|
||||
var vx = v1x - v2x;
|
||||
var vy = v1y - v2y;
|
||||
var vz = v1z - v2z;
|
||||
return Math.sqrt(vx * vx + vy * vy + vz * vz);
|
||||
}
|
||||
|
||||
public inline function distanceTo(p: Vec3): FastFloat {
|
||||
return Math.sqrt((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y) + (p.z - z) * (p.z - z));
|
||||
}
|
||||
|
||||
public inline function clamp(min: FastFloat, max: FastFloat): Vec3 {
|
||||
var l = length();
|
||||
if (l < min) normalize().mult(min);
|
||||
else if (l > max) normalize().mult(max);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static inline function xAxis(): Vec3 {
|
||||
return new Vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
public static inline function yAxis(): Vec3 {
|
||||
return new Vec3(0.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
public static inline function zAxis(): Vec3 {
|
||||
return new Vec3(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
public function toString(): String {
|
||||
return "(" + this.x + ", " + this.y + ", " + this.z + ")";
|
||||
}
|
||||
}
|
226
leenkx/Sources/iron/math/Vec4.hx
Normal file
226
leenkx/Sources/iron/math/Vec4.hx
Normal file
@ -0,0 +1,226 @@
|
||||
package iron.math;
|
||||
|
||||
import kha.FastFloat;
|
||||
|
||||
class Vec4 {
|
||||
|
||||
public var x: FastFloat;
|
||||
public var y: FastFloat;
|
||||
public var z: FastFloat;
|
||||
public var w: FastFloat;
|
||||
|
||||
public inline function new(x: FastFloat = 0.0, y: FastFloat = 0.0, z: FastFloat = 0.0, w: FastFloat = 1.0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
public inline function cross(v: Vec4): Vec4 {
|
||||
var ax = x; var ay = y; var az = z;
|
||||
var vx = v.x; var vy = v.y; var vz = v.z;
|
||||
x = ay * vz - az * vy;
|
||||
y = az * vx - ax * vz;
|
||||
z = ax * vy - ay * vx;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function crossvecs(a: Vec4, b: Vec4): Vec4 {
|
||||
var ax = a.x; var ay = a.y; var az = a.z;
|
||||
var bx = b.x; var by = b.y; var bz = b.z;
|
||||
x = ay * bz - az * by;
|
||||
y = az * bx - ax * bz;
|
||||
z = ax * by - ay * bx;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function set(x: FastFloat, y: FastFloat, z: FastFloat, w: FastFloat = 1.0): Vec4{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w = w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function add(v: Vec4): Vec4 {
|
||||
x += v.x;
|
||||
y += v.y;
|
||||
z += v.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function addf(x: FastFloat, y: FastFloat, z: FastFloat): Vec4 {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.z += z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function addvecs(a: Vec4, b: Vec4): Vec4 {
|
||||
x = a.x + b.x;
|
||||
y = a.y + b.y;
|
||||
z = a.z + b.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function subvecs(a: Vec4, b: Vec4): Vec4 {
|
||||
x = a.x - b.x;
|
||||
y = a.y - b.y;
|
||||
z = a.z - b.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function normalize(): Vec4 {
|
||||
var n = length();
|
||||
if (n > 0.0) {
|
||||
var invN = 1.0 / n;
|
||||
this.x *= invN;
|
||||
this.y *= invN;
|
||||
this.z *= invN;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function mult(f: FastFloat): Vec4 {
|
||||
x *= f;
|
||||
y *= f;
|
||||
z *= f;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function dot(v: Vec4): FastFloat {
|
||||
return x * v.x + y * v.y + z * v.z;
|
||||
}
|
||||
|
||||
public inline function setFrom(v: Vec4): Vec4 {
|
||||
x = v.x;
|
||||
y = v.y;
|
||||
z = v.z;
|
||||
w = v.w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function clone(): Vec4 {
|
||||
return new Vec4(x, y, z, w);
|
||||
}
|
||||
|
||||
public inline function lerp(from: Vec4, to: Vec4, s: FastFloat): Vec4 {
|
||||
x = from.x + (to.x - from.x) * s;
|
||||
y = from.y + (to.y - from.y) * s;
|
||||
z = from.z + (to.z - from.z) * s;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function applyproj(m: Mat4): Vec4 {
|
||||
var x = this.x; var y = this.y; var z = this.z;
|
||||
var d = 1.0 / (m._03 * x + m._13 * y + m._23 * z + m._33); // Perspective divide
|
||||
this.x = (m._00 * x + m._10 * y + m._20 * z + m._30) * d;
|
||||
this.y = (m._01 * x + m._11 * y + m._21 * z + m._31) * d;
|
||||
this.z = (m._02 * x + m._12 * y + m._22 * z + m._32) * d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function applymat(m: Mat4): Vec4 {
|
||||
var x = this.x; var y = this.y; var z = this.z;
|
||||
this.x = m._00 * x + m._10 * y + m._20 * z + m._30;
|
||||
this.y = m._01 * x + m._11 * y + m._21 * z + m._31;
|
||||
this.z = m._02 * x + m._12 * y + m._22 * z + m._32;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function applymat4(m: Mat4): Vec4 {
|
||||
var x = this.x; var y = this.y; var z = this.z; var w = this.w;
|
||||
this.x = m._00 * x + m._10 * y + m._20 * z + m._30 * w;
|
||||
this.y = m._01 * x + m._11 * y + m._21 * z + m._31 * w;
|
||||
this.z = m._02 * x + m._12 * y + m._22 * z + m._32 * w;
|
||||
this.w = m._03 * x + m._13 * y + m._23 * z + m._33 * w;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function applyAxisAngle(axis: Vec4, angle: FastFloat): Vec4 {
|
||||
var quat = new Quat();
|
||||
quat.fromAxisAngle(axis, angle);
|
||||
return applyQuat(quat);
|
||||
}
|
||||
|
||||
public inline function applyQuat(q: Quat): Vec4 {
|
||||
var ix = q.w * x + q.y * z - q.z * y;
|
||||
var iy = q.w * y + q.z * x - q.x * z;
|
||||
var iz = q.w * z + q.x * y - q.y * x;
|
||||
var iw = -q.x * x - q.y * y - q.z * z;
|
||||
x = ix * q.w + iw * -q.x + iy * -q.z - iz * -q.y;
|
||||
y = iy * q.w + iw * -q.y + iz * -q.x - ix * -q.z;
|
||||
z = iz * q.w + iw * -q.z + ix * -q.y - iy * -q.x;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function equals(v: Vec4): Bool {
|
||||
return x == v.x && y == v.y && z == v.z;
|
||||
}
|
||||
|
||||
public inline function almostEquals(v: Vec4, prec: FastFloat): Bool {
|
||||
return Math.abs(x - v.x) < prec && Math.abs(y - v.y) < prec && Math.abs(z - v.z) < prec;
|
||||
}
|
||||
|
||||
public inline function length(): FastFloat {
|
||||
return Math.sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
public inline function sub(v: Vec4): Vec4 {
|
||||
x -= v.x; y -= v.y; z -= v.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function exp(v: Vec4): Vec4 {
|
||||
x = Math.exp(v.x);
|
||||
y = Math.exp(v.y);
|
||||
z = Math.exp(v.z);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static inline function distance(v1: Vec4, v2: Vec4): FastFloat {
|
||||
return distancef(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);
|
||||
}
|
||||
|
||||
public static inline function distancef(v1x: FastFloat, v1y: FastFloat, v1z: FastFloat, v2x: FastFloat, v2y: FastFloat, v2z: FastFloat): FastFloat {
|
||||
var vx = v1x - v2x;
|
||||
var vy = v1y - v2y;
|
||||
var vz = v1z - v2z;
|
||||
return Math.sqrt(vx * vx + vy * vy + vz * vz);
|
||||
}
|
||||
|
||||
public inline function distanceTo(p: Vec4): FastFloat {
|
||||
return Math.sqrt((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y) + (p.z - z) * (p.z - z));
|
||||
}
|
||||
|
||||
public inline function reflect(n: Vec4): Vec4 {
|
||||
var d = 2 * this.dot(n);
|
||||
x = x - d * n.x;
|
||||
y = y - d * n.y;
|
||||
z = z - d * n.z;
|
||||
return this;
|
||||
}
|
||||
|
||||
public inline function clamp(min: FastFloat, max: FastFloat): Vec4 {
|
||||
var l = length();
|
||||
if (l < min) normalize().mult(min);
|
||||
else if (l > max) normalize().mult(max);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static inline function xAxis(): Vec4 {
|
||||
return new Vec4(1.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
public static inline function yAxis(): Vec4 {
|
||||
return new Vec4(0.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
public static inline function zAxis(): Vec4 {
|
||||
return new Vec4(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
public function toString(): String {
|
||||
return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")";
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user