Implemented transformations

This commit is contained in:
Lorenzo Torres 2025-08-06 15:32:32 +02:00
parent 00d51fc970
commit 6b948f6718
6 changed files with 250 additions and 30 deletions

View file

@ -3,23 +3,60 @@ pub const tan = std.math.tan;
pub const cos = std.math.cos;
pub const sin = std.math.sin;
pub const rad = std.math.degreesToRadians;
pub const sqrt = std.math.sqrt;
pub const Axis = struct {
pub const x: [3]f32 = .{1.0, 0.0, 0.0};
pub const y: [3]f32 = .{0.0, 1.0, 0.0};
pub const z: [3]f32 = .{0.0, 0.0, 1.0};
};
pub const Transform = struct {
translation: Matrix,
scale: Matrix,
rotation: Quaternion,
pub fn init(position: [3]f32, scale: [3]f32, rotation: [3]f32) Transform {
var translation = Matrix.identity();
translation.translate(position);
return .{
.translation = translation,
.rotation = Quaternion.fromEulerAngles(rotation),
.scale = Matrix.scale(scale),
};
}
pub fn translate(self: *Transform, delta: [3]f32) void {
self.translation.translate(delta);
}
pub fn rotate(self: *Transform, angle: f32, axis: [3]f32) void {
const delta = Quaternion.fromAxisAngle(axis, angle);
self.rotation = self.rotation.mul(delta);
self.rotation = self.rotation.normalize();
}
};
pub const Matrix = struct {
rows: [4]@Vector(4, f32),
rows: [4][4]f32,
pub fn lookAt(eye: @Vector(3, f32), target: @Vector(3, f32), arbitrary_up: @Vector(3, f32)) Matrix {
const forward = normalize(target - eye);
const right = normalize(cross(forward, arbitrary_up));
pub fn lookAt(eye: [3]f32, target: [3]f32, arbitrary_up: [3]f32) Matrix {
const t: @Vector(3, f32) = target;
const e: @Vector(3, f32) = eye;
const u: @Vector(3, f32) = arbitrary_up;
const forward = normalize(t - e);
const right = normalize(cross(forward, u));
const up = cross(right, forward);
const view = [_]@Vector(4, f32){
@Vector(4, f32){ right[0], up[0], -forward[0], 0.0 },
@Vector(4, f32){ right[1], up[1], -forward[1], 0.0 },
@Vector(4, f32){ right[2], up[2], -forward[2], 0.0 },
@Vector(4, f32){ -dot(eye, right), -dot(eye, up), -dot(eye, forward), 1.0 },
const view = [4][4]f32{
[4]f32{ right[0], up[0], -forward[0], 0.0 },
[4]f32{ right[1], up[1], -forward[1], 0.0 },
[4]f32{ right[2], up[2], -forward[2], 0.0 },
[4]f32{ -dot(e, right), -dot(e, up), -dot(e, forward), 1.0 },
};
return Matrix{
return .{
.rows = view,
};
}
@ -31,28 +68,161 @@ pub const Matrix = struct {
const a = near / (far - near);
const b = far * a;
const projection = [_]@Vector(4, f32){
@Vector(4, f32){ x, 0.0, 0.0, 0.0 },
@Vector(4, f32){ 0.0, y, 0.0, 0.0 },
@Vector(4, f32){ 0.0, 0.0, a, b },
@Vector(4, f32){ 0.0, 0.0, 1.0, 0.0 },
const projection = [4][4]f32{
[4]f32{ x, 0.0, 0.0, 0.0 },
[4]f32{ 0.0, y, 0.0, 0.0 },
[4]f32{ 0.0, 0.0, a, b },
[4]f32{ 0.0, 0.0, 1.0, 0.0 },
};
return Matrix{
return .{
.rows = projection,
};
}
pub fn identity() Matrix {
const view = [_]@Vector(4, f32){
@Vector(4, f32){ 1.0, 0.0, 0.0, 0.0 },
@Vector(4, f32){ 0.0, 1.0, 0.0, 0.0 },
@Vector(4, f32){ 0.0, 0.0, 1.0, 0.0 },
@Vector(4, f32){ 0.0, 0.0, 0.0, 1.0 },
pub inline fn identity() Matrix {
return .{
.rows = .{
[4]f32{ 1.0, 0.0, 0.0, 0.0 },
[4]f32{ 0.0, 1.0, 0.0, 0.0 },
[4]f32{ 0.0, 0.0, 1.0, 0.0 },
[4]f32{ 0.0, 0.0, 0.0, 1.0 },
},
};
}
pub fn mul(a: Matrix, b: Matrix) Matrix {
var result = [4][4]f32{
[4]f32{ 0.0, 0.0, 0.0, 0.0 },
[4]f32{ 0.0, 0.0, 0.0, 0.0 },
[4]f32{ 0.0, 0.0, 0.0, 0.0 },
[4]f32{ 0.0, 0.0, 0.0, 0.0 },
};
return Matrix{
.rows = view,
for (0..4) |i| {
for (0..4) |j| {
for (0..4) |k| {
result[i][j] += a.rows[i][k] * b.rows[k][j];
}
}
}
return .{
.rows = result,
};
}
pub inline fn translate(a: *Matrix, pos: [3]f32) void {
a.rows[3][0] += pos[0];
a.rows[3][1] += pos[1];
a.rows[3][2] += pos[2];
}
pub inline fn scale(s: [3]f32) Matrix {
return .{
.rows = [4][4]f32{
[4]f32{ s[0], 0.0, 0.0, 0.0 },
[4]f32{ 0.0, s[1], 0.0, 0.0 },
[4]f32{ 0.0, 0.0, s[2], 0.0 },
[4]f32{ 0.0, 0.0, 0.0, 1.0 },
},
};
}
pub fn transform(pos: [3]f32, s: [3]f32) Matrix {
var translation = Matrix.identity();
translation.translate(pos);
return translation.mul(Matrix.scale(s));
}
};
const Quaternion = struct {
w: f32,
x: f32,
y: f32,
z: f32,
pub const identity: Quaternion = .{ .w = 1.0, .x = 0.0, .y = 0.0, .z = 0.0 };
pub fn fromAxisAngle(axis: [3]f32, angle: f32) Quaternion {
const half_angle = angle / 2.0;
const s = sin(half_angle);
return .{
.w = cos(half_angle),
.x = axis[0] * s,
.y = axis[1] * s,
.z = axis[3] * s,
};
}
fn fromEulerAngles(rotation: [3]f32) Quaternion {
const pitch = rotation[0];
const yaw = rotation[1];
const roll = rotation[2];
const half_pitch = pitch / 2.0;
const half_yaw = yaw / 2.0;
const half_roll = roll / 2.0;
const sin_pitch = sin(half_pitch);
const cos_pitch = cos(half_pitch);
const sin_yaw = sin(half_yaw);
const cos_yaw = cos(half_yaw);
const sin_roll = sin(half_roll);
const cos_roll = cos(half_roll);
return .{
.w = cos_yaw * cos_pitch * cos_roll + sin_yaw * sin_pitch * sin_roll,
.x = cos_yaw * sin_pitch * cos_roll + sin_yaw * cos_pitch * sin_roll,
.y = sin_yaw * cos_pitch * cos_roll - cos_yaw * sin_pitch * sin_roll,
.z = cos_yaw * cos_pitch * sin_roll - sin_yaw * sin_pitch * cos_roll,
};
}
inline fn mul(a: Quaternion, b: Quaternion) Quaternion {
return .{
.w = a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
.x = a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
.y = a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
.z = a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
};
}
fn normalize(q: Quaternion) Quaternion {
const mag = sqrt(q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z);
return Quaternion{
.w = q.w / mag,
.x = q.x / mag,
.y = q.y / mag,
.z = q.z / mag,
};
}
fn matrix(q: Quaternion) Matrix {
const x2 = q.x + q.x;
const y2 = q.y + q.y;
const z2 = q.z + q.z;
const xx = q.x * x2;
const yy = q.y * y2;
const zz = q.z * z2;
const xy = q.x * y2;
const xz = q.x * z2;
const yz = q.y * z2;
const wx = q.w * x2;
const wy = q.w * y2;
const wz = q.w * z2;
return .{
.rows = .{
.{ 1.0 - (yy + zz), xy - wz, xz + wy, 0.0 },
.{ xy + wz, 1.0 - (xx + zz), yz - wx, 0.0 },
.{ xz - wy, yz + wx, 1.0 - (xx + yy), 0.0 },
.{ 0.0, 0.0, 0.0, 1.0 },
}
};
}
};