Compare commits
2 commits
ee1adc6803
...
674b479ad8
| Author | SHA1 | Date | |
|---|---|---|---|
| 674b479ad8 | |||
| 7da88d9db1 |
5 changed files with 222 additions and 1 deletions
|
|
@ -5,6 +5,9 @@
|
|||
#import,file "./module.jai"(true);
|
||||
#import,file "./encoding/module.jai"(true);
|
||||
#import,file "./hash/module.jai"(true);
|
||||
rmath :: #import,file "./math/module.jai"(.radians, true);
|
||||
dmath :: #import,file "./math/module.jai"(.degrees, true);
|
||||
tmath :: #import,file "./math/module.jai"(.turns, true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
43
math/mat.jai
Normal file
43
math/mat.jai
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
Mat4 :: #type,distinct Vec(4 * 4, float);
|
||||
|
||||
m4 :: (r0: Vec4, r1: Vec4, r2: Vec4, r3: Vec4) -> Mat4 #expand {
|
||||
return .{
|
||||
components = .[
|
||||
r0.x, r0.y, r0.z, r0.w,
|
||||
r1.x, r1.y, r1.z, r1.w,
|
||||
r2.x, r2.y, r2.z, r2.w,
|
||||
r3.x, r3.y, r3.z, r3.w,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
m4_identity :: #bake_arguments m4d(diag = 1);
|
||||
|
||||
m4d :: (diag: float) -> Mat4 #expand {
|
||||
res: Mat4;
|
||||
res[0][0] = diag;
|
||||
res[1][1] = diag;
|
||||
res[2][2] = diag;
|
||||
res[3][3] = diag;
|
||||
return res;
|
||||
}
|
||||
|
||||
operator [] :: inline (m: Mat4, idx: int) -> Vec4 #expand {
|
||||
bounds_check_index(idx * 4, m.N);
|
||||
return (m.components[idx * 4]).(*Vec4).*;
|
||||
}
|
||||
|
||||
operator *[] :: inline (m: *Mat4, $$idx: int) -> *Vec4 #no_abc {
|
||||
N :: Mat4.{}.N; // @note(judah): dumb workaround for not being able to access pointer type field constants
|
||||
bounds_check_index(idx * 4, N);
|
||||
return (*m.components[idx * 4]).(*Vec4);
|
||||
}
|
||||
|
||||
operator []= :: inline (m: *Mat4, $$idx: int, value: Vec4) #no_abc {
|
||||
N :: Mat4.{}.N;
|
||||
bounds_check_index(idx * 4, N);
|
||||
|
||||
ptr := (*m.components[idx * 4]).(*Vec4);
|
||||
ptr.*= value;
|
||||
}
|
||||
|
||||
25
math/module.jai
Normal file
25
math/module.jai
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#module_parameters(
|
||||
UNITS: enum { radians; degrees; turns; } = .turns,
|
||||
RUN_TESTS := false
|
||||
);
|
||||
|
||||
#load "vec.jai";
|
||||
#load "mat.jai";
|
||||
|
||||
#scope_module;
|
||||
|
||||
bounds_check_index :: ($$idx: int, $count: int, loc := #caller_location) #expand {
|
||||
#if is_constant(idx) {
|
||||
#assert (idx >= 0 && idx < count) "bounds check failed";
|
||||
}
|
||||
else {
|
||||
basic.assert(idx >= 0 && idx < count, "bounds check failed! index: % (min: 0, max: %)", idx, count, loc = loc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
basic :: #import "Basic";
|
||||
|
||||
#if RUN_TESTS {
|
||||
test :: #import,file "../test/module.jai";
|
||||
}
|
||||
150
math/vec.jai
Normal file
150
math/vec.jai
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
Vec is a generic set of N named values of type T.
|
||||
|
||||
The values can be accessed via array index or their common component names:
|
||||
|
||||
- u, v
|
||||
- x, y, z, w
|
||||
- r, g, b, a
|
||||
- c0, c1, c2, c3, ... cN
|
||||
|
||||
For most use cases, opt for the named variants of this type:
|
||||
|
||||
Vec2 : Vec(2, float)
|
||||
Vec3 : Vec(3, float)
|
||||
Vec4 : Vec(4, float)
|
||||
Quat : Vec(4, float)
|
||||
*/
|
||||
Vec :: struct(N: int, T: Type)
|
||||
#modify {
|
||||
info := T.(*Type_Info);
|
||||
return info.type == .INTEGER || info.type == .FLOAT, "Vec T must be a numeric type (int or float)";
|
||||
} {
|
||||
#as components: [N]T;
|
||||
#insert -> string {
|
||||
b: basic.String_Builder;
|
||||
basic.append(*b, "#place components;\n");
|
||||
|
||||
fields :: []string.[
|
||||
string.[ "x", "r", "u" ],
|
||||
string.[ "y", "g", "v" ],
|
||||
string.[ "z", "b", "" ],
|
||||
string.[ "w", "a", "" ],
|
||||
];
|
||||
|
||||
for i: 0..N - 1 {
|
||||
if i < fields.count {
|
||||
basic.append(*b, "union {\n");
|
||||
for field: fields[i] if field.count != 0 {
|
||||
basic.print_to_builder(*b, "\t%: T = ---;\n", field);
|
||||
}
|
||||
basic.print_to_builder(*b, "\tc%: T = ---;\n", i);
|
||||
basic.append(*b, "};\n");
|
||||
}
|
||||
else {
|
||||
basic.print_to_builder(*b, "c%: T = ---;\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
return basic.builder_to_string(*b);
|
||||
};
|
||||
}
|
||||
|
||||
operator [] :: (v: Vec, $$idx: int) -> v.T #no_abc {
|
||||
bounds_check_index(idx, v.N);
|
||||
return v.components[idx];
|
||||
}
|
||||
|
||||
operator *[] :: (v: *Vec, $$idx: int) -> *v.T #no_abc {
|
||||
bounds_check_index(idx, v.N);
|
||||
return *v.components[idx];
|
||||
}
|
||||
|
||||
operator []= :: (v: *Vec, $$idx: int, value: v.T) #no_abc {
|
||||
bounds_check_index(idx, v.N);
|
||||
v.components[idx] = value;
|
||||
}
|
||||
|
||||
for_expansion :: (v: *Vec, body: Code, flags: For_Flags) #expand {
|
||||
for i: 0..v.N - 1 {
|
||||
`it_index := i;
|
||||
#if flags & .POINTER {
|
||||
`it := *v.components[i];
|
||||
} else {
|
||||
`it := v.components[i];
|
||||
}
|
||||
|
||||
#insert,scope(body) body;
|
||||
}
|
||||
}
|
||||
|
||||
operator + :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc {
|
||||
res: Vec(l.N, l.T) = ---;
|
||||
for l res[it_index] = it + r[it_index];
|
||||
return res;
|
||||
}
|
||||
|
||||
operator - :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc {
|
||||
res: Vec(l.N, l.T) = ---;
|
||||
for l res[it_index] = it - r[it_index];
|
||||
return res;
|
||||
}
|
||||
|
||||
operator * :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc {
|
||||
res: Vec(l.N, l.T) = ---;
|
||||
for l res[it_index] = it * r[it_index];
|
||||
return res;
|
||||
}
|
||||
|
||||
operator / :: inline (l: Vec, r: Vec(l.N, l.T)) -> Vec(l.N, l.T) #no_abc {
|
||||
res: Vec(l.N, l.T) = ---;
|
||||
for l res[it_index] = it / r[it_index];
|
||||
return res;
|
||||
}
|
||||
|
||||
// Concrete vector types (the usual cases)
|
||||
|
||||
Vec2 :: Vec(2, float);
|
||||
Vec3 :: Vec(3, float);
|
||||
Vec4 :: Vec(4, float);
|
||||
Quat :: Vec4;
|
||||
|
||||
v2f :: (x: $T = 0, y: T = 0) -> Vec2
|
||||
#modify { return T.(*Type_Info).type == .FLOAT, "use v2i for integer arguments"; }
|
||||
#expand {
|
||||
return .{ x = x, y = y };
|
||||
}
|
||||
|
||||
v2i :: (x: $T = 0, y: T = 0) -> Vec(2, T)
|
||||
#modify { return T.(*Type_Info).type == .INTEGER, "use v2f for float arguments"; }
|
||||
#expand {
|
||||
return .{ x = x, y = y };
|
||||
}
|
||||
|
||||
v3f :: (x: $T = 0, y: T = 0, z: T = 0) -> Vec3
|
||||
#modify { return T.(*Type_Info).type == .FLOAT, "use v3i for integer arguments"; }
|
||||
#expand {
|
||||
return .{ x = x, y = y, z = z };
|
||||
}
|
||||
|
||||
v3i :: (x: $T = 0, y: T = 0, z: T = 0) -> Vec(3, T)
|
||||
#modify { return T.(*Type_Info).type == .INTEGER, "use v3f for float arguments"; }
|
||||
#expand {
|
||||
return .{ x = x, y = y, z = z };
|
||||
}
|
||||
|
||||
v4f :: (x: $T = 0, y: T = 0, z: T = 0, w: T = 0) -> Vec4
|
||||
#modify { return T.(*Type_Info).type == .FLOAT, "use v4i for integer arguments"; }
|
||||
#expand {
|
||||
return .{ x = x, y = y, z = z, w = w };
|
||||
}
|
||||
|
||||
v4i :: (x: $T = 0, y: T = 0, z: T = 0, w: T = 0) -> Vec(4, T)
|
||||
#modify { return T.(*Type_Info).type == .INTEGER, "use v4f for float arguments"; }
|
||||
#expand {
|
||||
return .{ x = x, y = y, z = z, w = w };
|
||||
}
|
||||
|
||||
quat :: (x: float = 0, y: float = 0, z: float = 0, w: float = 0) -> Quat #expand {
|
||||
return .{ x = x, y = y, z = z, w = w };
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ expect :: (t: *T, cond: bool, message := "", args: ..Any, loc := #caller_locatio
|
|||
|
||||
run :: (name: string, proc: Proc, loc := #caller_location) {
|
||||
filename := strings.path_filename(loc.fully_pathed_filename);
|
||||
basic.print("test %,%: %...", filename, loc.line_number, name);
|
||||
basic.print("%,%: %...", filename, loc.line_number, name);
|
||||
|
||||
t: T;
|
||||
proc(*t);
|
||||
|
|
|
|||
Loading…
Reference in a new issue