Files
coven/core/transform.jai
2024-10-11 22:21:32 +02:00

173 lines
5.0 KiB
Plaintext

#import "Math";
Transform_Identity : Transform : .{ .{0,0,0}, .{0,0,0,1}, .{1,1,1}, Matrix4_Identity, Matrix4_Identity, false };
Transform :: struct {
position: Vector3;
orientation: Quaternion;
scale : Vector3;
model_matrix: Matrix4 = Matrix4_Identity; @DontSerialize
world_matrix: Matrix4; @DontSerialize
dirty: bool; @DontSerialize
}
create_identity_transform :: () -> Transform {
transform : Transform;
transform.position = .{};
transform.orientation = .{0,0,0,1};
transform.scale = .{1,1,1};
transform.model_matrix = Matrix4_Identity;
update_matrix(*transform);
return transform;
}
make_matrix :: (position: Vector3, orientation: Quaternion, scale: Vector3) -> Matrix4 {
trans_mat := make_translation_matrix4(position);
scale_mat := make_scale_matrix4(scale);
rot_mat := rotation_matrix(Matrix4, orientation);
return trans_mat * rot_mat * scale_mat;
}
create_transform :: (position: Vector3, orientation: Quaternion, scale: Vector3) -> Transform {
transform : Transform;
transform.position = position;
transform.orientation = orientation;
transform.scale = scale;
transform.model_matrix = make_matrix(position, orientation, scale);
return transform;
}
update_matrix :: (transform: *Transform) {
transform.model_matrix = make_matrix(transform.position, transform.orientation, transform.scale);
transform.dirty = true;
}
set_position :: (transform: *Transform, position: Vector3, calculate_matrix: bool = true) {
transform.position = position;
if calculate_matrix update_matrix(transform);
}
set_position :: (transform: *Transform, x: float, y: float, z: float, calculate_matrix: bool = true) {
transform.position.x = x;
transform.position.y = y;
transform.position.z = z;
if calculate_matrix update_matrix(transform);
}
translate :: (transform: *Transform, translation: Vector3, calculate_matrix: bool = true) {
transform.position += translation;
if calculate_matrix update_matrix(transform);
}
euler_to_quaternion :: (yaw: float, pitch: float, roll: float) -> Quaternion {
cy := cos(yaw * 0.5);
sy := sin(yaw * 0.5);
cp := cos(pitch * 0.5);
sp := sin(pitch * 0.5);
cr := cos(roll * 0.5);
sr := sin(roll * 0.5);
q: Quaternion;
q.w = cr * cp * cy + sr * sp * sy;
q.x = sr * cp * cy - cr * sp * sy;
q.y = cr * sp * cy + sr * cp * sy;
q.z = cr * cp * sy - sr * sp * cy;
return q;
}
sign :: (val: $T) -> T {
if val < 0 return -1.0;
if val > 0 return 1.0;
return 0.0;
}
quaternion_to_euler_v3 :: (q: Quaternion) -> Vector3 {
yaw, pitch, roll := quaternion_to_euler(q);
v : Vector3 = ---;
v.x = yaw;
v.y = pitch;
v.z = roll;
return v;
}
quaternion_to_euler :: (q: Quaternion) -> yaw: float, pitch: float, roll: float {
yaw: float;
pitch: float;
roll: float;
sinr_cosp := 2.0 * (q.w * q.x + q.y * q.z);
cosr_cosp := 1.0 - 2.0 * (q.x * q.x + q.y * q.y);
roll = atan2(sinr_cosp, cosr_cosp);
// pitch (y-axis rotation)
sinp := 2.0 * (q.w * q.y - q.z * q.x);
if abs(sinp) >= 1.0
pitch = sign(sinp) * (PI / 2); // use 90 degrees if out of range
else
pitch = asin(sinp);
// yaw (z-axis rotation)
siny_cosp := 2.0 * (q.w * q.z + q.x * q.y);
cosy_cosp := 1.0 - 2.0 * (q.y * q.y + q.z * q.z);
yaw = atan2(siny_cosp, cosy_cosp);
return yaw, pitch, roll;
}
set_rotation :: (transform: *Transform, orientation: Quaternion, calculate_matrix: bool = true) {
transform.orientation = orientation;
if calculate_matrix update_matrix(transform);
}
set_rotation :: (transform: *Transform, euler_angles: Vector3, calculate_matrix: bool = true) {
orientation := euler_to_quaternion(degrees_to_radians(euler_angles.y), degrees_to_radians(euler_angles.x), degrees_to_radians(euler_angles.z));
transform.orientation = orientation;
if calculate_matrix update_matrix(transform);
}
set_scale :: (transform: *Transform, scale: Vector3, calculate_matrix: bool = true) {
transform.scale = scale;
if calculate_matrix update_matrix(transform);
}
set_scale :: (transform: *Transform, scale: float, calculate_matrix: bool = true) {
transform.scale = .{scale, scale, scale};
if calculate_matrix update_matrix(transform);
}
get_forward :: (transform: Transform) -> Vector3 {
v := rotation_matrix(Matrix4, transform.orientation) * Vector4.{0,0,1,0};
return .{v.x, v.y, v.z};
}
get_right :: (transform: Transform) -> Vector3 {
v := rotation_matrix(Matrix4, transform.orientation) * Vector4.{1,0,0,0};
return .{v.x, v.y, v.z};
}
get_up :: (transform: Transform) -> Vector3 {
v := rotation_matrix(Matrix4, transform.orientation) * Vector4.{0,1,0,0};
return .{v.x, v.y, v.z};
}
get_position :: (transform: Transform) -> Vector3 {
return .{transform.model_matrix._14, transform.model_matrix._24, transform.model_matrix._34};
}
get_rotation :: (transform: Transform) -> Vector3 {
return .{transform.model_matrix._14, transform.model_matrix._24, transform.model_matrix._34};
}