From 949261f56f7c99a79e495b7d84bf8abc71f54f50 Mon Sep 17 00:00:00 2001
From: talha <sarcxd@gmail.com>
Date: Thu, 31 Oct 2024 00:24:52 +0500
Subject: Added ColumnMajor matrix multiplication.

Main code path is disabled until I get everything working correctly.
Also added tags to gitignore
---
 .gitignore      |  1 +
 source/main.cpp | 60 +++++++++++++++++++++++++++++++---
 source/math.h   | 99 ++++++++++++++++++++++++++++++++++++++++++---------------
 3 files changed, 130 insertions(+), 30 deletions(-)

diff --git a/.gitignore b/.gitignore
index 567609b..332b722 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 build/
+tags
diff --git a/source/main.cpp b/source/main.cpp
index 0e38806..2035da3 100755
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -27,12 +27,13 @@
 * - Fixed framerate to prevent weird quirks with movement
 * - Basic camera follower
 * TODO:
+* - move from row-major to column major setup for math library
+* - Efficient Quad Renderer
 * - Some way to make and define levels
 * - Update camera follower for centering player in view (with limits) after
 *   a few seconds (maybe like 2 seconds)
 * - Level completion Object
 * - Implement Broad Phase Collision for efficient collision handling 
-* - Efficient Quad Renderer
 * - Audio
 * - Level Creation
 */
