177 lines
5.1 KiB
Plaintext
177 lines
5.1 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 :: (value: Vector3) -> Quaternion {
|
|
return euler_to_quaternion(value.x, value.y, value.z);
|
|
}
|
|
|
|
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};
|
|
}
|
|
|