|
package iron.math; |
|
|
|
import haxe.ds.Vector; |
|
import kha.FastFloat; |
|
import hotmem.F32; |
|
|
|
#if hotmem_vectors |
|
import hotmem.F32Array; |
|
#else |
|
#if js |
|
private typedef HotVec4Data = { |
|
x:FastFloat, |
|
y:FastFloat, |
|
z:FastFloat, |
|
w:FastFloat |
|
} |
|
#else |
|
private class HotVec4Data { |
|
public var x:FastFloat; |
|
public var y:FastFloat; |
|
public var z:FastFloat; |
|
public var w:FastFloat; |
|
|
|
public function new(x, y, z, w) { |
|
this.x = x; |
|
this.y = y; |
|
this.z = z; |
|
this.w = w; |
|
} |
|
} |
|
#end |
|
#end |
|
|
|
#if hotmem_vectors |
|
abstract HotVec4(F32Array) { |
|
#else |
|
abstract HotVec4(HotVec4Data) { |
|
#end |
|
|
|
public var x(get, set):F32; |
|
public var y(get, set):F32; |
|
public var z(get, set):F32; |
|
public var w(get, set):F32; |
|
public var length(get, set):F32; |
|
|
|
public inline function new(x:F32 = 0.0, y:F32 = 0.0, z:F32 = 0.0, w:F32 = 1.0) { |
|
#if hotmem_vectors |
|
this = new F32Array(4); |
|
#else |
|
#if js |
|
this = { |
|
x: x, |
|
y: y, |
|
z: z, |
|
w: w, |
|
} |
|
#else |
|
this = new HotVec4Data(x, y, z, w); |
|
#end |
|
#end |
|
} |
|
|
|
public inline function set(x:F32, y:F32, z:F32, w:F32 = 1.0):HotVec4 { |
|
set_x(x); |
|
set_y(y); |
|
set_z(z); |
|
set_w(w); |
|
return cast this; |
|
} |
|
|
|
public inline function setFrom(v:HotVec4):HotVec4 { |
|
x = v.x; |
|
y = v.y; |
|
z = v.z; |
|
w = v.w; |
|
return cast this; |
|
} |
|
|
|
public inline function clone():HotVec4 { |
|
return new HotVec4(x, y, z, w); |
|
} |
|
|
|
// |
|
// Getters and Setters |
|
// |
|
|
|
#if hotmem_vectors |
|
inline function get_x() { return this[0]; } |
|
inline function set_x(x:F32) { this[0] = x; return this[0]; } |
|
|
|
inline function get_y() { return this[1]; } |
|
inline function set_y(y:F32) { this[1] = y; return this[1]; } |
|
|
|
inline function get_z() { return this[2]; } |
|
inline function set_z(z:F32) { this[2] = z; return this[2]; } |
|
|
|
inline function get_w() { return this[3]; } |
|
inline function set_w(w:F32) { this[3] = w; return this[3]; } |
|
|
|
#else |
|
inline function get_x() { return this.x; } |
|
inline function set_x(x:F32) { this.x = x; return this.x; } |
|
|
|
inline function get_y() { return this.y; } |
|
inline function set_y(y:F32) { this.y = y; return this.y; } |
|
|
|
inline function get_z() { return this.z; } |
|
inline function set_z(z:F32) { this.z = z; return this.z; } |
|
|
|
inline function get_w() { return this.w; } |
|
inline function set_w(w:F32) { this.w = w; return this.w; } |
|
#end |
|
|
|
inline function get_length():F32 { |
|
return Math.sqrt(x* x + y * y + z * z); |
|
} |
|
|
|
inline function set_length(length:F32):F32 { |
|
var currentLength = get_length(); |
|
if (currentLength > 0.0) { |
|
var factor = length / currentLength; |
|
x *= factor; |
|
y *= factor; |
|
z *= factor; |
|
} |
|
return length; |
|
} |
|
|
|
// |
|
// Operator Overloads |
|
// |
|
|
|
@:op(a + b) |
|
private inline function _add(b:HotVec4):HotVec4 { |
|
return new HotVec4( |
|
x + b.x, |
|
y + b.y, |
|
z + b.z |
|
); |
|
} |
|
|
|
@:op(a += b) |
|
public inline function add(b:HotVec4):HotVec4 { |
|
x += b.x; |
|
y += b.y; |
|
z += b.z; |
|
return cast this; |
|
} |
|
|
|
@:op(a + b) |
|
private inline function _addFloat(b:F32):HotVec4 { |
|
return new HotVec4( |
|
x + b, |
|
y + b, |
|
z + b |
|
); |
|
} |
|
|
|
@:op(a += b) |
|
private inline function _addEqualsFloat(b:F32):HotVec4 { |
|
x += b; |
|
y += b; |
|
z += b; |
|
return cast this; |
|
} |
|
|
|
@:op(a - b) |
|
private inline function _sub(b:HotVec4):HotVec4 { |
|
return new HotVec4( |
|
x - b.x, |
|
y - b.y, |
|
z - b.z |
|
); |
|
} |
|
|
|
@:op(a -= b) |
|
public inline function sub(b:HotVec4):HotVec4 { |
|
x -= b.x; |
|
y -= b.y; |
|
z -= b.z; |
|
return cast this; |
|
} |
|
|
|
@:op(a - b) |
|
private inline function _subFloat(b:F32):HotVec4 { |
|
return new HotVec4( |
|
x - b, |
|
y - b, |
|
z - b |
|
); |
|
} |
|
|
|
@:op(a -= b) |
|
private inline function _subEqualsFloat(b:F32):HotVec4 { |
|
x -= b; |
|
y -= b; |
|
z -= b; |
|
return cast this; |
|
} |
|
|
|
@:op(a * b) |
|
private inline function _mult(b:F32):HotVec4 { |
|
return new HotVec4( |
|
x * b, |
|
y * b, |
|
z * b |
|
); |
|
} |
|
|
|
@:op(a *= b) |
|
public inline function mult(b:F32):HotVec4 { |
|
x *= b; |
|
y *= b; |
|
x *= b; |
|
return cast this; |
|
} |
|
|
|
@:op(a / b) |
|
private inline function _div(b:F32):HotVec4 { |
|
return new HotVec4( |
|
x / b, |
|
y / b, |
|
z / b |
|
); |
|
} |
|
|
|
@:op(a /= b) |
|
public inline function div(b:F32):HotVec4 { |
|
x /= b; |
|
y /= b; |
|
x /= b; |
|
return cast this; |
|
} |
|
|
|
@:op(a < b) |
|
private inline function _ltVec(b:HotVec4) { |
|
return length < b.length; |
|
} |
|
|
|
@:op(a < b) |
|
private inline function _ltFloat(b:F32) { |
|
return length < b; |
|
} |
|
|
|
@:op(a > b) |
|
private inline function _gtVec(b:HotVec4) { |
|
return length > b.length; |
|
} |
|
|
|
@:op(a > b) |
|
private inline function _gtFloat(b:F32) { |
|
return length > b; |
|
} |
|
|
|
@:op(a == b) |
|
public inline function equals(v:HotVec4) { |
|
return x == v.x && y == v.y && z == v.z; |
|
} |
|
|
|
// |
|
// Mutator Methods |
|
// |
|
|
|
public inline function normalize():HotVec4 { |
|
length = 1; |
|
return cast this; |
|
} |
|
|
|
public inline function dot(v:HotVec4):FastFloat { |
|
return x * v.x + y * v.y + z * v.z; |
|
} |
|
|
|
public inline function cross(v:HotVec4):HotVec4 { |
|
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 cast this; |
|
} |
|
|
|
public inline function crossvecs(a:HotVec4, b:HotVec4):HotVec4 { |
|
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 cast this; |
|
} |
|
|
|
inline public function addf(x:FastFloat, y:FastFloat, z:FastFloat):Vec4 { |
|
set_x(get_x() + x); |
|
set_y(get_y() + y); |
|
set_z(get_z() + z); |
|
return cast this; |
|
} |
|
|
|
public inline function addvecs(a:HotVec4, b:HotVec4):HotVec4 { |
|
x = a.x + b.x; |
|
y = a.y + b.y; |
|
z = a.z + b.z; |
|
return cast this; |
|
} |
|
|
|
public inline function subvecs(a:HotVec4, b:HotVec4):HotVec4 { |
|
x = a.x - b.x; |
|
y = a.y - b.y; |
|
z = a.z - b.z; |
|
return cast this; |
|
} |
|
|
|
public inline function lerp(from:HotVec4, to:HotVec4, s:FastFloat):HotVec4 { |
|
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 cast this; |
|
} |
|
|
|
public inline function applyproj(m:Mat4):HotVec4 { |
|
var x = get_x(); var y = get_y(); var z = get_z(); |
|
var d = 1.0 / (m._03 * x + m._13 * y + m._23 * z + m._33); // Perspective divide |
|
set_x((m._00 * x + m._10 * y + m._20 * z + m._30) * d); |
|
set_y((m._01 * x + m._11 * y + m._21 * z + m._31) * d); |
|
set_z((m._02 * x + m._12 * y + m._22 * z + m._32) * d); |
|
return cast this; |
|
} |
|
|
|
public inline function applymat(m:Mat4):HotVec4 { |
|
var x = get_x(); var y = get_y(); var z = get_z(); |
|
set_x(m._00 * x + m._10 * y + m._20 * z + m._30); |
|
set_y(m._01 * x + m._11 * y + m._21 * z + m._31); |
|
set_z(m._02 * x + m._12 * y + m._22 * z + m._32); |
|
return cast this; |
|
} |
|
|
|
public inline function applymat4(m:Mat4):HotVec4 { |
|
var x = get_x(); var y = get_y(); var z = get_z(); var w = get_w(); |
|
set_x(m._00 * x + m._10 * y + m._20 * z + m._30 * w); |
|
set_y(m._01 * x + m._11 * y + m._21 * z + m._31 * w); |
|
set_z(m._02 * x + m._12 * y + m._22 * z + m._32 * w); |
|
set_w(m._03 * x + m._13 * y + m._23 * z + m._33 * w); |
|
return cast this; |
|
} |
|
|
|
public inline function applyAxisAngle(axis:Vec4, angle:FastFloat):HotVec4 { |
|
var quat = new Quat(); |
|
quat.fromAxisAngle(axis, angle); |
|
return applyQuat(quat); |
|
} |
|
|
|
public inline function applyQuat(q:Quat):HotVec4 { |
|
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 cast this; |
|
} |
|
|
|
public inline function almostEquals(v:HotVec4, prec:FastFloat):Bool { |
|
return Math.abs(x - v.x) < prec && Math.abs(y - v.y) < prec && Math.abs(z - v.z) < prec; |
|
} |
|
|
|
public static inline function distance(v1:HotVec4, v2:HotVec4):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:HotVec4):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:HotVec4):HotVec4 { |
|
var d = 2 * dot(n); |
|
x = x - d * n.x; |
|
y = y - d * n.y; |
|
z = z - d * n.z; |
|
return cast this; |
|
} |
|
|
|
public inline function clamp(min:FastFloat, max:FastFloat):HotVec4 { |
|
var l = length; |
|
if (l < min) normalize().mult(min); |
|
else if (l > max) normalize().mult(max); |
|
return cast this; |
|
} |
|
|
|
public static inline function xAxis():HotVec4 { return new HotVec4(1.0, 0.0, 0.0); } |
|
public static inline function yAxis():HotVec4 { return new HotVec4(0.0, 1.0, 0.0); } |
|
public static inline function zAxis():HotVec4 { return new HotVec4(0.0, 0.0, 1.0); } |
|
|
|
public function toString():String { |
|
return "(" + x + ", " + y + ", " + z + ", " + w + ")"; |
|
} |
|
} |