zigsdof/vec3/src/vec3.zig

211 lines
6.3 KiB
Zig

const std = @import("std");
pub fn Vec3(comptime T: type) type {
return struct { x: T, y: T, z: T };
}
pub fn vec3Add(comptime T: type, a: Vec3(T), b: Vec3(T)) Vec3(T) {
return .{
.x = a.x + b.x,
.y = a.y + b.y,
.z = a.z + b.z,
};
}
pub fn vec3Sub(comptime T: type, a: Vec3(T), b: Vec3(T)) Vec3(T) {
return .{
.x = a.x - b.x,
.y = a.y - b.y,
.z = a.z - b.z,
};
}
pub fn vec3Dot(comptime T: type, a: Vec3(T), b: Vec3(T)) T {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
pub fn vec3Cross(comptime T: type, a: Vec3(T), b: Vec3(T)) Vec3(T) {
const x = a.y * b.z - a.z * b.y;
const y = a.z * b.x - a.x * b.z;
const z = a.x * b.y - a.y * b.x;
return .{ .x = x, .y = y, .z = z };
}
pub fn Mat3(comptime T: type) type {
return struct {
row1: Vec3(T),
row2: Vec3(T),
row3: Vec3(T),
};
}
pub fn mat3Add(comptime T: type, a: Mat3(T), b: Mat3(T)) Mat3(T) {
return .{
.row1 = vec3Add(T, a.row1, b.row1),
.row2 = vec3Add(T, a.row2, b.row2),
.row3 = vec3Add(T, a.row3, b.row3),
};
}
pub fn mat3Sub(comptime T: type, a: Mat3(T), b: Mat3(T)) Mat3(T) {
return .{
.row1 = vec3Sub(T, a.row1, b.row1),
.row2 = vec3Sub(T, a.row2, b.row2),
.row3 = vec3Sub(T, a.row3, b.row3),
};
}
pub fn mat3Mul(comptime T: type, a: Mat3(T), b: Mat3(T)) Mat3(T) {
const c_row1: Vec3(T) = .{
.x = a.row1.x * b.row1.x + a.row1.y * b.row2.x + a.row1.z * b.row3.x,
.y = a.row1.x * b.row1.y + a.row1.y * b.row2.y + a.row1.z * b.row3.y,
.z = a.row1.x * b.row1.z + a.row1.y * b.row2.z + a.row1.z * b.row3.z,
};
const c_row2: Vec3(T) = .{
.x = a.row2.x * b.row1.x + a.row2.y * b.row2.x + a.row2.z * b.row3.x,
.y = a.row2.x * b.row1.y + a.row2.y * b.row2.y + a.row2.z * b.row3.y,
.z = a.row2.x * b.row1.z + a.row2.y * b.row2.z + a.row2.z * b.row3.z,
};
const c_row3: Vec3(T) = .{
.x = a.row3.x * b.row1.x + a.row3.y * b.row2.x + a.row3.z * b.row3.x,
.y = a.row3.x * b.row1.y + a.row3.y * b.row2.y + a.row3.z * b.row3.y,
.z = a.row3.x * b.row1.z + a.row3.y * b.row2.z + a.row3.z * b.row3.z,
};
return .{ .row1 = c_row1, .row2 = c_row2, .row3 = c_row3 };
}
pub fn vec3MulMat3(comptime T: type, a: Vec3(T), b: Mat3(T)) Vec3(T) {
return .{
.x = a.x * b.row1.x + a.y * b.row2.x + a.z * b.row3.x,
.y = a.x * b.row1.y + a.y * b.row2.y + a.z * b.row3.y,
.z = a.x * b.row1.z + a.y * b.row2.z + a.z * b.row3.z,
};
}
test "vec3Add adds properly" {
const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 };
const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 };
const c = vec3Add(i8, a, b);
try std.testing.expect(c.x == 4);
try std.testing.expect(c.y == 3);
try std.testing.expect(c.z == 3);
}
test "vec3Sub subs properly" {
const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 };
const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 };
const c = vec3Sub(i8, a, b);
try std.testing.expect(c.x == -2);
try std.testing.expect(c.y == 1);
try std.testing.expect(c.z == 3);
}
test "vec3Dot dots properly" {
const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 };
const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 };
try std.testing.expect(vec3Dot(i8, a, b) == 5);
}
test "vec3Cross crosses properly" {
const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 };
const b: Vec3(i8) = .{ .x = 3, .y = 1, .z = 0 };
const c = vec3Cross(i8, a, b);
try std.testing.expect(c.x == -3);
try std.testing.expect(c.y == 9);
try std.testing.expect(c.z == -5);
}
test "Mat3 add works" {
const a: Mat3(i8) = .{
.row1 = .{ .x = 1, .y = 2, .z = 3 },
.row2 = .{ .x = 0, .y = 1, .z = 5 },
.row3 = .{ .x = 0, .y = 0, .z = 9 },
};
const b: Mat3(i8) = .{
.row1 = .{ .x = 0, .y = 1, .z = 0 },
.row2 = .{ .x = 0, .y = 1, .z = 1 },
.row3 = .{ .x = 0, .y = 0, .z = 1 },
};
const c = mat3Add(i8, a, b);
try std.testing.expect(c.row1.x == 1);
try std.testing.expect(c.row1.y == 3);
try std.testing.expect(c.row1.z == 3);
try std.testing.expect(c.row2.x == 0);
try std.testing.expect(c.row2.y == 2);
try std.testing.expect(c.row2.z == 6);
try std.testing.expect(c.row3.x == 0);
try std.testing.expect(c.row3.y == 0);
try std.testing.expect(c.row3.z == 10);
}
test "Mat3 sub works" {
const a: Mat3(i8) = .{
.row1 = .{ .x = 1, .y = 2, .z = 3 },
.row2 = .{ .x = 0, .y = 1, .z = 5 },
.row3 = .{ .x = 0, .y = 0, .z = 9 },
};
const b: Mat3(i8) = .{
.row1 = .{ .x = 0, .y = 1, .z = 0 },
.row2 = .{ .x = 0, .y = 1, .z = 1 },
.row3 = .{ .x = 0, .y = 0, .z = 1 },
};
const c = mat3Sub(i8, a, b);
try std.testing.expect(c.row1.x == 1);
try std.testing.expect(c.row1.y == 1);
try std.testing.expect(c.row1.z == 3);
try std.testing.expect(c.row2.x == 0);
try std.testing.expect(c.row2.y == 0);
try std.testing.expect(c.row2.z == 4);
try std.testing.expect(c.row3.x == 0);
try std.testing.expect(c.row3.y == 0);
try std.testing.expect(c.row3.z == 8);
}
test "Mat3 mul works" {
const a: Mat3(i8) = .{
.row1 = .{ .x = 1, .y = 2, .z = 3 },
.row2 = .{ .x = 0, .y = 1, .z = 5 },
.row3 = .{ .x = 0, .y = 0, .z = 9 },
};
const b: Mat3(i8) = .{
.row1 = .{ .x = 0, .y = 1, .z = 0 },
.row2 = .{ .x = 0, .y = 1, .z = 1 },
.row3 = .{ .x = 0, .y = 0, .z = 1 },
};
const c = mat3Mul(i8, a, b);
try std.testing.expect(c.row1.x == 0);
try std.testing.expect(c.row1.y == 3);
try std.testing.expect(c.row1.z == 5);
try std.testing.expect(c.row2.x == 0);
try std.testing.expect(c.row2.y == 1);
try std.testing.expect(c.row2.z == 6);
try std.testing.expect(c.row3.x == 0);
try std.testing.expect(c.row3.y == 0);
try std.testing.expect(c.row3.z == 9);
}
test "vec3 mul mat3 works" {
const a: Vec3(i8) = .{ .x = 1, .y = 2, .z = 3 };
const b: Mat3(i8) = .{
.row1 = .{ .x = 0, .y = 1, .z = 0 },
.row2 = .{ .x = 0, .y = 1, .z = 1 },
.row3 = .{ .x = 0, .y = 0, .z = 1 },
};
const c = vec3MulMat3(i8, a, b);
try std.testing.expect(c.x == 0);
try std.testing.expect(c.y == 3);
try std.testing.expect(c.z == 5);
}