604 lines
20 KiB
Zig
604 lines
20 KiB
Zig
const std = @import("std");
|
|
|
|
const mach = @import("../main.zig");
|
|
const testing = mach.testing;
|
|
const math = mach.math;
|
|
|
|
pub fn Vec(comptime n_value: usize, comptime Scalar: type) type {
|
|
return extern struct {
|
|
v: Vector,
|
|
|
|
/// The vector dimension size, e.g. Vec3.n == 3
|
|
pub const n = n_value;
|
|
|
|
/// The scalar type of this vector, e.g. Vec3.T == f32
|
|
pub const T = Scalar;
|
|
|
|
// The underlying @Vector type
|
|
pub const Vector = @Vector(n_value, Scalar);
|
|
|
|
const VecN = @This();
|
|
|
|
pub usingnamespace switch (VecN.n) {
|
|
inline 2 => struct {
|
|
pub inline fn init(xs: Scalar, ys: Scalar) VecN {
|
|
return .{ .v = .{ xs, ys } };
|
|
}
|
|
pub inline fn x(v: *const VecN) Scalar {
|
|
return v.v[0];
|
|
}
|
|
pub inline fn y(v: *const VecN) Scalar {
|
|
return v.v[1];
|
|
}
|
|
},
|
|
inline 3 => struct {
|
|
pub inline fn init(xs: Scalar, ys: Scalar, zs: Scalar) VecN {
|
|
return .{ .v = .{ xs, ys, zs } };
|
|
}
|
|
pub inline fn x(v: *const VecN) Scalar {
|
|
return v.v[0];
|
|
}
|
|
pub inline fn y(v: *const VecN) Scalar {
|
|
return v.v[1];
|
|
}
|
|
pub inline fn z(v: *const VecN) Scalar {
|
|
return v.v[2];
|
|
}
|
|
|
|
// TODO(math): come up with a better strategy for swizzling?
|
|
pub inline fn yzw(v: *const VecN) VecN {
|
|
return VecN.init(v.y(), v.z(), v.w());
|
|
}
|
|
pub inline fn zxy(v: *const VecN) VecN {
|
|
return VecN.init(v.z(), v.x(), v.y());
|
|
}
|
|
|
|
/// Calculates the cross product between vector a and b. This can be done only in 3D
|
|
/// and required inputs are Vec3.
|
|
pub inline fn cross(a: *const VecN, b: *const VecN) VecN {
|
|
// https://gamemath.com/book/vectors.html#cross_product
|
|
const s1 = a.yzx().mul(b.zxy());
|
|
const s2 = a.zxy().mul(b.yzx());
|
|
return s1.sub(s2);
|
|
}
|
|
},
|
|
inline 4 => struct {
|
|
pub inline fn init(xs: Scalar, ys: Scalar, zs: Scalar, ws: Scalar) VecN {
|
|
return .{ .v = .{ xs, ys, zs, ws } };
|
|
}
|
|
pub inline fn x(v: *const VecN) Scalar {
|
|
return v.v[0];
|
|
}
|
|
pub inline fn y(v: *const VecN) Scalar {
|
|
return v.v[1];
|
|
}
|
|
pub inline fn z(v: *const VecN) Scalar {
|
|
return v.v[2];
|
|
}
|
|
pub inline fn w(v: *const VecN) Scalar {
|
|
return v.v[3];
|
|
}
|
|
},
|
|
else => @compileError("Expected Vec2, Vec3, Vec4, found '" ++ @typeName(VecN) ++ "'"),
|
|
};
|
|
|
|
/// Element-wise addition
|
|
pub inline fn add(a: *const VecN, b: *const VecN) VecN {
|
|
return .{ .v = a.v + b.v };
|
|
}
|
|
|
|
/// Element-wise subtraction
|
|
pub inline fn sub(a: *const VecN, b: *const VecN) VecN {
|
|
return .{ .v = a.v - b.v };
|
|
}
|
|
|
|
/// Element-wise division
|
|
pub inline fn div(a: *const VecN, b: *const VecN) VecN {
|
|
return .{ .v = a.v / b.v };
|
|
}
|
|
|
|
/// Element-wise multiplication.
|
|
///
|
|
/// See also .cross()
|
|
pub inline fn mul(a: *const VecN, b: *const VecN) VecN {
|
|
return .{ .v = a.v * b.v };
|
|
}
|
|
|
|
/// Scalar addition
|
|
pub inline fn addScalar(a: *const VecN, s: Scalar) VecN {
|
|
return .{ .v = a.v + VecN.splat(s).v };
|
|
}
|
|
|
|
/// Scalar subtraction
|
|
pub inline fn subScalar(a: *const VecN, s: Scalar) VecN {
|
|
return .{ .v = a.v - VecN.splat(s).v };
|
|
}
|
|
|
|
/// Scalar division
|
|
pub inline fn divScalar(a: *const VecN, s: Scalar) VecN {
|
|
return .{ .v = a.v / VecN.splat(s).v };
|
|
}
|
|
|
|
/// Scalar multiplication.
|
|
///
|
|
/// See .dot() for the dot product
|
|
pub inline fn mulScalar(a: *const VecN, s: Scalar) VecN {
|
|
return .{ .v = a.v * VecN.splat(s).v };
|
|
}
|
|
|
|
/// Element-wise a < b
|
|
pub inline fn less(a: *const VecN, b: Scalar) bool {
|
|
return a.v < b.v;
|
|
}
|
|
|
|
/// Element-wise a <= b
|
|
pub inline fn lessEq(a: *const VecN, b: Scalar) bool {
|
|
return a.v <= b.v;
|
|
}
|
|
|
|
/// Element-wise a > b
|
|
pub inline fn greater(a: *const VecN, b: Scalar) bool {
|
|
return a.v > b.v;
|
|
}
|
|
|
|
/// Element-wise a >= b
|
|
pub inline fn greaterEq(a: *const VecN, b: Scalar) bool {
|
|
return a.v >= b.v;
|
|
}
|
|
|
|
/// Returns a vector with all components set to the `scalar` value:
|
|
///
|
|
/// ```
|
|
/// var v = Vec3.splat(1337.0).v;
|
|
/// // v.x == 1337, v.y == 1337, v.z == 1337
|
|
/// ```
|
|
pub inline fn splat(scalar: Scalar) VecN {
|
|
return .{ .v = @splat(scalar) };
|
|
}
|
|
|
|
/// Computes the squared length of the vector. Faster than `len()`
|
|
pub inline fn len2(v: *const VecN) Scalar {
|
|
return switch (VecN.n) {
|
|
inline 2 => (v.x() * v.x()) + (v.y() * v.y()),
|
|
inline 3 => (v.x() * v.x()) + (v.y() * v.y()) + (v.z() * v.z()),
|
|
inline 4 => (v.x() * v.x()) + (v.y() * v.y()) + (v.z() * v.z()) + (v.w() * v.w()),
|
|
else => @compileError("Expected Vec2, Vec3, Vec4, found '" ++ @typeName(VecN) ++ "'"),
|
|
};
|
|
}
|
|
|
|
/// Computes the length of the vector.
|
|
pub inline fn len(v: *const VecN) Scalar {
|
|
return math.sqrt(len2(v));
|
|
}
|
|
|
|
/// Normalizes a vector, such that all components end up in the range [0.0, 1.0].
|
|
///
|
|
/// d0 is added to the divisor, which means that e.g. if you provide a near-zero value, then in
|
|
/// situations where you would otherwise get NaN back you will instead get a near-zero vector.
|
|
///
|
|
/// ```
|
|
/// math.vec3(1.0, 2.0, 3.0).normalize(v, 0.00000001);
|
|
/// ```
|
|
pub inline fn normalize(v: *const VecN, d0: Scalar) VecN {
|
|
return v.div(&VecN.splat(v.len() + d0));
|
|
}
|
|
|
|
/// Returns the normalized direction vector from points a and b.
|
|
///
|
|
/// d0 is added to the divisor, which means that e.g. if you provide a near-zero value, then in
|
|
/// situations where you would otherwise get NaN back you will instead get a near-zero vector.
|
|
///
|
|
/// ```
|
|
/// var v = a_point.dir(b_point, 0.0000001);
|
|
/// ```
|
|
pub inline fn dir(a: *const VecN, b: *const VecN, d0: Scalar) VecN {
|
|
return b.sub(a).normalize(d0);
|
|
}
|
|
|
|
/// Calculates the squared distance between points a and b. Faster than `dist()`.
|
|
pub inline fn dist2(a: *const VecN, b: *const VecN) Scalar {
|
|
return b.sub(a).len2();
|
|
}
|
|
|
|
/// Calculates the distance between points a and b.
|
|
pub inline fn dist(a: *const VecN, b: *const VecN) Scalar {
|
|
return math.sqrt(a.dist2(b));
|
|
}
|
|
|
|
/// Performs linear interpolation between a and b by some amount.
|
|
///
|
|
/// ```
|
|
/// a.lerp(b, 0.0) == a
|
|
/// a.lerp(b, 1.0) == b
|
|
/// ```
|
|
pub inline fn lerp(a: *const VecN, b: *const VecN, amount: Scalar) VecN {
|
|
return a.mulScalar(1.0 - amount).add(&b.mulScalar(amount));
|
|
}
|
|
|
|
/// Calculates the dot product between vector a and b and returns scalar.
|
|
pub inline fn dot(a: *const VecN, b: *const VecN) Scalar {
|
|
return @reduce(.Add, a.v * b.v);
|
|
}
|
|
|
|
// Returns a new vector with the max values of two vectors
|
|
pub inline fn max(a: *const VecN, b: *const VecN) VecN {
|
|
return switch (VecN.n) {
|
|
inline 2 => VecN.init(
|
|
@max(a.x(), b.x()),
|
|
@max(a.y(), b.y()),
|
|
),
|
|
inline 3 => VecN.init(
|
|
@max(a.x(), b.x()),
|
|
@max(a.y(), b.y()),
|
|
@max(a.z(), b.z()),
|
|
),
|
|
inline 4 => VecN.init(
|
|
@max(a.x(), b.x()),
|
|
@max(a.y(), b.y()),
|
|
@max(a.z(), b.z()),
|
|
@max(a.w(), b.w()),
|
|
),
|
|
else => @compileError("Expected Vec2, Vec3, Vec4, found '" ++ @typeName(VecN) ++ "'"),
|
|
};
|
|
}
|
|
|
|
// Returns a new vector with the min values of two vectors
|
|
pub inline fn min(a: *const VecN, b: *const VecN) VecN {
|
|
return switch (VecN.n) {
|
|
inline 2 => VecN.init(
|
|
@min(a.x(), b.x()),
|
|
@min(a.y(), b.y()),
|
|
),
|
|
inline 3 => VecN.init(
|
|
@min(a.x(), b.x()),
|
|
@min(a.y(), b.y()),
|
|
@min(a.z(), b.z()),
|
|
),
|
|
inline 4 => VecN.init(
|
|
@min(a.x(), b.x()),
|
|
@min(a.y(), b.y()),
|
|
@min(a.z(), b.z()),
|
|
@min(a.w(), b.w()),
|
|
),
|
|
else => @compileError("Expected Vec2, Vec3, Vec4, found '" ++ @typeName(VecN) ++ "'"),
|
|
};
|
|
}
|
|
|
|
// Returns the inverse of a given vector
|
|
pub inline fn inverse(a: *const VecN) VecN {
|
|
return switch (VecN.n) {
|
|
inline 2 => .{ .v = (math.vec2(1, 1).v / a.v) },
|
|
inline 3 => .{ .v = (math.vec3(1, 1, 1).v / a.v) },
|
|
inline 4 => .{ .v = (math.vec4(1, 1, 1, 1).v / a.v) },
|
|
else => @compileError("Expected Vec2, Vec3, Vec4, found '" ++ @typeName(VecN) ++ "'"),
|
|
};
|
|
}
|
|
|
|
// Negates a given vector
|
|
pub inline fn negate(a: *const VecN) VecN {
|
|
return switch (VecN.n) {
|
|
inline 2 => .{ .v = math.vec2(-1, -1).v * a.v },
|
|
inline 3 => .{ .v = math.vec3(-1, -1, -1).v * a.v },
|
|
inline 4 => .{ .v = math.vec4(-1, -1, -1, -1).v * a.v },
|
|
else => @compileError("Expected Vec2, Vec3, Vec4, found '" ++ @typeName(VecN) ++ "'"),
|
|
};
|
|
}
|
|
|
|
// Returns the largest scalar of two vectors
|
|
pub inline fn maxScalar(a: *const VecN, b: *const VecN) Scalar {
|
|
var max_scalar: Scalar = a.v[0];
|
|
inline for (0..VecN.n) |i| {
|
|
if (a.v[i] > max_scalar)
|
|
max_scalar = a.v[i];
|
|
if (b.v[i] > max_scalar)
|
|
max_scalar = b.v[i];
|
|
}
|
|
|
|
return max_scalar;
|
|
}
|
|
|
|
// Returns the smallest scalar of two vectors
|
|
pub inline fn minScalar(a: *const VecN, b: *const VecN) Scalar {
|
|
var min_scalar: Scalar = a.v[0];
|
|
inline for (0..VecN.n) |i| {
|
|
if (a.v[i] < min_scalar)
|
|
min_scalar = a.v[i];
|
|
if (b.v[i] < min_scalar)
|
|
min_scalar = b.v[i];
|
|
}
|
|
|
|
return min_scalar;
|
|
}
|
|
};
|
|
}
|
|
|
|
test "gpu_compatibility" {
|
|
// https://www.w3.org/TR/WGSL/#alignment-and-size
|
|
try testing.expect(usize, 8).eql(@sizeOf(math.Vec2)); // WGSL AlignOf 8, SizeOf 8
|
|
try testing.expect(usize, 16).eql(@sizeOf(math.Vec3)); // WGSL AlignOf 16, SizeOf 12
|
|
try testing.expect(usize, 16).eql(@sizeOf(math.Vec4)); // WGSL AlignOf 16, SizeOf 16
|
|
|
|
try testing.expect(usize, 4).eql(@sizeOf(math.Vec2h)); // WGSL AlignOf 4, SizeOf 4
|
|
try testing.expect(usize, 8).eql(@sizeOf(math.Vec3h)); // WGSL AlignOf 8, SizeOf 6
|
|
try testing.expect(usize, 8).eql(@sizeOf(math.Vec4h)); // WGSL AlignOf 8, SizeOf 8
|
|
|
|
try testing.expect(usize, 8 * 2).eql(@sizeOf(math.Vec2d)); // speculative
|
|
try testing.expect(usize, 16 * 2).eql(@sizeOf(math.Vec3d)); // speculative
|
|
try testing.expect(usize, 16 * 2).eql(@sizeOf(math.Vec4d)); // speculative
|
|
}
|
|
|
|
test "zero_struct_overhead" {
|
|
// Proof that using Vec4 is equal to @Vector(4, f32)
|
|
try testing.expect(usize, @alignOf(@Vector(4, f32))).eql(@alignOf(math.Vec4));
|
|
try testing.expect(usize, @sizeOf(@Vector(4, f32))).eql(@sizeOf(math.Vec4));
|
|
}
|
|
|
|
test "dimensions" {
|
|
try testing.expect(usize, 3).eql(math.Vec3.n);
|
|
}
|
|
|
|
test "type" {
|
|
try testing.expect(type, f16).eql(math.Vec3h.T);
|
|
}
|
|
|
|
test "init" {
|
|
try testing.expect(math.Vec3h, math.vec3h(1, 2, 3)).eql(math.vec3h(1, 2, 3));
|
|
}
|
|
|
|
test "splat" {
|
|
try testing.expect(math.Vec3h, math.vec3h(1337, 1337, 1337)).eql(math.Vec3h.splat(1337));
|
|
}
|
|
|
|
test "swizzle_singular" {
|
|
try testing.expect(f32, 1).eql(math.vec3(1, 2, 3).x());
|
|
try testing.expect(f32, 2).eql(math.vec3(1, 2, 3).y());
|
|
try testing.expect(f32, 3).eql(math.vec3(1, 2, 3).z());
|
|
}
|
|
|
|
test "len2" {
|
|
try testing.expect(f32, 2).eql(math.vec2(1, 1).len2());
|
|
try testing.expect(f32, 29).eql(math.vec3(2, 3, -4).len2());
|
|
try testing.expect(f32, 38.115).eqlApprox(math.vec4(1.5, 2.25, 3.33, 4.44).len2(), 0.0001);
|
|
try testing.expect(f32, 0).eql(math.vec4(0, 0, 0, 0).len2());
|
|
}
|
|
|
|
test "len" {
|
|
try testing.expect(f32, 5).eql(math.vec2(3, 4).len());
|
|
try testing.expect(f32, 6).eql(math.vec3(4, 4, 2).len());
|
|
try testing.expect(f32, 6.17373468817700328621).eql(math.vec4(1.5, 2.25, 3.33, 4.44).len());
|
|
try testing.expect(f32, 0).eql(math.vec4(0, 0, 0, 0).len());
|
|
}
|
|
|
|
test "normalize_example" {
|
|
const normalized = math.vec4(10, 0.5, -3, -0.2).normalize(math.eps_f32);
|
|
try testing.expect(math.Vec4, math.vec4(0.95, 0.05, -0.3, -0.02)).eqlApprox(normalized, 0.1);
|
|
}
|
|
|
|
test "normalize_accuracy" {
|
|
const normalized = math.vec2(1, 1).normalize(0);
|
|
const norm_val = std.math.sqrt1_2; // 1 / sqrt(2)
|
|
try testing.expect(math.Vec2, math.Vec2.splat(norm_val)).eql(normalized);
|
|
}
|
|
|
|
test "normalize_nan" {
|
|
const near_zero = 0.0;
|
|
const normalized = math.vec2(0, 0).normalize(near_zero);
|
|
try testing.expect(bool, true).eql(math.isNan(normalized.x()));
|
|
}
|
|
|
|
test "normalize_no_nan" {
|
|
const near_zero = math.eps_f32;
|
|
const normalized = math.vec2(0, 0).normalize(near_zero);
|
|
try testing.expect(math.Vec2, math.vec2(0, 0)).eqlBinary(normalized);
|
|
}
|
|
|
|
// TODO(math): add basic tests for these:
|
|
//
|
|
// pub inline fn add(a: *const VecN, b: *const VecN) VecN {
|
|
// pub inline fn sub(a: *const VecN, b: *const VecN) VecN {
|
|
// pub inline fn div(a: *const VecN, b: *const VecN) VecN {
|
|
// pub inline fn mul(a: *const VecN, b: *const VecN) VecN {
|
|
// pub inline fn addScalar(a: *const VecN, s: Scalar) VecN {
|
|
// pub inline fn subScalar(a: *const VecN, s: Scalar) VecN {
|
|
// pub inline fn divScalar(a: *const VecN, s: Scalar) VecN {
|
|
// pub inline fn mulScalar(a: *const VecN, s: Scalar) VecN {
|
|
|
|
// TODO(math): the tests below violate our styleguide (https://machengine.org/about/style/) we
|
|
// should write new tests loosely based on them:
|
|
|
|
// test "vec.dir" {
|
|
// const near_zero_value = 1e-8;
|
|
|
|
// {
|
|
// const a = Vec2{ 0, 0 };
|
|
// const b = Vec2{ 0, 0 };
|
|
// const d = vec.dir(a, b, near_zero_value);
|
|
// try expect(d[0] == 0 and d[1] == 0);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec2{ 1, 2 };
|
|
// const b = Vec2{ 1, 2 };
|
|
// const d = vec.dir(a, b, near_zero_value);
|
|
// try expect(d[0] == 0 and d[1] == 0);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec2{ 1, 2 };
|
|
// const b = Vec2{ 3, 4 };
|
|
// const d = vec.dir(a, b, 0);
|
|
// const result = std.math.sqrt1_2; // 1 / sqrt(2)
|
|
// try expect(d[0] == result and d[1] == result);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec2{ 1, 2 };
|
|
// const b = Vec2{ -1, -2 };
|
|
// const d = vec.dir(a, b, 0);
|
|
// const result = -0.44721359549995793928; // 1 / sqrt(5)
|
|
// try expectApproxEqAbs(d[0], result, near_zero_value);
|
|
// try expectApproxEqAbs(d[1], 2 * result, near_zero_value);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec3{ 1, -1, 0 };
|
|
// const b = Vec3{ 0, 1, 1 };
|
|
// const d = vec.dir(a, b, 0);
|
|
|
|
// const result_3 = 0.40824829046386301637; // 1 / sqrt(6)
|
|
// const result_1 = -result_3; // -1 / sqrt(6)
|
|
// const result_2 = 0.81649658092772603273; // sqrt(2/3)
|
|
// try expectApproxEqAbs(d[0], result_1, 1e-7);
|
|
// try expectApproxEqAbs(d[1], result_2, 1e-7);
|
|
// try expectApproxEqAbs(d[2], result_3, 1e-7);
|
|
// }
|
|
// }
|
|
|
|
// test "vec.dist2" {
|
|
// {
|
|
// const a = Vec4{ 0, 0, 0, 0 };
|
|
// const b = Vec4{ 0, 0, 0, 0 };
|
|
// try expect(vec.dist2(a, b) == 0);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec2{ 1, 1 };
|
|
// try expect(vec.dist2(a, a) == 0);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec2{ 1, 2 };
|
|
// const b = Vec2{ 3, 4 };
|
|
// try expect(vec.dist2(a, b) == 8);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec3{ -1, -2, -3 };
|
|
// const b = Vec3{ 3, 2, 1 };
|
|
// try expect(vec.dist2(a, b) == 48);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec4{ 1.5, 2.25, 3.33, 4.44 };
|
|
// const b = Vec4{ 1.44, -9.33, 7.25, -0.5 };
|
|
// try expectApproxEqAbs(vec.dist2(a, b), 173.87, 1e-8);
|
|
// }
|
|
// }
|
|
|
|
// test "vec.dist" {
|
|
// {
|
|
// const a = Vec4{ 0, 0, 0, 0 };
|
|
// const b = Vec4{ 0, 0, 0, 0 };
|
|
// try expect(vec.dist(a, b) == 0);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec2{ 1, 1 };
|
|
// try expect(vec.dist(a, a) == 0);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec2{ 1, 2 };
|
|
// const b = Vec2{ 4, 6 };
|
|
// try expectEqual(vec.dist(a, b), 5);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec3{ -1, -2, -3 };
|
|
// const b = Vec3{ 3, 2, -1 };
|
|
// try expect(vec.dist(a, b) == 6);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec4{ 1.5, 2.25, 3.33, 4.44 };
|
|
// const b = Vec4{ 1.44, -9.33, 7.25, -0.5 };
|
|
// try expectApproxEqAbs(vec.dist(a, b), 13.18597740025364975978, 1e-8);
|
|
// }
|
|
// }
|
|
|
|
// test "vec.lerp" {
|
|
// {
|
|
// const a = Vec4{ 1, 1, 1, 1 };
|
|
// const b = Vec4{ 0, 0, 0, 0 };
|
|
// const lerp_to_a = vec.lerp(a, b, 0.0);
|
|
// try expectEqual(lerp_to_a[0], a[0]);
|
|
// try expectEqual(lerp_to_a[1], a[1]);
|
|
// try expectEqual(lerp_to_a[2], a[2]);
|
|
// try expectEqual(lerp_to_a[3], a[3]);
|
|
|
|
// const lerp_to_b = vec.lerp(a, b, 1.0);
|
|
// try expectEqual(lerp_to_b[0], b[0]);
|
|
// try expectEqual(lerp_to_b[1], b[1]);
|
|
// try expectEqual(lerp_to_b[2], b[2]);
|
|
// try expectEqual(lerp_to_b[3], b[3]);
|
|
|
|
// const lerp_to_mid = vec.lerp(a, b, 0.5);
|
|
// try expectEqual(lerp_to_mid[0], 0.5);
|
|
// try expectEqual(lerp_to_mid[1], 0.5);
|
|
// try expectEqual(lerp_to_mid[2], 0.5);
|
|
// try expectEqual(lerp_to_mid[3], 0.5);
|
|
// }
|
|
// }
|
|
|
|
// test "vec.cross" {
|
|
// {
|
|
// const a = Vec3{ 1, 3, 4 };
|
|
// const b = Vec3{ 2, -5, 8 };
|
|
// const cross = vec.cross(a, b);
|
|
// try expectEqual(cross[0], 44);
|
|
// try expectEqual(cross[1], 0);
|
|
// try expectEqual(cross[2], -11);
|
|
// }
|
|
// {
|
|
// const a = Vec3{ 1.0, 0.0, 0.0 };
|
|
// const b = Vec3{ 0.0, 1.0, 0.0 };
|
|
// const cross = vec.cross(a, b);
|
|
// try expectEqual(cross[0], 0.0);
|
|
// try expectEqual(cross[1], 0.0);
|
|
// try expectEqual(cross[2], 1.0);
|
|
// }
|
|
// {
|
|
// const a = Vec3{ 1.0, 0.0, 0.0 };
|
|
// const b = Vec3{ 0.0, -1.0, 0.0 };
|
|
// const cross = vec.cross(a, b);
|
|
// try expectEqual(cross[0], 0.0);
|
|
// try expectEqual(cross[1], 0.0);
|
|
// try expectEqual(cross[2], -1.0);
|
|
// }
|
|
// {
|
|
// const a = Vec3{ -3.0, 0.0, -2.0 };
|
|
// const b = Vec3{ 5.0, -1.0, 2.0 };
|
|
// const cross = vec.cross(a, b);
|
|
// try expectEqual(cross[0], -2.0);
|
|
// try expectEqual(cross[1], -4.0);
|
|
// try expectEqual(cross[2], 3.0);
|
|
// }
|
|
// }
|
|
|
|
// test "vec.dot" {
|
|
// {
|
|
// const a = Vec2{ -1, 2 };
|
|
// const b = Vec2{ 4, 5 };
|
|
// const dot = vec.dot(a, b);
|
|
// try expectEqual(dot, 6);
|
|
// }
|
|
// {
|
|
// const a = Vec3{ -1.0, 2.0, 3.0 };
|
|
// const b = Vec3{ 4.0, 5.0, 6.0 };
|
|
// const dot = vec.dot(a, b);
|
|
// try expectEqual(dot, 24.0);
|
|
// }
|
|
// {
|
|
// const a = Vec4{ -1.0, 2.0, 3.0, -2.0 };
|
|
// const b = Vec4{ 4.0, 5.0, 6.0, 2.0 };
|
|
// const dot = vec.dot(a, b);
|
|
// try expectEqual(dot, 20.0);
|
|
// }
|
|
|
|
// {
|
|
// const a = Vec4{ 0, 0, 0, 0 };
|
|
// const b = Vec4{ 0, 0, 0, 0 };
|
|
// const dot = vec.dot(a, b);
|
|
// try expectEqual(dot, 0.0);
|
|
// }
|
|
// }
|