replace math_graphics with glm version 1.0.3

This commit is contained in:
Sven Balzer
2026-04-15 10:50:41 +02:00
parent 07af9deb6a
commit 4ec664c8db
1676 changed files with 289261 additions and 1477 deletions
+124 -66
View File
@@ -11,15 +11,17 @@
#include <tracy/TracyC.h>
#include <webgpu/webgpu.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "defer.h"
#include "log.h"
#include "math_graphics.h"
#include "stb_image.h"
#include "change_directory.h"
#include "shaders/shaders.h"
using namespace M;
using namespace glm;
#define ASSETS_PATH "./assets/"
@@ -84,11 +86,11 @@ static float camera_fovy_degrees = 31.0f;
static float camera_tilt = 25.5f;
static float camera_distance = 13.5f;
static M4x4 view_matrix;
static M4x4 inverse_view_matrix;
static mat4x4 view_matrix;
static mat4x4 inverse_view_matrix;
static M4x4 projection_matrix;
static M4x4 inverse_projection_matrix;
static mat4x4 projection_matrix;
static mat4x4 inverse_projection_matrix;
static SDL_Time time;
@@ -96,7 +98,61 @@ static bool enable_time_tints = true;
static bool use_actual_time = true;
static SDL_DateTime calendar_time;
static V2 mouse_pos;
static vec2 mouse_pos;
float remap(float in_a, float in_b, float out_a, float out_b, float v) {
return mix(out_a, out_b, (v - in_a) / (in_b - in_a));
}
vec2 remap(vec2 in_a, vec2 in_b, vec2 out_a, vec2 out_b, vec2 v) {
return mix(out_a, out_b, (v - in_a) / (in_b - in_a));
}
mat4x4 view(vec3 player_pos, float tilt, float camera_distance) {
float s = sinf(tilt);
float c = cosf(tilt);
return {
1, 0, 0, -player_pos.x,
0, c, s, c * -player_pos.y,
0, -s, c, s * player_pos.y - camera_distance,
0, 0, 0, 1,
};
}
mat4x4 inverse_view(vec3 player_pos, float tilt, float camera_distance) {
float s = sinf(tilt);
float c = cosf(tilt);
return {
1, 0, 0, player_pos.x,
0, c, -s, -s * camera_distance + player_pos.y,
0, s, c, c * camera_distance,
0, 0, 0, 1,
};
}
mat4x4 projection(float fovy, float aspect, float near) {
float g = 1.0 / tanf(fovy * 0.5);
return {
g / aspect, 0, 0, 0,
0, g, 0, 0,
0, 0, 0, near,
0, 0, -1, 0,
};
}
mat4x4 inverse_projection(float fovy, float aspect, float near) {
float g = 1.0 / tanf(fovy * 0.5);
return {
aspect / g, 0, 0, 0,
0, 1 / g, 0, 0,
0, 0, 0, -1,
0, 0, 1 / near, 0,
};
}
#define MAX_TINT_TIMES 32
static int num_used_tint_times = 4;
@@ -107,11 +163,11 @@ static int time_tints_times[MAX_TINT_TIMES][3] = {
{ 21, 0, 0 },
};
static V3 time_tints[MAX_TINT_TIMES] = {
V3_(0.314f, 0.369f, 0.455f),
V3_(1.0f, 0.891f, 0.868f),
V3_(1.0f, 0.465f, 0.373f),
V3_(0.314f, 0.369f, 0.455f),
static vec3 time_tints[MAX_TINT_TIMES] = {
{ 0.314f, 0.369f, 0.455f },
{ 1.0f, 0.891f, 0.868f },
{ 1.0f, 0.465f, 0.373f },
{ 0.314f, 0.369f, 0.455f },
};
enum Settings_Category {
@@ -120,15 +176,15 @@ enum Settings_Category {
};
struct Vertex {
V3 pos;
V2 uv;
vec3 pos;
vec2 uv;
};
static Vertex vertices[] = {
{{ -0.5f, 0.5f }, { 0.0f, 0.0f }},
{{ -0.5f, -0.5f }, { 0.0f, 1.0f }},
{{ 0.5f, -0.5f }, { 1.0f, 1.0f }},
{{ 0.5f, 0.5f }, { 1.0f, 0.0f }},
{{ -0.5f, 0.5f, 0.0f }, { 0.0f, 0.0f }},
{{ -0.5f, -0.5f, 0.0f }, { 0.0f, 1.0f }},
{{ 0.5f, -0.5f, 0.0f }, { 1.0f, 1.0f }},
{{ 0.5f, 0.5f, 0.0f }, { 1.0f, 0.0f }},
};
static Uint16 indices[] = {
@@ -139,28 +195,28 @@ static Uint16 indices[] = {
#define grid_line_size (1.0f / 64.0f)
static Vertex grid_vertices[] = {
// LEFT
{{ -0.5f, 0.5f }},
{{ -0.5f, -0.5f + grid_line_size }},
{{ -0.5f + grid_line_size, -0.5f + grid_line_size }},
{{ -0.5f + grid_line_size, 0.5f }},
{{ -0.5f, 0.5f, 0.0f }},
{{ -0.5f, -0.5f + grid_line_size, 0.0f }},
{{ -0.5f + grid_line_size, -0.5f + grid_line_size, 0.0f }},
{{ -0.5f + grid_line_size, 0.5f, 0.0f }},
// TOP
{{ -0.5f + grid_line_size, 0.5f }},
{{ -0.5f + grid_line_size, 0.5f - grid_line_size }},
{{ 0.5f, 0.5f - grid_line_size }},
{{ 0.5f, 0.5f }},
{{ -0.5f + grid_line_size, 0.5f, 0.0f }},
{{ -0.5f + grid_line_size, 0.5f - grid_line_size, 0.0f }},
{{ 0.5f, 0.5f - grid_line_size, 0.0f }},
{{ 0.5f, 0.5f, 0.0f }},
// RIGHT
{{ 0.5f - grid_line_size, 0.5f - grid_line_size }},
{{ 0.5f - grid_line_size, -0.5f }},
{{ 0.5f, -0.5f }},
{{ 0.5f, 0.5f - grid_line_size }},
{{ 0.5f - grid_line_size, 0.5f - grid_line_size, 0.0f }},
{{ 0.5f - grid_line_size, -0.5f, 0.0f }},
{{ 0.5f, -0.5f, 0.0f }},
{{ 0.5f, 0.5f - grid_line_size, 0.0f }},
// BOTTOM
{{ -0.5f, -0.5f + grid_line_size }},
{{ -0.5f, -0.5f }},
{{ 0.5f - grid_line_size, -0.5f }},
{{ 0.5f - grid_line_size, -0.5f + grid_line_size }},
{{ -0.5f, -0.5f + grid_line_size, 0.0f }},
{{ -0.5f, -0.5f, 0.0f }},
{{ 0.5f - grid_line_size, -0.5f, 0.0f }},
{{ 0.5f - grid_line_size, -0.5f + grid_line_size, 0.0f }},
};
static Uint16 grid_indices[] = {
@@ -182,7 +238,7 @@ static Uint16 grid_indices[] = {
};
struct Instance {
V2 pos;
vec2 pos;
};
static Instance player_instance = {{ 0.0f, 0.0f }};
@@ -216,7 +272,7 @@ typedef struct Sint32x2 {
struct PerFrame {
Sint32x2 drag_start;
Sint32x2 mouse;
V2 grid_offset;
vec2 grid_offset;
Sint32 grid_width;
Sint32 map_width;
};
@@ -263,7 +319,7 @@ static TileInfo tile_infos[] = {
{ 0x0423, "tiles/grass_ground_two_corner.png", TILE_CORNER_INFO(TILEKIND_GRASS, TILEKIND_GROUND, TILEKIND_GRASS, TILEKIND_GROUND ) },
};
static V4 tile_uvs[SDL_arraysize(tile_infos)];
static vec4 tile_uvs[SDL_arraysize(tile_infos)];
static Sint32 selected_tile_kind = -1;
@@ -271,7 +327,7 @@ static Sint32 selected_tile = -1;
static Sint32 selected_rotation = 0;
static bool dragging_tile_change = false;
static V2 drag_start_pos;
static vec2 drag_start_pos;
static bool update_buffer(WGPUBuffer buffer, Uint32 offset, Uint32 num_bytes, void *data) {
wgpuQueueWriteBuffer(queue, buffer, offset, data, num_bytes);
@@ -579,7 +635,7 @@ static bool SelectableTile(const char *label, bool selected, Uint32 tile_index,
ImVec2 min = ImGui::GetItemRectMin();
ImVec2 max = ImGui::GetItemRectMax();
V4 uv = tile_uvs[tile_index] / TILE_ATLAS_SIZE;
vec4 uv = tile_uvs[tile_index] / (float)TILE_ATLAS_SIZE;
switch (orientation) {
case 0: context->CurrentWindow->DrawList->AddImageQuad((ImTextureID)tile_textures_atlas_view_unorm, min + padding, ImVec2(max.x - padding.x, min.y + padding.y), max - padding, ImVec2(min.x + padding.x, max.y - padding.y), ImVec2(uv.x, uv.y), ImVec2(uv.z, uv.y), ImVec2(uv.z, uv.w), ImVec2(uv.x, uv.w)); break;
@@ -608,24 +664,26 @@ static ImVec4 sRGB_to_linear(ImVec4 linear) {
return ImVec4(red, green, blue, linear.w);
}
static V3 Unproject(V3 screen_pos) {
V4 result = inverse_view_matrix * inverse_projection_matrix * V4_(screen_pos, 1.0f);
result.xyz /= result.w;
static vec3 Unproject(vec3 screen_pos) {
vec4 result = vec4(screen_pos, 1.0f) * inverse_projection_matrix * inverse_view_matrix;
result.x /= result.w;
result.y /= result.w;
result.z /= result.w;
return result.xyz;
return result.xyz();
}
static V2 get_floor_intersection_of_mouse(V2 mouse_pos) {
V2 mouse = remap(V2{ 0, 0 }, V2{ (float)window_width, (float)window_height }, V2{ -1, 1 }, V2{ 1, -1 }, V2{ mouse_pos.x, mouse_pos.y });
V3 camera_position = (inverse_view_matrix * V4_(0, 0, 0, 1)).xyz;
static vec2 get_floor_intersection_of_mouse(vec2 mouse_pos) {
vec2 mouse = remap(vec2(0, 0), vec2((float)window_width, (float)window_height), vec2(-1, 1), vec2(1, -1), mouse_pos);
vec3 camera_position = (vec4(0, 0, 0, 1) * inverse_view_matrix).xyz();
V3 probe = Unproject(V3_(mouse, .5));
V3 ray_dir = normalize(probe - camera_position);
vec3 probe = Unproject(vec3(mouse, .5));
vec3 ray_dir = normalize(probe - camera_position);
float t = -camera_position.z / ray_dir.z;
V3 floor_intersection = camera_position + (t * ray_dir);
vec3 floor_intersection = camera_position + (t * ray_dir);
return floor_intersection.xy;
return floor_intersection.xy();
}
#ifdef TRACY_ENABLE
@@ -1289,7 +1347,7 @@ static void SameLineOrWrap(const ImVec2& size) {
ImGui::SameLine();
}
static Sint32x2 grid_tile_pos_from_floor_intersection(V2 floor_intersection) {
static Sint32x2 grid_tile_pos_from_floor_intersection(vec2 floor_intersection) {
return {
(Sint32)SDL_floorf(floor_intersection.x + (selected_tile == -1 ? 0.5f : 1.0f)),
(Sint32)SDL_floorf(floor_intersection.y + (selected_tile == -1 ? 0.5f : 1.0f)),
@@ -1473,7 +1531,7 @@ static bool init_webgpu() {
pixel_sampler = wgpuDeviceCreateSampler(device, &pixel_sampler_descriptor);
view_projection_matrix_buffer = create_buffer(WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, sizeof(M4x4), NULL, "view_projection_matrix_buffer");
view_projection_matrix_buffer = create_buffer(WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, sizeof(mat4x4), NULL, "view_projection_matrix_buffer");
if (!view_projection_matrix_buffer) {
log_error("Failed to create buffer.");
return false;
@@ -1485,7 +1543,7 @@ static bool init_webgpu() {
return false;
}
tint_color_buffer = create_buffer(WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, sizeof(V3), NULL, "tint_color_buffer");
tint_color_buffer = create_buffer(WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst, sizeof(vec3), NULL, "tint_color_buffer");
if (!tint_color_buffer) {
log_error("Failed to create buffer.");
return false;
@@ -1840,7 +1898,7 @@ int main(int argc, char **argv) {
ImGui::NewLine();
for (int i = 0; i < num_used_tint_times; i++) {
ImGui::PushID(i);
ImGui::ColorEdit3("##color", time_tints[i].E);
ImGui::ColorEdit3("##color", glm::value_ptr(time_tints[i]));
ImGui::PopID();
}
@@ -1852,7 +1910,7 @@ int main(int argc, char **argv) {
time_tints_times[i][0] == time_tints_times[i + 1][0] && time_tints_times[i][1] == time_tints_times[i + 1][1] && time_tints_times[i][2] > time_tints_times[i + 1][2]) {
int temp_time[3] = { time_tints_times[i][0], time_tints_times[i][1], time_tints_times[i][2] };
V3 temp_color = time_tints[i];
vec3 temp_color = time_tints[i];
time_tints_times[i][0] = time_tints_times[i + 1][0];
time_tints_times[i][1] = time_tints_times[i + 1][1];
@@ -2042,7 +2100,7 @@ int main(int argc, char **argv) {
if (io.WantCaptureMouse)
continue;
V2 floor_intersection = get_floor_intersection_of_mouse(V2_(event.button.x, event.button.y));
vec2 floor_intersection = get_floor_intersection_of_mouse(vec2(event.button.x, event.button.y));
Sint32x2 tile_pos = grid_tile_pos_from_floor_intersection(floor_intersection);
drag_start_pos = floor_intersection;
@@ -2094,7 +2152,7 @@ int main(int argc, char **argv) {
continue;
if (selected_tile != -1 && dragging_tile_change) {
V2 floor_intersection = get_floor_intersection_of_mouse(V2_(event.button.x, event.button.y));
vec2 floor_intersection = get_floor_intersection_of_mouse(vec2(event.button.x, event.button.y));
Sint32x2 tile_pos = grid_tile_pos_from_floor_intersection(floor_intersection);
Sint32 tile_x = clamp(0, tile_pos.x, current_map.width - 1);
@@ -2126,10 +2184,10 @@ int main(int argc, char **argv) {
} break;
case SDL_EVENT_MOUSE_MOTION: {
mouse_pos = V2_(event.motion.x, event.motion.y);
mouse_pos = vec2(event.motion.x, event.motion.y);
if (selected_tile_kind != -1 && dragging_tile_change) {
V2 floor_intersection = get_floor_intersection_of_mouse(mouse_pos);
vec2 floor_intersection = get_floor_intersection_of_mouse(mouse_pos);
Sint32x2 tile_pos = grid_tile_pos_from_floor_intersection(floor_intersection);
change_map_tile(tile_pos.x, tile_pos.y, (TileKind)selected_tile_kind);
}
@@ -2217,21 +2275,21 @@ int main(int argc, char **argv) {
float aspect_ratio = ((float) window_width / (float) window_height);
view_matrix = view (V3_((float)player.pos_x, (float)player.pos_y, 0), radians(camera_tilt), camera_distance);
inverse_view_matrix = inverse_view(V3_((float)player.pos_x, (float)player.pos_y, 0), radians(camera_tilt), camera_distance);
view_matrix = view (vec3((float)player.pos_x, (float)player.pos_y, 0), radians(camera_tilt), camera_distance);
inverse_view_matrix = inverse_view(vec3((float)player.pos_x, (float)player.pos_y, 0), radians(camera_tilt), camera_distance);
projection_matrix = projection (radians(camera_fovy_degrees), aspect_ratio, NEAR_PLANE);
inverse_projection_matrix = inverse_projection(radians(camera_fovy_degrees), aspect_ratio, NEAR_PLANE);
M4x4 view_projection_matrix = projection_matrix * view_matrix;
mat4x4 view_projection_matrix = view_matrix * projection_matrix;
update_buffer(view_projection_matrix_buffer, 0, sizeof(view_projection_matrix), &view_projection_matrix);
V2 floor_intersection = get_floor_intersection_of_mouse(mouse_pos);
vec2 floor_intersection = get_floor_intersection_of_mouse(mouse_pos);
Sint32x2 tile_pos = grid_tile_pos_from_floor_intersection(floor_intersection);
per_frame.map_width = current_map.width;
per_frame.grid_width = selected_tile != -1 ? current_map.width : current_map.width + 1;
per_frame.grid_offset = selected_tile != -1 ? V2_(-0.5f, -0.5f) : V2_(-1.0f, -1.0f);
per_frame.grid_offset = selected_tile != -1 ? vec2(-0.5f, -0.5f) : vec2(-1.0f, -1.0f);
per_frame.mouse = tile_pos;
if (dragging_tile_change && selected_tile != -1) {
@@ -2265,8 +2323,8 @@ int main(int argc, char **argv) {
double t = v / (double)time_between;
V3 tint_color = lerp(time_tints[last_time_index], time_tints[(last_time_index + 1) % num_used_tint_times], t);
if (!enable_time_tints) tint_color = V3_(1, 1, 1);
vec3 tint_color = mix(time_tints[last_time_index], time_tints[(last_time_index + 1) % num_used_tint_times], t);
if (!enable_time_tints) tint_color = vec3(1, 1, 1);
update_buffer(tint_color_buffer, 0, sizeof(tint_color), &tint_color);
}
}
-921
View File
@@ -1,921 +0,0 @@
#include "math_graphics.h"
#include <math.h>
namespace M {
float square_root(float a) {
return sqrtf(a);
}
double square_root(double a) {
return sqrt(a);
}
float reciprocal_square_root(float a) {
return 1.0f / square_root(a);
}
double reciprocal_square_root(double a) {
return 1.0 / square_root(a);
}
float lerp(float a, float b, float t) {
return (1.0f - t) * a + t * b;
}
float ilerp(float a, float b, float v) {
return (v - a) / (b - a);
}
float remap(float in_a, float in_b, float out_a, float out_b, float v) {
float t = ilerp(in_a, in_b, v);
return lerp(out_a, out_b, t);
}
float radians(float degrees) {
return degrees * (3.14159265358979323846f / 180.0f);
}
V2 V2_(float x, float y) {
return { x, y };
}
V2 operator -(V2 a) {
return {
-a.x,
-a.y
};
}
V2 operator +(V2 a, V2 b) {
return {
a.x + b.x,
a.y + b.y
};
}
V2 operator +=(V2& a, V2 b) {
return a = a + b;
}
V2 operator -(V2 a, V2 b) {
return {
a.x - b.x,
a.y - b.y
};
}
V2 operator -=(V2& a, V2 b) {
return a = a - b;
}
V2 operator *(float a, V2 b) {
return {
a * b.x,
a * b.y
};
}
V2 operator *(V2 a, float b) {
return {
a.x * b,
a.y * b
};
}
V2 &operator *= (V2 &a, float b) {
a = a * b;
return a;
}
V2 operator /(float a, V2 b) {
return {
a / b.x,
a / b.y
};
}
V2 operator /(V2 a, float b) {
return {
a.x / b,
a.y / b
};
}
V2 &operator /= (V2 &a, float b) {
a = a / b;
return a;
}
V2 operator /(V2 a, V2 b) {
return {
a.x / b.x,
a.y / b.y
};
}
float dot(V2 a, V2 b) {
return a.x * b.x + a.y * b.y;
}
V2 hadamard(V2 a, V2 b) {
return {
a.x * b.x,
a.y * b.y
};
}
float length_squared(V2 a) {
return dot(a, a);
}
float length(V2 a) {
return square_root(length_squared(a));
}
float reciprocal_length(V2 a) {
return reciprocal_square_root(length_squared(a));
}
V2 normalize(V2 a) {
return a * reciprocal_length(a);
}
V2 perpendicular(V2 a) {
return {
-a.y,
a.x
};
}
V2 clamp01(V2 a) {
return {
clamp01(a.x),
clamp01(a.y)
};
}
V2 min(V2 a, V2 b) {
return {
min(a.x, b.x),
min(a.y, b.y)
};
}
V2 max(V2 a, V2 b) {
return {
max(a.x, b.x),
max(a.y, b.y)
};
}
float min(V2 a) {
return min(a.x, a.y);
}
float max(V2 a) {
return max(a.x, a.y);
}
V2 lerp(V2 a, V2 b, float t) {
return {
lerp(a.x, b.x, t),
lerp(a.y, b.y, t)
};
}
V2 lerp(V2 a, V2 b, V2 t) {
return {
lerp(a.x, b.x, t.x),
lerp(a.y, b.y, t.y)
};
}
V2 ilerp(V2 a, V2 b, V2 v) {
return (v - a) / (b - a);
}
V2 remap(V2 in_a, V2 in_b, V2 out_a, V2 out_b, V2 v) {
V2 t = ilerp(in_a, in_b, v);
return lerp(out_a, out_b, t);
}
V3 V3_(float x, float y, float z) {
return { x, y, z };
}
V3 V3_(V2 xy, float z) {
return { xy[0], xy[1], z };
}
V3 V3_(float x, V2 yz) {
return { x, yz[0], yz[1] };
}
V3 operator -(V3 a) {
return {
-a.x,
-a.y,
-a.z
};
}
V3 operator +(V3 a, V3 b) {
return {
a.x + b.x,
a.y + b.y,
a.z + b.z
};
}
V3 operator +=(V3 &a, V3 b) {
return a = a + b;
}
V3 operator -(V3 a, V3 b) {
return {
a.x - b.x,
a.y - b.y,
a.z - b.z
};
}
V3 operator -=(V3 &a, V3 b) {
return a = a - b;
}
V3 operator *(float a, V3 b) {
return {
a * b.x,
a * b.y,
a * b.z
};
}
V3 operator *(V3 a, float b) {
return {
a.x * b,
a.y * b,
a.z * b
};
}
V3 operator *=(V3 &a, float b) {
return a = a * b;
}
V3 operator /(float a, V3 b) {
return {
a / b.x,
a / b.y,
a / b.z
};
}
V3 operator /(V3 a, float b) {
return {
a.x / b,
a.y / b,
a.z / b
};
}
V3 operator /=(V3 &a, float b) {
return a = a / b;
}
V3 operator /(V3 a, V3 b) {
return {
a.x / b.x,
a.y / b.y,
a.z / b.z
};
}
float dot(V3 a, V3 b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
V3 hadamard(V3 a, V3 b) {
return {
a.x * b.x,
a.y * b.y,
a.z * b.z
};
}
V3 cross(V3 a, V3 b) {
return {
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x
};
}
float length_squared(V3 a) {
return dot(a, a);
}
float length(V3 a) {
return square_root(length_squared(a));
}
float reciprocal_length(V3 a) {
return reciprocal_square_root(length_squared(a));
}
V3 normalize(V3 a) {
return a * reciprocal_length(a);
}
V3 clamp01(V3 a) {
return {
clamp01(a.x),
clamp01(a.y),
clamp01(a.z)
};
}
V3 min(V3 a, V3 b) {
return {
min(a.x, b.x),
min(a.y, b.y),
min(a.z, b.z)
};
}
V3 max(V3 a, V3 b) {
return {
max(a.x, b.x),
max(a.y, b.y),
max(a.z, b.z)
};
}
float min(V3 a) {
return min(min(a.x, a.y), a.z);
}
float max(V3 a) {
return max(max(a.x, a.y), a.z);
}
V3 lerp(V3 a, V3 b, float t) {
return {
lerp(a.x, b.x, t),
lerp(a.y, b.y, t),
lerp(a.z, b.z, t)
};
}
V3 lerp(V3 a, V3 b, V3 t) {
return {
lerp(a.x, b.x, t.x),
lerp(a.y, b.y, t.y),
lerp(a.z, b.z, t.z)
};
}
V3 ilerp(V3 a, V3 b, V3 v) {
return (v - a) / (b - a);
}
V3 remap(V3 in_a, V3 in_b, V3 out_a, V3 out_b, V3 v) {
V3 t = ilerp(in_a, in_b, v);
return lerp(out_a, out_b, t);
}
V4 V4_(float x, float y, float z, float w) {
return { x, y, z, w };
}
V4 V4_(V2 xy, V2 zw) {
return { xy[0], xy[1], zw[0], zw[1] };
}
V4 V4_(V2 xy, float z, float w) {
return { xy[0], xy[1], z, w };
}
V4 V4_(float x, V2 yz, float w) {
return { x, yz[0], yz[1], w };
}
V4 V4_(float x, float y, V2 zw) {
return { x, y, zw[0], zw[1] };
}
V4 V4_(V3 xyz, float w) {
return { xyz[0], xyz[1], xyz[2], w };
}
V4 V4_(float x, V3 yzw) {
return { x, yzw[0], yzw[1], yzw[2] };
}
V4 operator -(V4 a) {
return {
-a.x,
-a.y,
-a.z,
-a.w
};
}
V4 operator +(V4 a, V4 b) {
return {
a.x + b.x,
a.y + b.y,
a.z + b.z,
a.w + b.w
};
}
V4 operator +=(V4 &a, V4 b) {
return a = a + b;
}
V4 operator -(V4 a, V4 b) {
return {
a.x - b.x,
a.y - b.y,
a.z - b.z,
a.w - b.w
};
}
V4 operator -=(V4 &a, V4 b) {
return a = a - b;
}
V4 operator *(float a, V4 b) {
return {
a * b.x,
a * b.y,
a * b.z,
a * b.w
};
}
V4 operator *(V4 a, float b) {
return {
a.x * b,
a.y * b,
a.z * b,
a.w * b
};
}
V4 operator *=(V4 &a, float b) {
return a = a * b;
}
V4 operator /(float a, V4 b) {
return {
a / b.x,
a / b.y,
a / b.z,
a / b.w
};
}
V4 operator /(V4 a, float b) {
return {
a.x / b,
a.y / b,
a.z / b,
a.w / b
};
}
V4 operator /=(V4 &a, float b) {
return a = a / b;
}
V4 operator /(V4 a, V4 b) {
return {
a.x / b.x,
a.y / b.y,
a.z / b.z,
a.w / b.w
};
}
float dot(V4 a, V4 b) {
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
V4 hadamard(V4 a, V4 b) {
return {
a.x * b.x,
a.y * b.y,
a.z * b.z,
a.w * b.w
};
}
float length_squared(V4 a) {
return dot(a, a);
}
float length(V4 a) {
return square_root(length_squared(a));
}
float reciprocal_length(V4 a) {
return reciprocal_square_root(length_squared(a));
}
V4 normalize(V4 a) {
return a * reciprocal_length(a);
}
V4 clamp01(V4 a) {
return {
clamp01(a.x),
clamp01(a.y),
clamp01(a.z),
clamp01(a.w)
};
}
V4 min(V4 a, V4 b) {
return {
min(a.x, b.x),
min(a.y, b.y),
min(a.z, b.z),
min(a.w, b.w)
};
}
V4 max(V4 a, V4 b) {
return {
max(a.x, b.x),
max(a.y, b.y),
max(a.z, b.z),
max(a.w, b.w)
};
}
float min(V4 a) {
return min(min(a.x, a.y), min(a.z, a.w));
}
float max(V4 a) {
return max(max(a.x, a.y), max(a.z, a.w));
}
V4 lerp(V4 a, V4 b, float t) {
return {
lerp(a.x, b.x, t),
lerp(a.y, b.y, t),
lerp(a.z, b.z, t),
lerp(a.w, b.w, t)
};
}
V4 lerp(V4 a, V4 b, V4 t) {
return {
lerp(a.x, b.x, t.x),
lerp(a.y, b.y, t.y),
lerp(a.z, b.z, t.z),
lerp(a.w, b.w, t.w)
};
}
V4 ilerp(V4 a, V4 b, V4 v) {
return (v - a) / (b - a);
}
V4 remap(V4 in_a, V4 in_b, V4 out_a, V4 out_b, V4 v) {
V4 t = ilerp(in_a, in_b, v);
return lerp(out_a, out_b, t);
}
M2x2 M2x2_(float _00, float _01,
float _10, float _11) {
return {
_00, _01,
_10, _11,
};
}
M2x2 M2x2_(V2 row0, V2 row1) {
return {
row0[0], row0[1],
row1[0], row1[1],
};
}
M2x2 operator -(M2x2 a){
return {
-a[0][0], -a[0][1],
-a[1][0], -a[1][1]
};
}
M2x2 operator +(M2x2 a, M2x2 b) {
return {
a[0][0] + b[0][0], a[0][1] + b[0][1],
a[1][0] + b[1][0], a[1][1] + b[1][1]
};
}
M2x2 operator +=(M2x2 &a, M2x2 b) {
return a = a + b;
}
M2x2 operator -(M2x2 a, M2x2 b) {
return {
a[0][0] - b[0][0], a[0][1] - b[0][1],
a[1][0] - b[1][0], a[1][1] - b[1][1]
};
}
M2x2 operator -=(M2x2 &a, M2x2 b) {
return a = a - b;
}
M2x2 operator *(float a, M2x2 b) {
return {
a * b[0][0], a * b[0][1],
a * b[1][0], a * b[1][1]
};
}
M2x2 operator *(M2x2 a, float b) {
return {
a[0][0] * b, a[0][1] * b,
a[1][0] * b, a[1][1] * b
};
}
M2x2 operator *=(M2x2 &a, float b) {
return a = a * b;
}
M2x2 operator *(M2x2 a, M2x2 b) {
return {
a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1],
a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]
};
}
V2 operator *(M2x2 a, V2 b) {
return {
a[0][0] * b[0] + a[0][1] * b[1],
a[1][0] * b[0] + a[1][1] * b[1],
};
}
M2x2 transpose(M2x2 a) {
return {
a[0][0], a[1][0],
a[0][1], a[1][1]
};
}
M3x3 M3x3_(float _00, float _01, float _02,
float _10, float _11, float _12,
float _20, float _21, float _22) {
return {
_00, _01, _02,
_10, _11, _12,
_20, _21, _22
};
}
M3x3 M3x3_(V3 row0, V3 row1, V3 row2) {
return {
row0[0], row0[1], row0[2],
row1[0], row1[1], row1[2],
row2[0], row2[1], row2[2]
};
}
M3x3 operator -(M3x3 a) {
return {
-a[0][0], -a[0][1], -a[0][1],
-a[1][0], -a[1][1], -a[1][2],
-a[2][0], -a[2][1], -a[2][2]
};
}
M3x3 operator +(M3x3 a, M3x3 b) {
return {
a[0][0] + b[0][0], a[0][1] + b[0][1], a[0][2] + b[0][2],
a[1][0] + b[1][0], a[1][1] + b[1][1], a[1][2] + b[1][2],
a[2][0] + b[2][0], a[2][1] + b[2][1], a[2][2] + b[2][2]
};
}
M3x3 operator +=(M3x3 &a, M3x3 b) {
return a = a + b;
}
M3x3 operator -(M3x3 a, M3x3 b) {
return {
a[0][0] - b[0][0], a[0][1] - b[0][1], a[0][2] - b[0][2],
a[1][0] - b[1][0], a[1][1] - b[1][1], a[1][2] - b[1][2],
a[2][0] - b[2][0], a[2][1] - b[2][1], a[2][2] - b[2][2]
};
}
M3x3 operator -=(M3x3 &a, M3x3 b) {
return a = a - b;
}
M3x3 operator *(float a, M3x3 b) {
return {
a * b[0][0], a * b[0][1], a * b[0][2],
a * b[1][0], a * b[1][1], a * b[1][2],
a * b[2][0], a * b[2][1], a * b[2][2]
};
}
M3x3 operator *(M3x3 a, float b) {
return {
a[0][0] * b, a[0][1] * b, a[0][2] * b,
a[1][0] * b, a[1][1] * b, a[1][2] * b,
a[2][0] * b, a[2][1] * b, a[2][2] * b
};
}
M3x3 operator *=(M3x3 &a, float b) {
return a = a * b;
}
M3x3 operator *(M3x3 a, M3x3 b) {
return {
a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0], a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1], a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2],
a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0], a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1], a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[0][2] * b[2][2],
a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0], a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1], a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[0][2] * b[2][2]
};
}
V3 operator *(M3x3 a, V3 b) {
return {
a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2],
a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2],
a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2]
};
}
M3x3 transpose(M3x3 a) {
return {
a[0][0], a[1][0], a[2][0],
a[0][1], a[1][1], a[2][1],
a[0][2], a[1][2], a[2][2]
};
}
M4x4 M4x4_(float _00, float _01, float _02, float _03,
float _10, float _11, float _12, float _13,
float _20, float _21, float _22, float _23,
float _30, float _31, float _32, float _33) {
return {
_00, _01, _02, _03,
_10, _11, _12, _13,
_20, _21, _22, _23,
_30, _31, _32, _33
};
}
M4x4 M4x4_(V4 row0, V4 row1, V4 row2, V4 row3) {
return {
row0[0], row0[1], row0[2], row0[3],
row1[0], row1[1], row1[2], row1[3],
row2[0], row2[1], row2[2], row2[3],
row3[0], row3[1], row3[2], row3[3]
};
}
M4x4 operator -(M4x4 a) {
return {
-a[0][0], -a[0][1], -a[0][1], -a[0][3],
-a[1][0], -a[1][1], -a[1][2], -a[1][3],
-a[2][0], -a[2][1], -a[2][2], -a[2][3],
-a[3][0], -a[3][1], -a[3][2], -a[3][3]
};
}
M4x4 operator +(M4x4 a, M4x4 b) {
return {
a[0][0] + b[0][0], a[0][1] + b[0][1], a[0][2] + b[0][2], a[0][3] + b[0][3],
a[1][0] + b[1][0], a[1][1] + b[1][1], a[1][2] + b[1][2], a[1][3] + b[1][3],
a[2][0] + b[2][0], a[2][1] + b[2][1], a[2][2] + b[2][2], a[2][3] + b[2][3],
a[3][0] + b[3][0], a[3][1] + b[3][1], a[3][2] + b[3][2], a[3][3] + b[3][3]
};
}
M4x4 operator +=(M4x4 &a, M4x4 b) {
return a = a + b;
}
M4x4 operator -(M4x4 a, M4x4 b) {
return {
a[0][0] - b[0][0], a[0][1] - b[0][1], a[0][2] - b[0][2], a[0][3] - b[0][3],
a[1][0] - b[1][0], a[1][1] - b[1][1], a[1][2] - b[1][2], a[1][3] - b[1][3],
a[2][0] - b[2][0], a[2][1] - b[2][1], a[2][2] - b[2][2], a[2][3] - b[2][3],
a[3][0] - b[3][0], a[3][1] - b[3][1], a[3][2] - b[3][2], a[3][3] - b[3][3]
};
}
M4x4 operator -=(M4x4 &a, M4x4 b) {
return a = a - b;
}
M4x4 operator *(float a, M4x4 b) {
return {
a * b[0][0], a * b[0][1], a * b[0][2], a * b[0][3],
a * b[1][0], a * b[1][1], a * b[1][2], a * b[1][3],
a * b[2][0], a * b[2][1], a * b[2][2], a * b[2][3],
a * b[3][0], a * b[3][1], a * b[3][2], a * b[3][3]
};
}
M4x4 operator *(M4x4 a, float b) {
return {
a[0][0] * b, a[0][1] * b, a[0][2] * b, a[0][3] * b,
a[1][0] * b, a[1][1] * b, a[1][2] * b, a[1][3] * b,
a[2][0] * b, a[2][1] * b, a[2][2] * b, a[2][3] * b,
a[3][0] * b, a[3][1] * b, a[3][2] * b, a[3][3] * b
};
}
M4x4 operator *=(M4x4 &a, float b) {
return a = a * b;
}
M4x4 operator *(M4x4 a, M4x4 b) {
return {
a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0] + a[0][3] * b[3][0], a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1] + a[0][3] * b[3][1], a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2] + a[0][3] * b[3][2], a[0][0] * b[0][3] + a[0][1] * b[1][3] + a[0][2] * b[2][3] + a[0][3] * b[3][3],
a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0] + a[1][3] * b[3][0], a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1] + a[1][3] * b[3][1], a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2] + a[1][3] * b[3][2], a[1][0] * b[0][3] + a[1][1] * b[1][3] + a[1][2] * b[2][3] + a[1][3] * b[3][3],
a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0] + a[2][3] * b[3][0], a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1] + a[2][3] * b[3][1], a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2] + a[2][3] * b[3][2], a[2][0] * b[0][3] + a[2][1] * b[1][3] + a[2][2] * b[2][3] + a[2][3] * b[3][3],
a[3][0] * b[0][0] + a[3][1] * b[1][0] + a[3][2] * b[2][0] + a[3][3] * b[3][0], a[3][0] * b[0][1] + a[3][1] * b[1][1] + a[3][2] * b[2][1] + a[3][3] * b[3][1], a[3][0] * b[0][2] + a[3][1] * b[1][2] + a[3][2] * b[2][2] + a[3][3] * b[3][2], a[3][0] * b[0][3] + a[3][1] * b[1][3] + a[3][2] * b[2][3] + a[3][3] * b[3][3],
};
}
V4 operator *(M4x4 a, V4 b) {
return {
a[0][0] * b[0] + a[0][1] * b[1] + a[0][2] * b[2] + a[0][3] * b[3],
a[1][0] * b[0] + a[1][1] * b[1] + a[1][2] * b[2] + a[1][3] * b[3],
a[2][0] * b[0] + a[2][1] * b[1] + a[2][2] * b[2] + a[2][3] * b[3],
a[3][0] * b[0] + a[3][1] * b[1] + a[3][2] * b[2] + a[3][3] * b[3],
};
}
M4x4 transpose(M4x4 a) {
return {
a[0][0], a[1][0], a[2][0], a[3][0],
a[0][1], a[1][1], a[2][1], a[3][1],
a[0][2], a[1][2], a[2][2], a[3][2],
a[0][3], a[1][3], a[2][3], a[3][3],
};
}
M4x4 view(V3 player_pos, float tilt, float camera_distance) {
float s = sinf(tilt);
float c = cosf(tilt);
return {
1, 0, 0, -player_pos.x,
0, c, s, c * -player_pos.y,
0, -s, c, s * player_pos.y - camera_distance,
0, 0, 0, 1,
};
}
M4x4 inverse_view(V3 player_pos, float tilt, float camera_distance) {
float s = sinf(tilt);
float c = cosf(tilt);
return {
1, 0, 0, player_pos.x,
0, c, -s, -s * camera_distance + player_pos.y,
0, s, c, c * camera_distance,
0, 0, 0, 1,
};
}
M4x4 projection(float fovy, float aspect, float near) {
float g = 1.0 / tanf(fovy * 0.5);
return {
g / aspect, 0, 0, 0,
0, g, 0, 0,
0, 0, 0, near,
0, 0, -1, 0,
};
}
M4x4 inverse_projection(float fovy, float aspect, float near) {
float g = 1.0 / tanf(fovy * 0.5);
return {
aspect / g, 0, 0, 0,
0, 1 / g, 0, 0,
0, 0, 0, -1,
0, 0, 1 / near, 0,
};
}
}
-489
View File
@@ -1,489 +0,0 @@
#pragma once
#include <stddef.h>
#undef min
#undef max
namespace M {
template<typename T>
constexpr inline T min(T a, T b) {
return (a < b) ? a : b;
}
template<typename T>
constexpr inline T max(T a, T b) {
return (a > b) ? a : b;
}
template<typename T>
constexpr inline T clamp(T min, T a, T max) {
return M::min(M::max(min, a), max);
}
template<typename T>
constexpr inline T clamp01(T a) {
return clamp((T)0, a, (T)1);
}
float square_root(float a);
double square_root(double a);
float reciprocal_square_root(float a);
double reciprocal_square_root(double a);
float lerp (float a, float b, float t);
float ilerp(float a, float b, float v);
float remap(float in_a, float in_b, float out_a, float out_b, float v);
float radians(float degrees);
union V2 {
struct {
float x;
float y;
};
struct {
float u;
float v;
};
struct {
float width;
float height;
};
struct {
float E[2];
};
constexpr float &operator [](size_t index) {
return E[index];
}
};
V2 V2_(float x, float y);
V2 operator - (V2 a);
V2 operator + (V2 a, V2 b);
V2 operator +=(V2 &a, V2 b);
V2 operator - (V2 a, V2 b);
V2 operator -=(V2 &a, V2 b);
V2 operator * (float a, V2 b);
V2 operator * (V2 a, float b);
V2 &operator *=(V2 &a, float b);
V2 operator / (float a, V2 b);
V2 operator / (V2 a, float b);
V2 &operator /=(V2 &a, float b);
V2 operator / (V2 a, V2 b);
float dot (V2 a, V2 b);
V2 hadamard(V2 a, V2 b);
float length_squared (V2 a);
float length (V2 a);
float reciprocal_length(V2 a);
V2 normalize (V2 a);
V2 perpendicular(V2 a);
V2 clamp01 (V2 a);
V2 min(V2 a, V2 b);
V2 max(V2 a, V2 b);
float min(V2 a);
float max(V2 a);
V2 lerp (V2 a, V2 b, float t);
V2 lerp (V2 a, V2 b, V2 t);
V2 ilerp(V2 a, V2 b, V2 v);
V2 remap(V2 in_a, V2 in_b, V2 out_a, V2 out_b, V2 v);
union V3 {
struct {
float x;
float y;
float z;
};
struct {
float r;
float g;
float b;
};
struct {
float u;
float v;
float s;
};
struct {
V2 xy;
float _z;
};
struct {
float _x;
V2 yz;
};
struct {
V2 uv;
float _s;
};
struct {
float _u;
V2 vs;
};
struct {
V2 rg;
float _b;
};
struct {
float _r;
V2 gb;
};
struct {
float E[3];
};
constexpr float &operator [](size_t index) {
return E[index];
}
};
V3 V3_(float x, float y, float z);
V3 V3_(V2 xy, float z);
V3 V3_(float x, V2 yz);
V3 operator - (V3 a);
V3 operator + (V3 a, V3 b);
V3 operator +=(V3 &a, V3 b);
V3 operator - (V3 a, V3 b);
V3 operator -=(V3 &a, V3 b);
V3 operator * (float a, V3 b);
V3 operator * (V3 a, float b);
V3 operator *=(V3 &a, float b);
V3 operator / (float a, V3 b);
V3 operator / (V3 a, float b);
V3 operator /=(V3 &a, float b);
V3 operator / (V3 a, V3 b);
float dot (V3 a, V3 b);
V3 hadamard(V3 a, V3 b);
V3 cross (V3 a, V3 b);
float length_squared (V3 a);
float length (V3 a);
float reciprocal_length(V3 a);
V3 normalize(V3 a);
V3 clamp01 (V3 a);
V3 min(V3 a, V3 b);
V3 max(V3 a, V3 b);
float min(V3 a);
float max(V3 a);
V3 lerp (V3 a, V3 b, float t);
V3 lerp (V3 a, V3 b, V3 t);
V3 ilerp(V3 a, V3 b, V3 v);
V3 remap(V3 in_a, V3 in_b, V3 out_a, V3 out_b, V3 v);
union V4 {
struct {
float x;
float y;
float z;
float w;
};
struct {
float r;
float g;
float b;
float a;
};
struct {
float u;
float v;
float s;
float t;
};
struct {
V2 xy;
V2 zw;
};
struct {
float _x;
V2 yz;
float _w;
};
struct {
V2 uv0;
V2 uv1;
};
struct {
V2 uv;
V2 st;
};
struct {
float _u;
V2 vs;
float _t;
};
struct {
V2 rg;
V2 ba;
};
struct {
float _r;
V2 gb;
float _a;
};
struct {
V3 xyz;
float _w2;
};
struct {
float _x2;
V3 yzw;
};
struct {
V3 rgb;
float _a2;
};
struct {
float _r2;
V3 gba;
};
struct {
V3 uvs;
float _t2;
};
struct {
float _u2;
V3 vst;
};
struct {
float E[4];
};
constexpr float &operator [](size_t index) {
return E[index];
}
};
V4 V4_(float x, float y, float z, float w);
V4 V4_(V2 xy, V2 zw);
V4 V4_(V2 xy, float z, float w);
V4 V4_(float x, V2 yz, float w);
V4 V4_(float x, float y, V2 zw);
V4 V4_(V3 xyz, float w);
V4 V4_(float x, V3 yzw);
V4 operator - (V4 a);
V4 operator + (V4 a, V4 b);
V4 operator +=(V4 &a, V4 b);
V4 operator - (V4 a, V4 b);
V4 operator -=(V4 &a, V4 b);
V4 operator * (float a, V4 b);
V4 operator * (V4 a, float b);
V4 operator *=(V4 &a, float b);
V4 operator / (float a, V4 b);
V4 operator / (V4 a, float b);
V4 operator /=(V4 &a, float b);
V4 operator / (V4 a, V4 b);
float dot (V4 a, V4 b);
V4 hadamard(V4 a, V4 b);
float length_squared (V4 a);
float length (V4 a);
float reciprocal_length(V4 a);
V4 normalize(V4 a);
V4 clamp01 (V4 a);
V4 min(V4 a, V4 b);
V4 max(V4 a, V4 b);
float min(V4 a);
float max(V4 a);
V4 lerp (V4 a, V4 b, float t);
V4 lerp (V4 a, V4 b, V4 t);
V4 ilerp(V4 a, V4 b, V4 v);
V4 remap(V4 in_a, V4 in_b, V4 out_a, V4 out_b, V4 v);
union M2x2 {
struct {
float _00; float _01;
float _10; float _11;
};
struct {
float E[2][2];
};
struct {
V2 V[2];
};
constexpr V2 &operator [](size_t row) {
return V[row];
}
constexpr static M2x2 identity() {
return {
1.0f, 0.0f,
0.0f, 1.0f
};
}
};
M2x2 M2x2_(float _00, float _01,
float _10, float _11);
M2x2 M2x2_(V2 row0, V2 row1);
M2x2 operator - (M2x2 a);
M2x2 operator + (M2x2 a, M2x2 b);
M2x2 operator +=(M2x2 &a, M2x2 b);
M2x2 operator - (M2x2 a, M2x2 b);
M2x2 operator -=(M2x2 &a, M2x2 b);
M2x2 operator * (float a, M2x2 b);
M2x2 operator * (M2x2 a, float b);
M2x2 operator *=(M2x2 &a, float b);
M2x2 operator * (M2x2 a, M2x2 b);
V2 operator * (M2x2 a, V2 b);
M2x2 transpose(M2x2 a);
union M3x3 {
struct {
float _00; float _01; float _02;
float _10; float _11; float _12;
float _20; float _21; float _22;
};
struct {
float E[3][3];
};
struct {
V3 V[3];
};
constexpr V3 &operator [](size_t row) {
return V[row];
}
constexpr static M3x3 identity() {
return {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
}
};
M3x3 M3x3_(float _00, float _01, float _02,
float _10, float _11, float _12,
float _20, float _21, float _22);
M3x3 M3x3_(V3 row0, V3 row1, V3 row2);
M3x3 operator - (M3x3 a);
M3x3 operator + (M3x3 a, M3x3 b);
M3x3 operator +=(M3x3 &a, M3x3 b);
M3x3 operator - (M3x3 a, M3x3 b);
M3x3 operator -=(M3x3 &a, M3x3 b);
M3x3 operator * (float a, M3x3 b);
M3x3 operator * (M3x3 a, float b);
M3x3 operator *=(M3x3 &a, float b);
M3x3 operator * (M3x3 a, M3x3 b);
V3 operator * (M3x3 a, V3 b);
M3x3 transpose(M3x3 a);
union M4x4 {
struct {
float _00; float _01; float _02; float _03;
float _10; float _11; float _12; float _13;
float _20; float _21; float _22; float _23;
float _30; float _31; float _32; float _33;
};
struct {
float E[4][4];
};
struct {
V4 V[4];
};
constexpr V4 &operator [](size_t row) {
return V[row];
}
constexpr static M4x4 identity() {
return {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
}
};
M4x4 M4x4_(float _00, float _01, float _02, float _03,
float _10, float _11, float _12, float _13,
float _20, float _21, float _22, float _23,
float _30, float _31, float _32, float _33);
M4x4 M4x4_(V4 row0, V4 row1, V4 row2, V4 row3);
M4x4 operator - (M4x4 a);
M4x4 operator + (M4x4 a, M4x4 b);
M4x4 operator +=(M4x4 &a, M4x4 b);
M4x4 operator - (M4x4 a, M4x4 b);
M4x4 operator -=(M4x4 &a, M4x4 b);
M4x4 operator * (float a, M4x4 b);
M4x4 operator * (M4x4 a, float b);
M4x4 operator *=(M4x4 &a, float b);
M4x4 operator * (M4x4 a, M4x4 b);
V4 operator * (M4x4 a, V4 b);
M4x4 transpose(M4x4 a);
M4x4 view (V3 player_pos, float tilt, float camera_distance);
M4x4 inverse_view(V3 player_pos, float tilt, float camera_distance);
M4x4 projection (float fovy, float aspect, float near);
M4x4 inverse_projection(float fovy, float aspect, float near);
}