@@ -333,10 +334,10 @@ void gl_draw_colored_quad(
   // setting quad size
   Mat4 model = init_value4m(1.0);
   Mat4 scale = scaling_matrix4m(size.x, size.y, 0.0f);
-  model = multiply4m(scale, model);
+  model = multiply4m_rm(scale, model);
   // setting quad position
   Mat4 translation = translation_matrix4m(position.x, position.y, position.z);
-  model = multiply4m(translation, model);
+  model = multiply4m_rm(translation, model);
   // setting color
   glUniform3fv(glGetUniformLocation(renderer->cq_sp, "Color"), 1, color.data);
   
@@ -491,7 +492,7 @@ void gl_render_text(GLRenderer *renderer, char* text, Vec2 position, r32 size, V
       
       Mat4 sm = scaling_matrix4m(w, h, 0);
       Mat4 tm = translation_matrix4m(xpos, ypos, 0);
-      Mat4 model = multiply4m(tm, sm);
+      Mat4 model = multiply4m_rm(tm, sm);
       renderer->ui_text.transforms[running_index] = model;
       renderer->ui_text.char_indexes[running_index] = int(*char_iter);
       
@@ -597,6 +598,55 @@ Vec3 get_screen_position_from_percent(GameState state, Vec3 v) {
 
 int main(int argc, char* argv[])
 {
+  // @matrix testing
+  Mat4ColumnMajor a = {0};
+  Mat4ColumnMajor b = {0};
+
+  a.data[0][0] = 4;
+  a.data[0][1] = 2;
+  a.data[0][2] = 0;
+  a.data[0][3] = 0;
+
+  a.data[1][0] = 0;
+  a.data[1][1] = 8;
+  a.data[1][2] = 1;
+  a.data[1][3] = 0;
+
+  a.data[2][0] = 0;
+  a.data[2][1] = 1;
+  a.data[2][2] = 0;
+  a.data[2][3] = 0;
+
+  a.data[3][0] = 0;
+  a.data[3][1] = 0;
+  a.data[3][2] = 0;
+  a.data[3][3] = 0;
+
+  b.data[0][0] = 4;
+  b.data[0][1] = 2;
+  b.data[0][2] = 1;
+  b.data[0][3] = 0;
+
+  b.data[1][0] = 2;
+  b.data[1][1] = 0;
+  b.data[1][2] = 4;
+  b.data[1][3] = 0;
+
+  b.data[2][0] = 9;
+  b.data[2][1] = 4;
+  b.data[2][2] = 2;
+  b.data[2][3] = 0;
+
+  b.data[3][0] = 0;
+  b.data[3][1] = 0;
+  b.data[3][2] = 0;
+  b.data[3][3] = 0;
+
+  Mat4 product = multiply4m_cm(a,b);
+
+  int dbg = 1;
+  return 0;
+#if DISABLE_MAIN_GAME
   u32 scr_width = 1024;
   u32 scr_height = 768;
   
@@ -1195,6 +1245,7 @@ int main(int argc, char* argv[])
                    Vec3{0.0f, 0.0f, 0.0f});   // color
     
     sprintf(fmt_buffer, "%f pixels", pd_1.x);
+
     gl_render_text(renderer,
                    fmt_buffer,
                    Vec2{500.0f, 200.0f},       // position
@@ -1218,4 +1269,5 @@ int main(int argc, char* argv[])
   SDL_DestroyWindow(window);
   SDL_Quit();
   return 0;
+#endif
 }
diff --git a/source/math.h b/source/math.h
index 7deb0bc..d7bf215 100755
--- a/source/math.h
+++ b/source/math.h
@@ -108,12 +108,19 @@ union Vec4 {
 	r32 data[4];
 };
 
+// @note: matrix and all matrix operations will be done in column major
+// @todo: be able to specify and configure this in the future
+// possibly through separate functions
 union Mat4 {
 	Vec4 xyzw[4];
 	r32 data[4][4];
 	r32 buffer[16];
 };
 
+typedef Mat4 Mat4RowMajor;
+typedef Mat4 Mat4ColumnMajor;
+
+
 // ==== Vec2 ====
 Vec2 v2(r32 v) {
   return Vec2{v, v};
@@ -346,7 +353,7 @@ Mat4 subtract4m(Mat4 a, Mat4 b)
 	return res;
 }
 
-Vec4 multiply4vm(Vec4 vec, Mat4 mat)
+Vec4 multiply4mv_rm(Mat4RowMajor mat, Vec4 vec)
 {
     /*
      * @note: Incase I get confused about this in the future.
@@ -372,23 +379,62 @@ Vec4 multiply4vm(Vec4 vec, Mat4 mat)
 	return res;
 }
 
-Mat4 multiply4m(Mat4 a, Mat4 b)
+Mat4RowMajor multiply4m_rm(Mat4RowMajor a, Mat4RowMajor b) 
 {
-	Mat4 res = { 0 };
-	
-	res.xyzw[0] = multiply4vm(a.xyzw[0], b);
-	res.xyzw[1] = multiply4vm(a.xyzw[1], b);
-	res.xyzw[2] = multiply4vm(a.xyzw[2], b);
-	res.xyzw[3] = multiply4vm(a.xyzw[3], b);
-    
-	return res;
+  Mat4RowMajor res = { 0 };
+
+  res.xyzw[0] = multiply4mv_rm(b, a.xyzw[0]);
+  res.xyzw[1] = multiply4mv_rm(b, a.xyzw[1]);
+  res.xyzw[2] = multiply4mv_rm(b, a.xyzw[2]);
+  res.xyzw[3] = multiply4mv_rm(b, a.xyzw[3]);
+
+  return res;
+}
+
+Vec4 multiply4mv_cm(Mat4ColumnMajor m, Vec4 v)
+{
+  Vec4 res = {0};
+
+  res.x += m.data[0][0]*v.x;
+  res.y += m.data[0][1]*v.x;
+  res.z += m.data[0][2]*v.x;
+  res.w += m.data[0][3]*v.x;
+
+  res.x += m.data[1][0]*v.y;
+  res.y += m.data[1][1]*v.y;
+  res.z += m.data[1][2]*v.y;
+  res.w += m.data[1][3]*v.y;
+
+  res.x += m.data[2][0]*v.z;
+  res.y += m.data[2][1]*v.z;
+  res.z += m.data[2][2]*v.z;
+  res.w += m.data[2][3]*v.z;
+
+  res.x += m.data[3][0]*v.w;
+  res.y += m.data[3][1]*v.w;
+  res.z += m.data[3][2]*v.w;
+  res.w += m.data[3][3]*v.w;
+
+  return res;
 }
 
+Mat4ColumnMajor multiply4m_cm(Mat4ColumnMajor a, Mat4ColumnMajor b) 
+{
+  Mat4ColumnMajor res = { 0 };
+
+  res.xyzw[0] = multiply4mv_cm(b, a.xyzw[0]);
+  res.xyzw[1] = multiply4mv_cm(b, a.xyzw[1]);
+  res.xyzw[2] = multiply4mv_cm(b, a.xyzw[2]);
+  res.xyzw[3] = multiply4mv_cm(b, a.xyzw[3]);
+
+  return res;
+}
 // ==== Matrix Transformation ====
 
-Mat4 scaling_matrix4m(r32 x, r32 y, r32 z)	// generates a 4x4 scaling matrix for scaling each of the x,y,z axis
+Mat4RowMajor scaling_matrix4m(r32 x, r32 y, r32 z)	
 {
-	Mat4 res = init_value4m(1.0f);
+  // generates a 4x4 scaling matrix for scaling each of the x,y,z axis
+	Mat4RowMajor res = init_value4m(1.0f);
 	res.data[0][0] = x;
 	res.data[1][1] = y;
 	res.data[2][2] = z;
@@ -396,9 +442,10 @@ Mat4 scaling_matrix4m(r32 x, r32 y, r32 z)	// generates a 4x4 scaling matrix for
 	return res;
 }
 
-Mat4 translation_matrix4m(r32 x, r32 y, r32 z)	// generates a 4x4 translation matrix for translation along each of the x,y,z axis
+Mat4RowMajor translation_matrix4m(r32 x, r32 y, r32 z)	
 {
-	Mat4 res = init_value4m(1.0f);
+  // generates a 4x4 translation matrix for translation along each of the x,y,z axis
+	Mat4RowMajor res = init_value4m(1.0f);
 	res.data[0][3] = x;
 	res.data[1][3] = y;
 	res.data[2][3] = z;
@@ -406,9 +453,9 @@ Mat4 translation_matrix4m(r32 x, r32 y, r32 z)	// generates a 4x4 translation ma
 	return res;
 }
 
-Mat4 rotation_matrix4m(r32 angle_radians, Vec3 axis)	// generates a 4x4 rotation matrix for rotation along each of the x,y,z axis
+Mat4RowMajor rotation_matrix4m(r32 angle_radians, Vec3 axis)	// generates a 4x4 rotation matrix for rotation along each of the x,y,z axis
 {
-	Mat4 res = init_value4m(1.0f);
+	Mat4RowMajor res = init_value4m(1.0f);
 	axis = normalize3v(axis);
 	
 	r32 cos_theta = cosf(angle_radians);
@@ -430,9 +477,9 @@ Mat4 rotation_matrix4m(r32 angle_radians, Vec3 axis)	// generates a 4x4 rotation
 	return res;
 }
 
-Mat4 perspective_projection4m(r32 left, r32 right, r32 bottom, r32 top, r32 near, r32 far)
+Mat4RowMajor perspective_projection4m(r32 left, r32 right, r32 bottom, r32 top, r32 near, r32 far)
 {
-	Mat4 res = { 0 };
+	Mat4RowMajor res = { 0 };
 	
 	res.data[0][0] = (2.0 * near)/(right - left);
 	res.data[0][2] = (right + left)/(right - left);
@@ -448,11 +495,11 @@ Mat4 perspective_projection4m(r32 left, r32 right, r32 bottom, r32 top, r32 near
 	return res;
 }
 
-Mat4 perspective4m(r32 fov, r32 aspect_ratio, r32 near, r32 far)
+Mat4RowMajor perspective4m(r32 fov, r32 aspect_ratio, r32 near, r32 far)
 {
 	r32 cotangent = 1.0f / tanf(fov / 2.0f);
 	
-	Mat4 res = { 0 };
+	Mat4RowMajor res = { 0 };
     
 	res.data[0][0] = cotangent / aspect_ratio;
 	
@@ -466,10 +513,10 @@ Mat4 perspective4m(r32 fov, r32 aspect_ratio, r32 near, r32 far)
 	return res;
 }
 
-Mat4 orthographic_projection4m(r32 left, r32 right, r32 bottom, r32 top, r32 near, r32 far)
+Mat4RowMajor orthographic_projection4m(r32 left, r32 right, r32 bottom, r32 top, r32 near, r32 far)
 {
   // @todo: understand the derivation once I am done experimenting
-  Mat4 res = { 0 };
+  Mat4RowMajor res = { 0 };
   res.data[0][0] = 2.0f/(right - left);   res.data[0][3] = -(right + left)/(right - left);
   res.data[1][1] = 2.0f/(top - bottom);   res.data[1][3] = -(top + bottom)/(top - bottom);
   res.data[2][2] = -2.0f/(far - near);    res.data[2][3] = -(far + near)/(far - near);
@@ -478,7 +525,7 @@ Mat4 orthographic_projection4m(r32 left, r32 right, r32 bottom, r32 top, r32 nea
   return res;
 }
 
-Mat4 lookat4m(Vec3 up, Vec3 forward, Vec3 right, Vec3 position)
+Mat4RowMajor lookat4m(Vec3 up, Vec3 forward, Vec3 right, Vec3 position)
 {
 	/*
 	* @note: The construction of the lookat matrix is not obvious. For that reason here is the supplemental matrial I have used to understand
@@ -490,7 +537,7 @@ Mat4 lookat4m(Vec3 up, Vec3 forward, Vec3 right, Vec3 position)
   *
   * I am guessing this is not useful for 2D stuff
 	*/
-	Mat4 res = init_value4m(1.0);
+	Mat4RowMajor res = init_value4m(1.0);
 	res.xyzw[0] = Vec4{ right.x,		right.y,	 right.z,		-dot_multiply3v(right, position) };
 	res.xyzw[1] = Vec4{ up.x,				up.y,			 up.z,			-dot_multiply3v(up, position) };
 	res.xyzw[2] = Vec4{ forward.x,  forward.y, forward.z, -dot_multiply3v(forward, position) };
@@ -510,7 +557,7 @@ Vec3 camera_look_around(r32 angle_pitch, r32 angle_yaw)
   return camera_look;
 }
 
-Mat4 camera_create4m(Vec3 camera_pos, Vec3 camera_look, Vec3 camera_up)
+Mat4RowMajor camera_create4m(Vec3 camera_pos, Vec3 camera_look, Vec3 camera_up)
 {
 	// @note: We do this because this allows the camera to have the axis it looks at
 	// inwards be the +z axis.
@@ -520,7 +567,7 @@ Mat4 camera_create4m(Vec3 camera_pos, Vec3 camera_look, Vec3 camera_up)
 	Vec3 camera_right_dir   = normalize3v(cross_multiply3v(camera_up, camera_forward_dir));
 	Vec3 camera_up_dir      = normalize3v(cross_multiply3v(camera_forward_dir, camera_right_dir));
     
-	Mat4 res = lookat4m(camera_up_dir, camera_forward_dir, camera_right_dir, camera_pos);
+	Mat4RowMajor res = lookat4m(camera_up_dir, camera_forward_dir, camera_right_dir, camera_pos);
     
 	return res;
 }
-- 
cgit v1.2.3