nuclear option
This commit is contained in:
parent
6991731160
commit
541c4dec44
@ -18,8 +18,8 @@ void* array_hold(void* array, int count, int item_size) {
|
||||
return array;
|
||||
} else {
|
||||
int needed_size = ARRAY_OCCUPIED(array) + count;
|
||||
int double_curr = ARRAY_CAPACITY(array) * 2;
|
||||
int capacity = needed_size > double_curr ? needed_size : double_curr;
|
||||
int float_curr = ARRAY_CAPACITY(array) * 2;
|
||||
int capacity = needed_size > float_curr ? needed_size : float_curr;
|
||||
int occupied = needed_size;
|
||||
int raw_size = sizeof(int) * 2 + item_size * capacity;
|
||||
int* base = (int*)realloc(ARRAY_RAW_DATA(array), raw_size);
|
||||
@ -37,4 +37,4 @@ void array_free(void* array) {
|
||||
if (array != NULL) {
|
||||
free(ARRAY_RAW_DATA(array));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,4 +11,4 @@ void* array_hold(void* array, int count, int item_size);
|
||||
int array_length(void* array);
|
||||
void array_free(void* array);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
#include "display.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "triangle.h"
|
||||
|
||||
#include "display.h"
|
||||
SDL_Window* window = NULL;
|
||||
SDL_Renderer* renderer = NULL;
|
||||
uint32_t* color_buffer = NULL;
|
||||
@ -20,8 +16,8 @@ bool initialize_window(void) {
|
||||
// Set width and height of the SDL window with the max screen resolution
|
||||
SDL_DisplayMode display_mode;
|
||||
SDL_GetCurrentDisplayMode(0, &display_mode);
|
||||
window_width = 800;//display_mode.w;
|
||||
window_height = 800;//display_mode.h;
|
||||
window_width = display_mode.w;
|
||||
window_height = display_mode.h;
|
||||
|
||||
// Create a SDL Window
|
||||
window = SDL_CreateWindow(
|
||||
@ -30,7 +26,7 @@ bool initialize_window(void) {
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
window_width,
|
||||
window_height,
|
||||
0//SDL_WINDOW_BORDERLESS
|
||||
SDL_WINDOW_BORDERLESS
|
||||
);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window.\n");
|
||||
@ -61,23 +57,11 @@ void draw_pixel(int x, int y, uint32_t color) {
|
||||
}
|
||||
}
|
||||
|
||||
void draw_rect(int x, int y, int width, int height, uint32_t color) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
int current_x = x + i;
|
||||
int current_y = y + j;
|
||||
draw_pixel(current_x, current_y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void draw_line(int x0, int y0, int x1, int y1, uint32_t color) {
|
||||
int delta_x = (x1 - x0);
|
||||
int delta_y = (y1 - y0);
|
||||
|
||||
int longest_side_length = abs(delta_x) > abs(delta_y) ? abs(delta_x) : abs(delta_y);
|
||||
int longest_side_length = (abs(delta_x) >= abs(delta_y)) ? abs(delta_x) : abs(delta_y);
|
||||
|
||||
float x_inc = delta_x / (float)longest_side_length;
|
||||
float y_inc = delta_y / (float)longest_side_length;
|
||||
@ -90,7 +74,16 @@ void draw_line(int x0, int y0, int x1, int y1, uint32_t color) {
|
||||
current_x += x_inc;
|
||||
current_y += y_inc;
|
||||
}
|
||||
}
|
||||
|
||||
void draw_rect(int x, int y, int width, int height, uint32_t color) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
int current_x = x + i;
|
||||
int current_y = y + j;
|
||||
draw_pixel(current_x, current_y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_color_buffer(void) {
|
||||
|
||||
@ -5,11 +5,23 @@
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#include "triangle.h"
|
||||
|
||||
#define FPS 30
|
||||
#define FPS 60
|
||||
#define FRAME_TARGET_TIME (1000 / FPS)
|
||||
|
||||
enum cull_method {
|
||||
CULL_NONE,
|
||||
CULL_BACKFACE
|
||||
};
|
||||
|
||||
enum render_method {
|
||||
RENDER_WIRE,
|
||||
RENDER_WIRE_VERTEX,
|
||||
RENDER_FILL_TRIANGLE,
|
||||
RENDER_FILL_TRIANGLE_WIRE,
|
||||
RENDER_TEXTURED,
|
||||
RENDER_TEXTURED_WIRE
|
||||
};
|
||||
|
||||
extern SDL_Window* window;
|
||||
extern SDL_Renderer* renderer;
|
||||
extern uint32_t* color_buffer;
|
||||
@ -17,28 +29,12 @@ extern SDL_Texture* color_buffer_texture;
|
||||
extern int window_width;
|
||||
extern int window_height;
|
||||
|
||||
enum render_methods {
|
||||
RENDER_WIRE_VERTEX,
|
||||
RENDER_WIRE,
|
||||
RENDER_FILL_TRIANGLE,
|
||||
RENDER_FILL_TRIANGLE_LINE,
|
||||
RENDER_TEXTURED,
|
||||
RENDER_TEXTURED_LINE,
|
||||
};
|
||||
|
||||
enum cull_methods {
|
||||
CULL_NONE,
|
||||
CULL_BACKFACE,
|
||||
};
|
||||
|
||||
typedef uint32_t color_t;
|
||||
|
||||
bool initialize_window(void);
|
||||
bool initialize_window(void);
|
||||
void draw_grid(void);
|
||||
void draw_pixel(int x, int y, uint32_t color);
|
||||
void draw_line(int x0, int y0, int x1, int y1, uint32_t color);
|
||||
void draw_rect(int x, int y, int width, int height, uint32_t color);
|
||||
void render_color_buffer(void);
|
||||
void render_color_buffer(void);
|
||||
void clear_color_buffer(uint32_t color);
|
||||
void destroy_window(void);
|
||||
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
#include <stdint.h>
|
||||
#include "light.h"
|
||||
|
||||
uint32_t light_apply_intensity(uint32_t original_color, float p) {
|
||||
if (p < 0) p = 0;
|
||||
if (p > 1) p = 1;
|
||||
light_t light = {
|
||||
.direction = { 0, 0, 1 }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Change color based on a percentage factor to represent light intensity
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
uint32_t light_apply_intensity(uint32_t original_color, float percentage_factor) {
|
||||
if (percentage_factor < 0) percentage_factor = 0;
|
||||
if (percentage_factor > 1) percentage_factor = 1;
|
||||
|
||||
uint32_t a = (original_color & 0xFF000000);
|
||||
uint32_t r = (original_color & 0x00FF0000) * p;
|
||||
uint32_t g = (original_color & 0x0000FF00) * p;
|
||||
uint32_t b = (original_color & 0x000000FF) * p;
|
||||
uint32_t r = (original_color & 0x00FF0000) * percentage_factor;
|
||||
uint32_t g = (original_color & 0x0000FF00) * percentage_factor;
|
||||
uint32_t b = (original_color & 0x000000FF) * percentage_factor;
|
||||
|
||||
return (a | (r & 0x00FF0000) | (g & 0x0000FF00) | (b & 0x000000FF));
|
||||
}
|
||||
uint32_t new_color = a | (r & 0x00FF0000) | (g & 0x0000FF00) | (b & 0x000000FF);
|
||||
|
||||
return new_color;
|
||||
}
|
||||
|
||||
@ -8,7 +8,8 @@ typedef struct {
|
||||
vec3_t direction;
|
||||
} light_t;
|
||||
|
||||
uint32_t light_apply_intensity(uint32_t original_color, float p);
|
||||
extern light_t light;
|
||||
|
||||
uint32_t light_apply_intensity(uint32_t original_color, float percentage_factor);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
401
scripts/main.c
401
scripts/main.c
@ -1,51 +1,40 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <SDL.h>
|
||||
#include "display.h"
|
||||
#include "mesh.h"
|
||||
#include "vector.h"
|
||||
#include "array.h"
|
||||
#include "display.h"
|
||||
#include "vector.h"
|
||||
#include "matrix.h"
|
||||
#include "light.h"
|
||||
#include "triangle.h"
|
||||
#include "texture.h"
|
||||
#include "mesh.h"
|
||||
|
||||
#define STEP 0.075
|
||||
|
||||
uint32_t colors[12] = {
|
||||
0xFF6A2EFF, // purple
|
||||
0xFFE9C46A, // sand yellow
|
||||
0xFF2A9D8F, // teal green
|
||||
0xFFF4A261, // orange
|
||||
0xFF264653, // dark blue-grey
|
||||
0xFFB5838D, // mauve
|
||||
0xFFD7263D, // red
|
||||
0xFF38A3A5, // turquoise
|
||||
0xFF757575, // grey
|
||||
0xFF70C1B3, // light green-blue
|
||||
0xFFFFC300, // yellow
|
||||
0xFF5D2E8C // deep purple
|
||||
};
|
||||
|
||||
triangle_t* triangles_to_render = NULL; //[N_MESH_FACES];
|
||||
|
||||
vec3_t camera_position = { 0, 0, 0 };
|
||||
|
||||
mat4_t proj_matrix;
|
||||
light_t light = { .direction = { .x = 0, .y = 0, .z = 1 }};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Array of triangles that should be rendered frame by frame
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
triangle_t* triangles_to_render = NULL;
|
||||
int render_method, cull_method;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Global variables for execution status and game loop
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bool is_running = false;
|
||||
int previous_frame_time = 0;
|
||||
|
||||
int cull_method = CULL_BACKFACE;
|
||||
int render_method = RENDER_TEXTURED;
|
||||
bool sort_faces = true;
|
||||
|
||||
uint32_t previous_frame_time = 0;
|
||||
vec3_t camera_position = { .x = 0, .y = 0, .z = 0 };
|
||||
mat4_t proj_matrix;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Setup function to initialize variables and game objects
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void setup(void) {
|
||||
// Initialize render mode and triangle culling method
|
||||
render_method = RENDER_TEXTURED_WIRE;
|
||||
cull_method = CULL_BACKFACE;
|
||||
|
||||
// Allocate the required memory in bytes to hold the color buffer
|
||||
color_buffer = (uint32_t*) malloc(sizeof(uint32_t) * window_width * window_height);
|
||||
color_buffer = (uint32_t*)malloc(sizeof(uint32_t) * window_width * window_height);
|
||||
|
||||
// Creating a SDL texture that is used to display the color buffer
|
||||
color_buffer_texture = SDL_CreateTexture(
|
||||
@ -56,27 +45,29 @@ void setup(void) {
|
||||
window_height
|
||||
);
|
||||
|
||||
float fov = M_PI / 3;
|
||||
// Initialize the perspective projection matrix
|
||||
float fov = M_PI / 3.0; // the same as 180/3, or 60deg
|
||||
float aspect = (float)window_height / (float)window_width;
|
||||
float znear = 0.0f;
|
||||
float zfar = 100.0f;
|
||||
|
||||
float znear = 0.1;
|
||||
float zfar = 100.0;
|
||||
proj_matrix = mat4_make_perspective(fov, aspect, znear, zfar);
|
||||
|
||||
// Manually load the hardcoded texture data from the static array
|
||||
mesh_texture = (uint32_t*)REDBRICK_TEXTURE;
|
||||
texture_height = 64;
|
||||
texture_width = 64;
|
||||
texture_height = 64;
|
||||
|
||||
// load cube mesh data
|
||||
//load_file("..\\assets\\f22.obj");
|
||||
// Loads the vertex and face values for the mesh data structure
|
||||
load_cube_mesh_data();
|
||||
|
||||
// load_obj_file_data("./assets/f22.obj");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Poll system events and handle keyboard input
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void process_input(void) {
|
||||
SDL_Event event;
|
||||
SDL_PollEvent(&event);
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
is_running = false;
|
||||
@ -84,106 +75,57 @@ void process_input(void) {
|
||||
case SDL_KEYDOWN:
|
||||
if (event.key.keysym.sym == SDLK_ESCAPE)
|
||||
is_running = false;
|
||||
//break;
|
||||
if (event.key.keysym.sym == SDLK_UP)
|
||||
mesh.rotation.z += STEP;
|
||||
if (event.key.keysym.sym == SDLK_LEFT)
|
||||
mesh.rotation.x += STEP;
|
||||
if (event.key.keysym.sym == SDLK_RIGHT)
|
||||
mesh.rotation.y += STEP;
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
SDL_Keycode key = event.key.keysym.sym;
|
||||
if (key == SDLK_c) {
|
||||
cull_method = !cull_method;
|
||||
}
|
||||
|
||||
if (key == SDLK_s) {
|
||||
sort_faces = !sort_faces;
|
||||
}
|
||||
|
||||
if (key == SDLK_1) {
|
||||
if (event.key.keysym.sym == SDLK_1)
|
||||
render_method = RENDER_WIRE_VERTEX;
|
||||
}
|
||||
if (key == SDLK_2) {
|
||||
if (event.key.keysym.sym == SDLK_2)
|
||||
render_method = RENDER_WIRE;
|
||||
}
|
||||
if (key == SDLK_3) {
|
||||
if (event.key.keysym.sym == SDLK_3)
|
||||
render_method = RENDER_FILL_TRIANGLE;
|
||||
}
|
||||
if (key == SDLK_4) {
|
||||
render_method = RENDER_FILL_TRIANGLE_LINE;
|
||||
}
|
||||
if (key == SDLK_5) {
|
||||
if (event.key.keysym.sym == SDLK_4)
|
||||
render_method = RENDER_FILL_TRIANGLE_WIRE;
|
||||
if (event.key.keysym.sym == SDLK_5)
|
||||
render_method = RENDER_TEXTURED;
|
||||
}
|
||||
if (key == SDLK_6) {
|
||||
render_method = RENDER_TEXTURED_LINE;
|
||||
}
|
||||
|
||||
if (event.key.keysym.sym == SDLK_6)
|
||||
render_method = RENDER_TEXTURED_WIRE;
|
||||
if (event.key.keysym.sym == SDLK_c)
|
||||
cull_method = CULL_BACKFACE;
|
||||
if (event.key.keysym.sym == SDLK_d)
|
||||
cull_method = CULL_NONE;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Function that receives a 3D vector and returns a projected 2D point
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
vec2_t project(vec3_t point) {
|
||||
float fov_factor = 1; // placeholder
|
||||
vec2_t projected_point = {
|
||||
.x = roundf((fov_factor * point.x) / point.z),
|
||||
.y = roundf((fov_factor * point.y) / point.z),
|
||||
};
|
||||
return projected_point;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Update function frame by frame with a fixed time step
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void update(void) {
|
||||
//while (!SDL_TICKS_PASSED(SDL_GetTicks(), previous_frame_time + FRAME_TARGET_TIME));
|
||||
|
||||
// Wait some time until the reach the target frame time in milliseconds
|
||||
int time_to_wait = FRAME_TARGET_TIME - (SDL_GetTicks() - previous_frame_time);
|
||||
|
||||
// only delay execution if we are running too fast
|
||||
// Only delay execution if we are running too fast
|
||||
if (time_to_wait > 0 && time_to_wait <= FRAME_TARGET_TIME) {
|
||||
SDL_Delay(time_to_wait);
|
||||
}
|
||||
|
||||
previous_frame_time = SDL_GetTicks();
|
||||
|
||||
//mesh.rotation.y += 0.01f;
|
||||
mesh.rotation.x -= 0.01f;
|
||||
//mesh.rotation.z += 0.01f;
|
||||
// Initialize the array of triangles to render
|
||||
triangles_to_render = NULL;
|
||||
|
||||
//mesh.translation.x += 0.004f;
|
||||
mesh.translation.z = 5.0f;
|
||||
// Change the mesh scale, rotation, and translation values per animation frame
|
||||
mesh.rotation.x += 0.000;
|
||||
mesh.rotation.y += 0.003;
|
||||
mesh.rotation.z += 0.000;
|
||||
mesh.translation.z = 5.0;
|
||||
|
||||
//mesh.scale.x += 0.002f;
|
||||
//mesh.scale.y += 0.002f;
|
||||
|
||||
// create scale matrix that will be used
|
||||
// Create scale, rotation, and translation matrices that will be used to multiply the mesh vertices
|
||||
mat4_t scale_matrix = mat4_make_scale(mesh.scale.x, mesh.scale.y, mesh.scale.z);
|
||||
|
||||
// create translation matrix
|
||||
mat4_t translation_matrix = mat4_make_translation(mesh.translation.x, mesh.translation.y, mesh.translation.z);
|
||||
|
||||
// create rotation matrices
|
||||
mat4_t rotation_matrix_x = mat4_make_rotation_x(mesh.rotation.x);
|
||||
mat4_t rotation_matrix_y = mat4_make_rotation_y(mesh.rotation.y);
|
||||
mat4_t rotation_matrix_z = mat4_make_rotation_z(mesh.rotation.z);
|
||||
|
||||
// create world matrix
|
||||
mat4_t world_matrix = mat4_identity();
|
||||
world_matrix = mat4_mul_mat4(&scale_matrix, &world_matrix);
|
||||
world_matrix = mat4_mul_mat4(&rotation_matrix_x, &world_matrix);
|
||||
world_matrix = mat4_mul_mat4(&rotation_matrix_y, &world_matrix);
|
||||
world_matrix = mat4_mul_mat4(&rotation_matrix_z, &world_matrix);
|
||||
world_matrix = mat4_mul_mat4(&translation_matrix, &world_matrix);
|
||||
|
||||
|
||||
triangles_to_render = NULL;
|
||||
|
||||
// Loop all triangle faces of our mesh
|
||||
int num_faces = array_length(mesh.faces);
|
||||
for (int i = 0; i < num_faces; i++) {
|
||||
face_t mesh_face = mesh.faces[i];
|
||||
@ -195,39 +137,51 @@ void update(void) {
|
||||
|
||||
vec4_t transformed_vertices[3];
|
||||
|
||||
// Loop all three vertices of this current face and apply transformations
|
||||
for (int j = 0; j < 3; j++) {
|
||||
vec4_t transformed_vertex = vec4_from_vec3(face_vertices[j]);
|
||||
|
||||
// use matrix to scale original matrix
|
||||
transformed_vertex = mat4_multiply_vec4(world_matrix, transformed_vertex);
|
||||
// Create a World Matrix combining scale, rotation, and translation matrices
|
||||
mat4_t world_matrix = mat4_identity();
|
||||
|
||||
// save translated vertex in the array of transformed vertices
|
||||
// Order matters: First scale, then rotate, then translate. [T]*[R]*[S]*v
|
||||
world_matrix = mat4_mul_mat4(scale_matrix, world_matrix);
|
||||
world_matrix = mat4_mul_mat4(rotation_matrix_z, world_matrix);
|
||||
world_matrix = mat4_mul_mat4(rotation_matrix_y, world_matrix);
|
||||
world_matrix = mat4_mul_mat4(rotation_matrix_x, world_matrix);
|
||||
world_matrix = mat4_mul_mat4(translation_matrix, world_matrix);
|
||||
|
||||
// Multiply the world matrix by the original vector
|
||||
transformed_vertex = mat4_mul_vec4(world_matrix, transformed_vertex);
|
||||
|
||||
// Save transformed vertex in the array of transformed vertices
|
||||
transformed_vertices[j] = transformed_vertex;
|
||||
}
|
||||
|
||||
vec3_t vector_a = vec3_from_vec4(transformed_vertices[0]); /* A */
|
||||
vec3_t vector_b = vec3_from_vec4(transformed_vertices[1]); /* / \ */
|
||||
vec3_t vector_c = vec3_from_vec4(transformed_vertices[2]); /* C---B */
|
||||
// Get individual vectors from A, B, and C vertices to compute normal
|
||||
vec3_t vector_a = vec3_from_vec4(transformed_vertices[0]); /* A */
|
||||
vec3_t vector_b = vec3_from_vec4(transformed_vertices[1]); /* / \ */
|
||||
vec3_t vector_c = vec3_from_vec4(transformed_vertices[2]); /* C---B */
|
||||
|
||||
// get the vector subtraction of B-A and C-A
|
||||
vec3_t vector_ab = vec3_subtract(vector_b, vector_a);
|
||||
vec3_t vector_ac = vec3_subtract(vector_c, vector_a);
|
||||
// Get the vector subtraction of B-A and C-A
|
||||
vec3_t vector_ab = vec3_sub(vector_b, vector_a);
|
||||
vec3_t vector_ac = vec3_sub(vector_c, vector_a);
|
||||
vec3_normalize(&vector_ab);
|
||||
vec3_normalize(&vector_ac);
|
||||
|
||||
// compute the face normal using the cross product to find perpindicular
|
||||
// Compute the face normal (using cross product to find perpendicular)
|
||||
vec3_t normal = vec3_cross(vector_ab, vector_ac);
|
||||
vec3_normalize(&normal);
|
||||
|
||||
// Find the vector between vertex A in the triangle and the camera origin
|
||||
vec3_t camera_ray = vec3_sub(camera_position, vector_a);
|
||||
|
||||
// Calculate how aligned the camera ray is with the face normal (using dot product)
|
||||
float dot_normal_camera = vec3_dot(normal, camera_ray);
|
||||
|
||||
// Backface culling test to see if the current face should be projected
|
||||
if (cull_method == CULL_BACKFACE) {
|
||||
// check backface culling
|
||||
|
||||
// find the vector between a point in the triangle and the camera origin
|
||||
vec3_t camera_ray = vec3_subtract(camera_position, vector_a);
|
||||
|
||||
// calculate how aligned the camera ray is with the face normal
|
||||
float dot_normal_camera = vec3_dot(normal, camera_ray);
|
||||
|
||||
// Backface culling, bypassing triangles that are looking away from the camera
|
||||
if (dot_normal_camera < 0) {
|
||||
continue;
|
||||
}
|
||||
@ -235,130 +189,117 @@ void update(void) {
|
||||
|
||||
vec4_t projected_points[3];
|
||||
|
||||
// Loop all three vertices to perform projection
|
||||
for (int j = 0; j < 3; j++) {
|
||||
// project the current vertex
|
||||
// Project the current vertex
|
||||
projected_points[j] = mat4_mul_vec4_project(proj_matrix, transformed_vertices[j]);
|
||||
|
||||
// Flip vertically since the y values of the 3D mesh grow bottom->up and in screen space y values grow top->down
|
||||
projected_points[j].y *= -1;
|
||||
|
||||
// Scale into the view
|
||||
projected_points[j].x *= (window_width / 2.0);
|
||||
projected_points[j].y *= (window_height / 2.0);
|
||||
|
||||
// invert y to account for flipped screen y coordinates
|
||||
projected_points[j].y *= -1;
|
||||
|
||||
// Translate the projected points to the middle of the screen
|
||||
projected_points[j].x += (window_width / 2.0);
|
||||
projected_points[j].y += (window_height / 2.0);
|
||||
|
||||
//projected_triangle.points[j] = projected_point;
|
||||
}
|
||||
|
||||
// calculate color using normal and light direction, then invert
|
||||
float dot_color_p = -vec3_dot(normal, light.direction);
|
||||
// Calculate the average depth for each face based on the vertices after transformation
|
||||
float avg_depth = (transformed_vertices[0].z + transformed_vertices[1].z + transformed_vertices[2].z) / 3.0;
|
||||
|
||||
color_t flat_shaded_color = light_apply_intensity(0xFFFFFFFF, dot_color_p);
|
||||
// Calculate the shade intensity based on how aliged is the normal with the flipped light direction ray
|
||||
float light_intensity_factor = -vec3_dot(normal, light.direction);
|
||||
|
||||
// Calculate the triangle color based on the light angle
|
||||
uint32_t triangle_color = light_apply_intensity(mesh_face.color, light_intensity_factor);
|
||||
|
||||
// calculate the average depth of the triangle
|
||||
float avg_depth = (transformed_vertices[0].z + transformed_vertices[1].z + transformed_vertices[2].z) / 3.0f;
|
||||
#define FUNC3 (int)
|
||||
triangle_t projected_triangle = {
|
||||
.points = {
|
||||
{ FUNC3(projected_points[0].x), FUNC3(projected_points[0].y) },
|
||||
{ FUNC3(projected_points[1].x), FUNC3(projected_points[1].y) },
|
||||
{ FUNC3(projected_points[2].x), FUNC3(projected_points[2].y) },
|
||||
{ projected_points[0].x, projected_points[0].y, projected_points[0].z, projected_points[0].w },
|
||||
{ projected_points[1].x, projected_points[1].y, projected_points[1].z, projected_points[1].w },
|
||||
{ projected_points[2].x, projected_points[2].y, projected_points[2].z, projected_points[2].w },
|
||||
},
|
||||
.texcoords = {
|
||||
{ mesh_face.a_uv.u, mesh_face.a_uv.v },
|
||||
{ mesh_face.b_uv.u, mesh_face.b_uv.v },
|
||||
{ mesh_face.c_uv.u, mesh_face.c_uv.v },
|
||||
{ mesh_face.a_uv.u, mesh_face.a_uv.v },
|
||||
{ mesh_face.b_uv.u, mesh_face.b_uv.v },
|
||||
{ mesh_face.c_uv.u, mesh_face.c_uv.v }
|
||||
},
|
||||
.color = flat_shaded_color,
|
||||
.average_depth = avg_depth,
|
||||
.color = triangle_color,
|
||||
.avg_depth = avg_depth
|
||||
};
|
||||
|
||||
//vec2_t midpoint = triangle_midpoint(projected_triangle);
|
||||
//draw_rect(midpoint.x, midpoint.y, 10, 10, 0xFFFF0000);
|
||||
|
||||
// save the projected triangle in the array of triangles
|
||||
// Save the projected triangle in the array of triangles to render
|
||||
array_push(triangles_to_render, projected_triangle);
|
||||
|
||||
}
|
||||
|
||||
// Sort the triangles to render by their avg_depth
|
||||
int num_triangles = array_length(triangles_to_render);
|
||||
for (int i = 0; i < num_triangles; i++) {
|
||||
for (int j = i; j < num_triangles; j++) {
|
||||
if (triangles_to_render[i].avg_depth < triangles_to_render[j].avg_depth) {
|
||||
// Swap the triangles positions in the array
|
||||
triangle_t temp = triangles_to_render[i];
|
||||
triangles_to_render[i] = triangles_to_render[j];
|
||||
triangles_to_render[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int depth_comp(const void* a, const void* b) {
|
||||
triangle_t arg_a = *(const triangle_t*)a;
|
||||
triangle_t arg_b = *(const triangle_t*)b;
|
||||
|
||||
if (arg_a.average_depth > arg_b.average_depth) return -1;
|
||||
if (arg_a.average_depth < arg_b.average_depth) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Render function to draw objects on the display
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void render(void) {
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
draw_grid();
|
||||
//uint32_t colors[] = { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF, 0xFF757500, 0xFF007575, 0xFF750075 };
|
||||
// Loop all projected points and render them
|
||||
size_t arr_length = array_length(triangles_to_render);
|
||||
|
||||
// sort triangles
|
||||
if (sort_faces) qsort(triangles_to_render, arr_length, sizeof(triangle_t), depth_comp);
|
||||
|
||||
for (int i = 0; i < arr_length; i++) {
|
||||
// Loop all projected triangles and render them
|
||||
int num_triangles = array_length(triangles_to_render);
|
||||
for (int i = 0; i < num_triangles; i++) {
|
||||
triangle_t triangle = triangles_to_render[i];
|
||||
|
||||
switch (render_method) {
|
||||
case RENDER_WIRE:
|
||||
draw_triangle(triangle, 0x0000ff);
|
||||
break;
|
||||
case RENDER_WIRE_VERTEX:
|
||||
draw_triangle(triangle, 0x0000ff);
|
||||
draw_rect(triangle.points[0].x, triangle.points[0].y, 3, 3, 0xFFFFFF00);
|
||||
draw_rect(triangle.points[1].x, triangle.points[1].y, 3, 3, 0xFFFFFF00);
|
||||
draw_rect(triangle.points[2].x, triangle.points[2].y, 3, 3, 0xFFFFFF00);
|
||||
break;
|
||||
case RENDER_FILL_TRIANGLE:
|
||||
draw_filled_triangle(
|
||||
triangle.points[0].x, triangle.points[0].y, // vertex A
|
||||
triangle.points[1].x, triangle.points[1].y, // vertex B
|
||||
triangle.points[2].x, triangle.points[2].y,
|
||||
triangle.color
|
||||
);
|
||||
break;
|
||||
case RENDER_FILL_TRIANGLE_LINE:
|
||||
draw_filled_triangle(
|
||||
triangle.points[0].x, triangle.points[0].y, // vertex A
|
||||
triangle.points[1].x, triangle.points[1].y, // vertex B
|
||||
triangle.points[2].x, triangle.points[2].y, // vertex C
|
||||
triangle.color
|
||||
);
|
||||
draw_triangle(triangle, 0xff0000ff);
|
||||
break;
|
||||
case RENDER_TEXTURED:
|
||||
draw_textured_triangle(
|
||||
triangle.points[0].x, triangle.points[0].y, triangle.texcoords[0].u, triangle.texcoords[0].v, // vertex A
|
||||
triangle.points[1].x, triangle.points[1].y, triangle.texcoords[1].u, triangle.texcoords[1].v, // vertex B
|
||||
triangle.points[2].x, triangle.points[2].y, triangle.texcoords[2].u, triangle.texcoords[2].v, // vertex C
|
||||
mesh_texture
|
||||
);
|
||||
break;
|
||||
case RENDER_TEXTURED_LINE:
|
||||
draw_textured_triangle(
|
||||
triangle.points[0].x, triangle.points[0].y, triangle.texcoords[0].u, triangle.texcoords[0].v, // vertex A
|
||||
triangle.points[1].x, triangle.points[1].y, triangle.texcoords[1].u, triangle.texcoords[1].v, // vertex B
|
||||
triangle.points[2].x, triangle.points[2].y, triangle.texcoords[2].u, triangle.texcoords[2].v, // vertex C
|
||||
mesh_texture
|
||||
);
|
||||
draw_triangle(triangle, 0xff0000ff);
|
||||
default:
|
||||
break;
|
||||
// Draw filled triangle
|
||||
if (render_method == RENDER_FILL_TRIANGLE || render_method == RENDER_FILL_TRIANGLE_WIRE) {
|
||||
draw_filled_triangle(
|
||||
triangle.points[0].x, triangle.points[0].y, // vertex A
|
||||
triangle.points[1].x, triangle.points[1].y, // vertex B
|
||||
triangle.points[2].x, triangle.points[2].y, // vertex C
|
||||
triangle.color
|
||||
);
|
||||
}
|
||||
|
||||
// Draw textured triangle
|
||||
if (render_method == RENDER_TEXTURED || render_method == RENDER_TEXTURED_WIRE) {
|
||||
draw_textured_triangle(
|
||||
triangle.points[0].x, triangle.points[0].y, triangle.points[0].z, triangle.points[0].w, triangle.texcoords[0].u, triangle.texcoords[0].v, // vertex A
|
||||
triangle.points[1].x, triangle.points[1].y, triangle.points[1].z, triangle.points[1].w, triangle.texcoords[1].u, triangle.texcoords[1].v, // vertex B
|
||||
triangle.points[2].x, triangle.points[2].y, triangle.points[2].z, triangle.points[2].w, triangle.texcoords[2].u, triangle.texcoords[2].v, // vertex C
|
||||
mesh_texture
|
||||
);
|
||||
}
|
||||
|
||||
// Draw triangle wireframe
|
||||
if (render_method == RENDER_WIRE || render_method == RENDER_WIRE_VERTEX || render_method == RENDER_FILL_TRIANGLE_WIRE || render_method == RENDER_TEXTURED_WIRE) {
|
||||
draw_triangle(
|
||||
triangle.points[0].x, triangle.points[0].y, // vertex A
|
||||
triangle.points[1].x, triangle.points[1].y, // vertex B
|
||||
triangle.points[2].x, triangle.points[2].y, // vertex C
|
||||
0xFFFFFFFF
|
||||
);
|
||||
}
|
||||
|
||||
// Draw triangle vertex points
|
||||
if (render_method == RENDER_WIRE_VERTEX) {
|
||||
draw_rect(triangle.points[0].x - 3, triangle.points[0].y - 3, 6, 6, 0xFFFF0000); // vertex A
|
||||
draw_rect(triangle.points[1].x - 3, triangle.points[1].y - 3, 6, 6, 0xFFFF0000); // vertex B
|
||||
draw_rect(triangle.points[2].x - 3, triangle.points[2].y - 3, 6, 6, 0xFFFF0000); // vertex C
|
||||
}
|
||||
}
|
||||
|
||||
//vec2_t m = triangle_midpoint(t);
|
||||
//draw_rect(m.x, m.y, 10, 10, 0xFFFF0000);
|
||||
|
||||
//draw_line(10, 10, 500, 500, 0x00FF00);
|
||||
// Clear the array of triangles to render every frame loop
|
||||
array_free(triangles_to_render);
|
||||
|
||||
render_color_buffer();
|
||||
@ -368,13 +309,19 @@ void render(void) {
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Free the memory that was dynamically allocated by the program
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void free_resources(void) {
|
||||
free(color_buffer);
|
||||
array_free(mesh.faces);
|
||||
array_free(mesh.vertices);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Main function
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argv, char* args[]) {
|
||||
is_running = initialize_window();
|
||||
|
||||
setup();
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
#include <SDL.h>
|
||||
|
||||
int main(int argc, char* args []) {
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
SDL_Window* window = SDL_CreateWindow("Blank Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN);
|
||||
if (window == nullptr) {
|
||||
SDL_Log("Failed to create window: %s", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||
if (renderer == nullptr) {
|
||||
SDL_Log("Failed to create renderer: %s", SDL_GetError());
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool running = true;
|
||||
SDL_Event event;
|
||||
|
||||
while (running) {
|
||||
// Close window with any input
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT || event.type == SDL_KEYDOWN || event.type == SDL_MOUSEBUTTONDOWN) {
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(renderer, 100, 100, 180, 255); // Set the background color to purple
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
@ -1,172 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <SDL.h>
|
||||
|
||||
bool is_running = false;
|
||||
|
||||
SDL_Window* window = NULL;
|
||||
SDL_Renderer* renderer = NULL;
|
||||
|
||||
uint32_t* color_buffer = NULL;
|
||||
SDL_Texture* color_buffer_texture = NULL;
|
||||
|
||||
int window_width = 800;
|
||||
int window_height = 600;
|
||||
|
||||
bool initialize_window(void) {
|
||||
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
|
||||
fprintf(stderr, "Error initializing SDL.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set width and height of the SDL window with the max screen resolution
|
||||
SDL_DisplayMode display_mode;
|
||||
SDL_GetCurrentDisplayMode(0, &display_mode);
|
||||
window_width = display_mode.w;
|
||||
window_height = display_mode.h;
|
||||
|
||||
// Create a SDL Window
|
||||
window = SDL_CreateWindow(
|
||||
NULL,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
window_width,
|
||||
window_height,
|
||||
SDL_WINDOW_BORDERLESS
|
||||
);
|
||||
if (!window) {
|
||||
fprintf(stderr, "Error creating SDL window.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a SDL renderer
|
||||
renderer = SDL_CreateRenderer(window, -1, 0);
|
||||
if (!renderer) {
|
||||
fprintf(stderr, "Error creating SDL renderer.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup(void) {
|
||||
// Allocate the required memory in bytes to hold the color buffer
|
||||
color_buffer = (uint32_t*) malloc(sizeof(uint32_t) * window_width * window_height);
|
||||
|
||||
// Creating a SDL texture that is used to display the color buffer
|
||||
color_buffer_texture = SDL_CreateTexture(
|
||||
renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
window_width,
|
||||
window_height
|
||||
);
|
||||
}
|
||||
|
||||
void process_input(void) {
|
||||
SDL_Event event;
|
||||
SDL_PollEvent(&event);
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
is_running = false;
|
||||
break;
|
||||
case SDL_KEYDOWN:
|
||||
if (event.key.keysym.sym == SDLK_ESCAPE)
|
||||
is_running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void update(void) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void draw_rect(int xpos, int ypos, int width, int height, uint32_t color) {
|
||||
for (int y = ypos; y < (ypos + height); y++) {
|
||||
for (int x = xpos; x < (xpos + width); x++) {
|
||||
color_buffer[(window_width * y) + x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw_grid(void) {
|
||||
// TODO:
|
||||
uint32_t color = 0xc0c0c0;
|
||||
bool draw_line = false;
|
||||
int grid_spacing = 40;
|
||||
|
||||
/*for (int y = 0; y < window_height; y++) {
|
||||
draw_line = !(y % grid_spacing);
|
||||
for (int x = 0; x < window_width; x++) {
|
||||
if (draw_line || !(x % grid_spacing)) {
|
||||
color_buffer[(window_width * y) + x] = color;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
for (int y = 0; y < window_height; y = y + grid_spacing) {
|
||||
for (int x = 0; x < window_width; x++) {
|
||||
color_buffer[(window_width * y) + x] = color;
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < window_width; x = x + grid_spacing) {
|
||||
for (int y = 0; y < window_height; y++) {
|
||||
color_buffer[(window_width * y) + x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_color_buffer(void) {
|
||||
SDL_UpdateTexture(
|
||||
color_buffer_texture,
|
||||
NULL,
|
||||
color_buffer,
|
||||
(int)(window_width * sizeof(uint32_t))
|
||||
);
|
||||
SDL_RenderCopy(renderer, color_buffer_texture, NULL, NULL);
|
||||
}
|
||||
|
||||
void clear_color_buffer(uint32_t color) {
|
||||
for (int y = 0; y < window_height; y++) {
|
||||
for (int x = 0; x < window_width; x++) {
|
||||
color_buffer[(window_width * y) + x] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render(void) {
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
draw_grid();
|
||||
draw_rect(20, 120, 150, 100, 0xFFFF00);
|
||||
|
||||
render_color_buffer();
|
||||
clear_color_buffer(0xFF000000);
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
void destroy_window(void) {
|
||||
free(color_buffer);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
is_running = initialize_window();
|
||||
|
||||
setup();
|
||||
|
||||
while (is_running) {
|
||||
process_input();
|
||||
update();
|
||||
render();
|
||||
}
|
||||
|
||||
destroy_window();
|
||||
|
||||
return 0;
|
||||
}
|
||||
160
scripts/matrix.c
160
scripts/matrix.c
@ -1,139 +1,131 @@
|
||||
#include <math.h>
|
||||
#include "matrix.h"
|
||||
|
||||
mat4_t mat4_identity(void) {
|
||||
// | 1 0 0 0 |
|
||||
// | 0 1 0 0 |
|
||||
// | 0 0 1 0 |
|
||||
// | 0 0 0 1 |
|
||||
mat4_t m = {{
|
||||
{ 1, 0, 0, 0},
|
||||
{ 0, 1, 0, 0},
|
||||
{ 0, 0, 1, 0},
|
||||
{ 0, 0, 0, 1},
|
||||
{ 1, 0, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 0, 1 }
|
||||
}};
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_t mat4_make_scale(float sx, float sy, float sz) {
|
||||
// | sx 0 0 0 |
|
||||
// | 0 sy 0 0 |
|
||||
// | 0 0 sz 0 |
|
||||
// | 0 0 0 1 |
|
||||
mat4_t m = mat4_identity();
|
||||
m.m[0][0] *= sx;
|
||||
m.m[1][1] *= sy;
|
||||
m.m[2][2] *= sz;
|
||||
|
||||
m.m[0][0] = sx;
|
||||
m.m[1][1] = sy;
|
||||
m.m[2][2] = sz;
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_t mat4_make_translation(float tx, float ty, float tz) {
|
||||
/*
|
||||
* 1 0 0 tx
|
||||
* 0 1 0 ty
|
||||
* 0 0 1 tz
|
||||
* 0 0 0 1
|
||||
*/
|
||||
|
||||
// | 1 0 0 tx |
|
||||
// | 0 1 0 ty |
|
||||
// | 0 0 1 tz |
|
||||
// | 0 0 0 1 |
|
||||
mat4_t m = mat4_identity();
|
||||
m.m[0][3] = tx;
|
||||
m.m[1][3] = ty;
|
||||
m.m[2][3] = tz;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_t mat4_make_rotation_y(float ra) {
|
||||
/*
|
||||
* cos 0 -sin 0
|
||||
* 0 1 0 0
|
||||
* sin 0 cos 0
|
||||
* 0 0 0 1
|
||||
*/
|
||||
const float cosine = cosf(ra);
|
||||
const float sine = sinf(ra);
|
||||
mat4_t mat4_make_rotation_x(float angle) {
|
||||
float c = cos(angle);
|
||||
float s = sin(angle);
|
||||
// | 1 0 0 0 |
|
||||
// | 0 c -s 0 |
|
||||
// | 0 s c 0 |
|
||||
// | 0 0 0 1 |
|
||||
mat4_t m = mat4_identity();
|
||||
m.m[0][0] = cosine;
|
||||
m.m[0][2] = -sine;
|
||||
m.m[2][0] = sine;
|
||||
m.m[2][2] = cosine;
|
||||
|
||||
m.m[1][1] = c;
|
||||
m.m[1][2] = -s;
|
||||
m.m[2][1] = s;
|
||||
m.m[2][2] = c;
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_t mat4_make_rotation_x(float ra) {
|
||||
/*
|
||||
* 1 0 0 0
|
||||
* 0 cos sin 0
|
||||
* 0 -sin cos 0
|
||||
* 0 0 0 1
|
||||
*/
|
||||
const float cosine = cosf(ra);
|
||||
const float sine = sinf(ra);
|
||||
mat4_t mat4_make_rotation_y(float angle) {
|
||||
float c = cos(angle);
|
||||
float s = sin(angle);
|
||||
// | c 0 s 0 |
|
||||
// | 0 1 0 0 |
|
||||
// | -s 0 c 0 |
|
||||
// | 0 0 0 1 |
|
||||
mat4_t m = mat4_identity();
|
||||
m.m[1][1] = cosine;
|
||||
m.m[1][2] = sine;
|
||||
m.m[2][1] = -sine;
|
||||
m.m[2][2] = cosine;
|
||||
|
||||
m.m[0][0] = c;
|
||||
m.m[0][2] = s;
|
||||
m.m[2][0] = -s;
|
||||
m.m[2][2] = c;
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
mat4_t mat4_make_rotation_z(float ra) {
|
||||
/*
|
||||
* cos sin 0 0
|
||||
* -sin cos 0 0
|
||||
* 0 0 1 0
|
||||
* 0 0 0 1
|
||||
*/
|
||||
const float cosine = cosf(ra);
|
||||
const float sine = sinf(ra);
|
||||
mat4_t mat4_make_rotation_z(float angle) {
|
||||
float c = cos(angle);
|
||||
float s = sin(angle);
|
||||
// | c -s 0 0 |
|
||||
// | s c 0 0 |
|
||||
// | 0 0 1 0 |
|
||||
// | 0 0 0 1 |
|
||||
mat4_t m = mat4_identity();
|
||||
m.m[0][0] = cosine;
|
||||
m.m[0][1] = sine;
|
||||
m.m[1][0] = -sine;
|
||||
m.m[1][1] = cosine;
|
||||
|
||||
m.m[0][0] = c;
|
||||
m.m[0][1] = -s;
|
||||
m.m[1][0] = s;
|
||||
m.m[1][1] = c;
|
||||
return m;
|
||||
}
|
||||
|
||||
vec4_t mat4_multiply_vec4(mat4_t m, vec4_t v) {
|
||||
vec4_t ret = {};
|
||||
|
||||
ret.x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3] * v.w;
|
||||
ret.y = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3] * v.w;
|
||||
ret.z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3] * v.w;
|
||||
ret.w = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] * v.w;
|
||||
|
||||
return ret;
|
||||
vec4_t mat4_mul_vec4(mat4_t m, vec4_t v) {
|
||||
vec4_t result;
|
||||
result.x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3] * v.w;
|
||||
result.y = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3] * v.w;
|
||||
result.z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3] * v.w;
|
||||
result.w = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] * v.w;
|
||||
return result;
|
||||
}
|
||||
|
||||
mat4_t mat4_mul_mat4(mat4_t* a, mat4_t* b) {
|
||||
mat4_t ret = {};
|
||||
|
||||
for (int r = 0; r < 4; r++) {
|
||||
for (int c = 0; c < 4; c++) {
|
||||
ret.m[r][c] = (a->m[r][0] * b->m[0][c]) + (a->m[r][1] * b->m[1][c]) + (a->m[r][2] * b->m[2][c]) + (a->m[r][3] * b->m[3][c]);
|
||||
mat4_t mat4_mul_mat4(mat4_t a, mat4_t b) {
|
||||
mat4_t m;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
m.m[i][j] = a.m[i][0] * b.m[0][j] + a.m[i][1] * b.m[1][j] + a.m[i][2] * b.m[2][j] + a.m[i][3] * b.m[3][j];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_t mat4_make_perspective(float fov, float aspect, float znear, float zfar) {
|
||||
// | (h/w)*1/tan(fov/2) 0 0 0 |
|
||||
// | 0 1/tan(fov/2) 0 0 |
|
||||
// | 0 0 zf/(zf-zn) (-zf*zn)/(zf-zn) |
|
||||
// | 0 0 1 0 |
|
||||
mat4_t m = {{{ 0 }}};
|
||||
m.m[0][0] = aspect * (1 / tanf(fov / 2));
|
||||
m.m[1][1] = 1 / tanf(fov / 2);
|
||||
m.m[0][0] = aspect * (1 / tan(fov / 2));
|
||||
m.m[1][1] = 1 / tan(fov / 2);
|
||||
m.m[2][2] = zfar / (zfar - znear);
|
||||
m.m[2][3] = (-zfar * znear) / (zfar - znear);
|
||||
m.m[3][2] = 1.0f;
|
||||
m.m[3][2] = 1.0;
|
||||
return m;
|
||||
}
|
||||
|
||||
vec4_t mat4_mul_vec4_project(mat4_t mat_proj, vec4_t v) {
|
||||
// multiply the projection matrix by our original vector
|
||||
vec4_t result = mat4_multiply_vec4(mat_proj, v);
|
||||
vec4_t result = mat4_mul_vec4(mat_proj, v);
|
||||
|
||||
// perform perspective divide with original z-value
|
||||
// perform perspective divide with original z-value that is now stored in w
|
||||
if (result.w != 0.0) {
|
||||
result.x /= result.w;
|
||||
result.y /= result.w;
|
||||
result.z /= result.w;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,21 @@
|
||||
#ifndef MATRIX_H
|
||||
#define MATRIX_H
|
||||
|
||||
#include <math.h>
|
||||
#include "vector.h"
|
||||
|
||||
typedef struct mat4_t mat4_t;
|
||||
struct mat4_t {
|
||||
typedef struct {
|
||||
float m[4][4];
|
||||
};
|
||||
} mat4_t;
|
||||
|
||||
mat4_t mat4_identity(void);
|
||||
mat4_t mat4_make_scale(float sx, float sy, float sz);
|
||||
mat4_t mat4_make_translation(float tx, float ty, float tz);
|
||||
mat4_t mat4_make_rotation_x(float ra);
|
||||
mat4_t mat4_make_rotation_y(float ra);
|
||||
mat4_t mat4_make_rotation_z(float ra);
|
||||
mat4_t mat4_mul_mat4(mat4_t* a, mat4_t* b);
|
||||
vec4_t mat4_multiply_vec4(mat4_t m, vec4_t v);
|
||||
mat4_t mat4_make_rotation_x(float angle);
|
||||
mat4_t mat4_make_rotation_y(float angle);
|
||||
mat4_t mat4_make_rotation_z(float angle);
|
||||
mat4_t mat4_make_perspective(float fov, float aspect, float znear, float zfar);
|
||||
vec4_t mat4_mul_vec4(mat4_t m, vec4_t v);
|
||||
mat4_t mat4_mul_mat4(mat4_t a, mat4_t b);
|
||||
vec4_t mat4_mul_vec4_project(mat4_t mat_proj, vec4_t v);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1,19 +1,14 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "mesh.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "array.h"
|
||||
#include "mesh.h"
|
||||
|
||||
mesh_t mesh = {
|
||||
.vertices = NULL,
|
||||
.faces = NULL,
|
||||
.rotation = { 0, 0, 0 },
|
||||
.scale = { 1.0, 1.0, 1.0 },
|
||||
.translation = { 0, 0, 0 },
|
||||
.translation = { 0, 0, 0 }
|
||||
};
|
||||
|
||||
vec3_t cube_vertices[N_CUBE_VERTICES] = {
|
||||
@ -50,60 +45,45 @@ face_t cube_faces[N_CUBE_FACES] = {
|
||||
|
||||
void load_cube_mesh_data(void) {
|
||||
for (int i = 0; i < N_CUBE_VERTICES; i++) {
|
||||
array_push(mesh.vertices, cube_vertices[i]);
|
||||
vec3_t cube_vertex = cube_vertices[i];
|
||||
array_push(mesh.vertices, cube_vertex);
|
||||
}
|
||||
for (int i = 0; i < N_CUBE_FACES; i++) {
|
||||
array_push(mesh.faces, cube_faces[i]);
|
||||
face_t cube_face = cube_faces[i];
|
||||
array_push(mesh.faces, cube_face);
|
||||
}
|
||||
}
|
||||
|
||||
void parse_face(const char* buffer, face_t* face) {
|
||||
char temp_a[64], temp_b[64], temp_c[64];
|
||||
sscanf(buffer, "f %63s %63s %63s", temp_a, temp_b, temp_c);
|
||||
void load_obj_file_data(char* filename) {
|
||||
FILE* file;
|
||||
file = fopen(filename, "r");
|
||||
char line[1024];
|
||||
|
||||
char* token;
|
||||
|
||||
token = strtok(temp_a, "/");
|
||||
face->a = token ? atoi(token) : -1;
|
||||
|
||||
token = strtok(temp_b, "/");
|
||||
face->b = token ? atoi(token) : -1;
|
||||
|
||||
token = strtok(temp_c, "/");
|
||||
face->c = token ? atoi(token) : -1;
|
||||
}
|
||||
|
||||
void load_file(const char* filename) {
|
||||
FILE* fp;
|
||||
char* tok;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
|
||||
if (fp == NULL) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char buffer[MAX_LEN];
|
||||
while (fgets(buffer, MAX_LEN, fp)) {
|
||||
|
||||
if (strncmp(buffer, "v ", 2) == 0) {
|
||||
while (fgets(line, 1024, file)) {
|
||||
// Vertex information
|
||||
if (strncmp(line, "v ", 2) == 0) {
|
||||
vec3_t vertex;
|
||||
sscanf(buffer, "v %f %f %f", &vertex.x, &vertex.y, &vertex.z);
|
||||
|
||||
sscanf(line, "v %f %f %f", &vertex.x, &vertex.y, &vertex.z);
|
||||
array_push(mesh.vertices, vertex);
|
||||
|
||||
} else if (strncmp(buffer, "f ", 2) == 0) {
|
||||
face_t face;
|
||||
|
||||
parse_face(buffer, &face);
|
||||
|
||||
array_push(mesh.faces, face);
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
// Face information
|
||||
if (strncmp(line, "f ", 2) == 0) {
|
||||
int vertex_indices[3];
|
||||
int texture_indices[3];
|
||||
int normal_indices[3];
|
||||
sscanf(
|
||||
line, "f %d/%d/%d %d/%d/%d %d/%d/%d",
|
||||
&vertex_indices[0], &texture_indices[0], &normal_indices[0],
|
||||
&vertex_indices[1], &texture_indices[1], &normal_indices[1],
|
||||
&vertex_indices[2], &texture_indices[2], &normal_indices[2]
|
||||
);
|
||||
face_t face = {
|
||||
.a = vertex_indices[0],
|
||||
.b = vertex_indices[1],
|
||||
.c = vertex_indices[2],
|
||||
.color = 0xFFFFFFFF
|
||||
};
|
||||
array_push(mesh.faces, face);
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fclose(fp);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,40 +7,23 @@
|
||||
#define N_CUBE_VERTICES 8
|
||||
#define N_CUBE_FACES (6 * 2) // 6 cube faces, 2 triangles per face
|
||||
|
||||
#define MAX_LEN 256
|
||||
|
||||
extern vec3_t cube_vertices[N_CUBE_VERTICES];
|
||||
extern face_t cube_faces[N_CUBE_FACES];
|
||||
|
||||
typedef enum {
|
||||
COLOR_PURPLE = 0xFF6A2EFF,
|
||||
COLOR_SAND_YELLOW = 0xFFE9C46A,
|
||||
COLOR_TEAL_GREEN = 0xFF2A9D8F,
|
||||
COLOR_ORANGE = 0xFFF4A261,
|
||||
COLOR_DARK_BLUE_GREY = 0xFF264653,
|
||||
COLOR_MAUVE = 0xFFB5838D,
|
||||
COLOR_RED = 0xFFD7263D,
|
||||
COLOR_TURQUOISE = 0xFF38A3A5,
|
||||
COLOR_GREY = 0xFF757575,
|
||||
COLOR_LIGHT_GREEN_BLUE = 0xFF70C1B3,
|
||||
COLOR_YELLOW = 0xFFFFC300,
|
||||
COLOR_DEEP_PURPLE = 0xFF5D2E8C
|
||||
} color_enum_t;
|
||||
|
||||
typedef struct mesh_t mesh_t;
|
||||
struct mesh_t {
|
||||
vec3_t* vertices;
|
||||
face_t* faces;
|
||||
vec3_t rotation;
|
||||
vec3_t scale;
|
||||
vec3_t translation;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Define a struct for dynamic size meshes, with array of vertices and faces
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
typedef struct {
|
||||
vec3_t* vertices; // dynamic array of vertices
|
||||
face_t* faces; // dynamic array of faces
|
||||
vec3_t rotation; // rotation with x, y, and z values
|
||||
vec3_t scale; // scale with x, y, and z values
|
||||
vec3_t translation; // translation with x, y, and z values
|
||||
} mesh_t;
|
||||
|
||||
extern mesh_t mesh;
|
||||
|
||||
void parse_face(const char* buffer, face_t* face);
|
||||
|
||||
void load_cube_mesh_data(void);
|
||||
void load_file(const char* filename);
|
||||
void load_obj_file_data(char* filename);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,2 +1,7 @@
|
||||
#ifndef SWAP_H
|
||||
#define SWAP_H
|
||||
|
||||
void int_swap(int* a, int* b);
|
||||
void float_swap(float* a, float* b);
|
||||
void float_swap(float* a, float* b);
|
||||
|
||||
#endif
|
||||
|
||||
@ -71,4 +71,4 @@ const uint8_t REDBRICK_TEXTURE[] = {
|
||||
0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x38, 0x38, 0x38, 0xff, 0x34, 0x34, 0x34, 0xff, 0x34, 0x34, 0x34, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x38, 0x38, 0x38, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x20, 0x20, 0x20, 0xff, 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff,
|
||||
0x38, 0x38, 0x38, 0xff, 0x54, 0x54, 0x54, 0xff, 0x38, 0x38, 0x38, 0xff, 0x54, 0x54, 0x54, 0xff, 0x38, 0x38, 0x38, 0xff, 0x38, 0x38, 0x38, 0xff, 0x38, 0x38, 0x38, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x38, 0x38, 0x38, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x38, 0x38, 0x38, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x40, 0x40, 0x40, 0xff, 0x38, 0x38, 0x38, 0xff, 0x38, 0x38, 0x38, 0xff, 0x40, 0x40, 0x40, 0xff, 0x38, 0x38, 0x38, 0xff, 0x38, 0x38, 0x38, 0xff, 0x40, 0x40, 0x40, 0xff, 0x48, 0x48, 0x48, 0xff, 0x40, 0x40, 0x40, 0xff, 0x38, 0x38, 0x38, 0xff, 0x40, 0x40, 0x40, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x38, 0x38, 0x38, 0xff, 0x54, 0x54, 0x54, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x40, 0x40, 0x40, 0xff, 0x38, 0x38, 0x38, 0xff, 0x40, 0x40, 0x40, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff, 0x48, 0x48, 0x48, 0xff,
|
||||
0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff,
|
||||
};
|
||||
};
|
||||
|
||||
@ -15,4 +15,4 @@ extern const uint8_t REDBRICK_TEXTURE[];
|
||||
|
||||
extern uint32_t* mesh_texture;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1,34 +1,6 @@
|
||||
#include "triangle.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "display.h"
|
||||
|
||||
// TODO: Create implementation for triangle.h functions
|
||||
int compare_vec2_t(const void* a, const void* b) {
|
||||
const int_vec2_t* arg1 = (const int_vec2_t*)a;
|
||||
const int_vec2_t* arg2 = (const int_vec2_t*)b;
|
||||
if (arg1->y < arg2->y) return -1;
|
||||
if (arg1->y > arg2->y) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FUNC (int)ceilf
|
||||
#define FUNC2 (int)floorf
|
||||
|
||||
uint32_t invert_rgb(uint32_t color) {
|
||||
uint32_t a = color & 0xFF000000; // Alpha channel
|
||||
uint32_t rgb = color & 0x00FFFFFF; // RGB channels
|
||||
rgb = ~rgb & 0x00FFFFFF; // Invert RGB only
|
||||
return a | rgb;
|
||||
}
|
||||
|
||||
void draw_triangle(triangle_t triangle, uint32_t color) {
|
||||
draw_line(triangle.points[0].x, triangle.points[0].y, triangle.points[1].x, triangle.points[1].y, color);
|
||||
draw_line(triangle.points[1].x, triangle.points[1].y, triangle.points[2].x, triangle.points[2].y, color);
|
||||
draw_line(triangle.points[2].x, triangle.points[2].y, triangle.points[0].x, triangle.points[0].y, color);
|
||||
}
|
||||
#include "swap.h"
|
||||
#include "triangle.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Draw a filled a triangle with a flat bottom
|
||||
@ -147,13 +119,37 @@ void draw_filled_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Draw a triangle using three raw line calls
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color) {
|
||||
draw_line(x0, y0, x1, y1, color);
|
||||
draw_line(x1, y1, x2, y2, color);
|
||||
draw_line(x2, y2, x0, y0, color);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Return the barycentric weights alpha, beta, and gamma for point p
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (B)
|
||||
// /|\
|
||||
// / | \
|
||||
// / | \
|
||||
// / (P) \
|
||||
// / / \ \
|
||||
// / / \ \
|
||||
// // \\
|
||||
// (A)------------(C)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
vec3_t barycentric_weights(vec2_t a, vec2_t b, vec2_t c, vec2_t p) {
|
||||
// Find the vectors between the vertices ABC and point p
|
||||
vec2_t ac = vec2_subtract(c, a);
|
||||
vec2_t ab = vec2_subtract(b, a);
|
||||
vec2_t ap = vec2_subtract(p, a);
|
||||
vec2_t pc = vec2_subtract(c, p);
|
||||
vec2_t pb = vec2_subtract(b, p);
|
||||
vec2_t ac = vec2_sub(c, a);
|
||||
vec2_t ab = vec2_sub(b, a);
|
||||
vec2_t ap = vec2_sub(p, a);
|
||||
vec2_t pc = vec2_sub(c, p);
|
||||
vec2_t pb = vec2_sub(b, p);
|
||||
|
||||
// Compute the area of the full parallegram/triangle ABC using 2D cross product
|
||||
float area_parallelogram_abc = (ac.x * ab.y - ac.y * ab.x); // || AC x AB ||
|
||||
@ -170,62 +166,113 @@ vec3_t barycentric_weights(vec2_t a, vec2_t b, vec2_t c, vec2_t p) {
|
||||
vec3_t weights = { alpha, beta, gamma };
|
||||
return weights;
|
||||
}
|
||||
////////////////////////////
|
||||
// Function to draw textue at x/y using interpolation
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Function to draw the textured pixel at position x and y using interpolation
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void draw_texel(
|
||||
int x, int y, uint32_t* texture,
|
||||
vec2_t point_a, vec2_t point_b, vec2_t point_c,
|
||||
float u0, float v0, float u1, float v1, float u2, float v2) {
|
||||
vec2_t point_p = { x, y };
|
||||
vec3_t weights = barycentric_weights(point_a, point_b, point_c, point_p);
|
||||
vec4_t point_a, vec4_t point_b, vec4_t point_c,
|
||||
tex2_t a_uv, tex2_t b_uv, tex2_t c_uv
|
||||
) {
|
||||
vec2_t p = { x, y };
|
||||
vec2_t a = vec2_from_vec4(point_a);
|
||||
vec2_t b = vec2_from_vec4(point_b);
|
||||
vec2_t c = vec2_from_vec4(point_c);
|
||||
|
||||
// Calculate the barycentric coordinates of our point 'p' inside the triangle
|
||||
vec3_t weights = barycentric_weights(a, b, c, p);
|
||||
|
||||
float alpha = weights.x;
|
||||
float beta = weights.y;
|
||||
float gamma = weights.z;
|
||||
|
||||
// Perform the interpolation of all U and V values using barycentric weights
|
||||
float interpolated_u = (u0) * alpha + (u1) * beta + (u2) * gamma;
|
||||
float interpolated_v = (v0) * alpha + (v1) * beta + (v2) * gamma;
|
||||
// Variables to store the interpolated values of U, V, and also 1/w for the current pixel
|
||||
float interpolated_u;
|
||||
float interpolated_v;
|
||||
float interpolated_reciprocal_w;
|
||||
|
||||
// Perform the interpolation of all U/w and V/w values using barycentric weights and a factor of 1/w
|
||||
interpolated_u = (a_uv.u / point_a.w) * alpha + (b_uv.u / point_b.w) * beta + (c_uv.u / point_c.w) * gamma;
|
||||
interpolated_v = (a_uv.v / point_a.w) * alpha + (b_uv.v / point_b.w) * beta + (c_uv.v / point_c.w) * gamma;
|
||||
|
||||
// Also interpolate the value of 1/w for the current pixel
|
||||
interpolated_reciprocal_w = (1 / point_a.w) * alpha + (1 / point_b.w) * beta + (1 / point_c.w) * gamma;
|
||||
|
||||
// Now we can divide back both interpolated values by 1/w
|
||||
interpolated_u /= interpolated_reciprocal_w;
|
||||
interpolated_v /= interpolated_reciprocal_w;
|
||||
|
||||
// Map the UV coordinate to the full texture width and height
|
||||
int tex_x = abs((int)(interpolated_u * texture_width));
|
||||
int tex_y = abs((int)(interpolated_v * texture_height));
|
||||
|
||||
draw_pixel(x, y, texture[(texture_width * tex_y) + tex_x]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Draw a textured triangle based on a texture array of colors.
|
||||
// We split the original triangle in two, half flat-bottom and half flat-top.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// v0
|
||||
// /\
|
||||
// / \
|
||||
// / \
|
||||
// / \
|
||||
// v1--------\
|
||||
// \_ \
|
||||
// \_ \
|
||||
// \_ \
|
||||
// \_ \
|
||||
// \\
|
||||
// \
|
||||
// v2
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void draw_textured_triangle(
|
||||
int x0, int y0, float u0, float v0,
|
||||
int x1, int y1, float u1, float v1,
|
||||
int x2, int y2, float u2, float v2,
|
||||
uint32_t* texture) {
|
||||
// sort by y
|
||||
int temp = 0, min_idx = 0, mid_idx = 1, max_idx = 2;
|
||||
|
||||
int x0, int y0, float z0, float w0, float u0, float v0,
|
||||
int x1, int y1, float z1, float w1, float u1, float v1,
|
||||
int x2, int y2, float z2, float w2, float u2, float v2,
|
||||
uint32_t* texture
|
||||
) {
|
||||
// We need to sort the vertices by y-coordinate ascending (y0 < y1 < y2)
|
||||
if (y0 > y1) {
|
||||
int_swap(&y0, &y1);
|
||||
int_swap(&x0, &x1);
|
||||
float_swap(&z0, &z1);
|
||||
float_swap(&w0, &w1);
|
||||
float_swap(&u0, &u1);
|
||||
float_swap(&v0, &v1);
|
||||
}
|
||||
if (y1 > y2) {
|
||||
int_swap(&y1, &y2);
|
||||
int_swap(&x1, &x2);
|
||||
float_swap(&z1, &z2);
|
||||
float_swap(&w1, &w2);
|
||||
float_swap(&u1, &u2);
|
||||
float_swap(&v1, &v2);
|
||||
}
|
||||
if (y0 > y1) {
|
||||
int_swap(&y0, &y1);
|
||||
int_swap(&x0, &x1);
|
||||
float_swap(&z0, &z1);
|
||||
float_swap(&w0, &w1);
|
||||
float_swap(&u0, &u1);
|
||||
float_swap(&v0, &v1);
|
||||
}
|
||||
|
||||
// create vector points after sorting vertices
|
||||
vec2_t point_a = { x0, y0 };
|
||||
vec2_t point_b = { x1, y1 };
|
||||
vec2_t point_c = { x2, y2 };
|
||||
|
||||
|
||||
// FLAT BOTTOM
|
||||
// Create vector points and texture coords after we sort the vertices
|
||||
vec4_t point_a = { x0, y0, z0, w0 };
|
||||
vec4_t point_b = { x1, y1, z1, w1 };
|
||||
vec4_t point_c = { x2, y2, z2, w2 };
|
||||
tex2_t a_uv = { u0, v0 };
|
||||
tex2_t b_uv = { u1, v1 };
|
||||
tex2_t c_uv = { u2, v2 };
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Render the upper part of the triangle (flat-bottom)
|
||||
///////////////////////////////////////////////////////
|
||||
float inv_slope_1 = 0;
|
||||
float inv_slope_2 = 0;
|
||||
|
||||
@ -238,18 +285,19 @@ void draw_textured_triangle(
|
||||
int x_end = x0 + (y - y0) * inv_slope_2;
|
||||
|
||||
if (x_end < x_start) {
|
||||
int_swap(&x_start, &x_end);
|
||||
int_swap(&x_start, &x_end); // swap if x_start is to the right of x_end
|
||||
}
|
||||
|
||||
for (int x = x_start; x < x_end; x++) {
|
||||
// draw pixel with color from texture
|
||||
//draw_pixel(x, y, (x % 2 == 0 && y % 2 == 0) ? 0xFF00FF00 : 0xFF000000);
|
||||
draw_texel(x, y, texture, point_a, point_b, point_c, u0, v0, u1, v1, u2, v2);
|
||||
// Draw our pixel with the color that comes from the texture
|
||||
draw_texel(x, y, texture, point_a, point_b, point_c, a_uv, b_uv, c_uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FLAT TOP
|
||||
///////////////////////////////////////////////////////
|
||||
// Render the bottom part of the triangle (flat-top)
|
||||
///////////////////////////////////////////////////////
|
||||
inv_slope_1 = 0;
|
||||
inv_slope_2 = 0;
|
||||
|
||||
@ -262,18 +310,13 @@ void draw_textured_triangle(
|
||||
int x_end = x0 + (y - y0) * inv_slope_2;
|
||||
|
||||
if (x_end < x_start) {
|
||||
int_swap(&x_start, &x_end);
|
||||
int_swap(&x_start, &x_end); // swap if x_start is to the right of x_end
|
||||
}
|
||||
|
||||
for (int x = x_start; x < x_end; x++) {
|
||||
// draw pixel with color from texture
|
||||
//draw_pixel(x, y, (x % 2 == 0 && y % 2 == 0) ? 0xFF00FF00 : 0xFF000000);
|
||||
draw_texel(x, y, texture, point_a, point_b, point_c, u0, v0, u1, v1, u2, v2);
|
||||
// Draw our pixel with the color that comes from the texture
|
||||
draw_texel(x, y, texture, point_a, point_b, point_c, a_uv, b_uv, c_uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,13 +2,8 @@
|
||||
#define TRIANGLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "texture.h"
|
||||
#include "swap.h"
|
||||
#include "vector.h"
|
||||
#include "texture.h"
|
||||
|
||||
typedef uint32_t color_t;
|
||||
|
||||
typedef struct {
|
||||
int a;
|
||||
@ -17,31 +12,24 @@ typedef struct {
|
||||
tex2_t a_uv;
|
||||
tex2_t b_uv;
|
||||
tex2_t c_uv;
|
||||
color_t color;
|
||||
uint32_t color;
|
||||
} face_t;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
} int_vec2_t;
|
||||
|
||||
typedef struct {
|
||||
vec2_t points[3];
|
||||
vec4_t points[3];
|
||||
tex2_t texcoords[3];
|
||||
color_t color;
|
||||
float average_depth;
|
||||
uint32_t color;
|
||||
float avg_depth;
|
||||
} triangle_t;
|
||||
|
||||
void draw_triangle(triangle_t triangle, uint32_t color);
|
||||
void draw_filled_triangle(int x0, int y0, int x1, int y1, int x2, int y2, color_t color);
|
||||
void draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color);
|
||||
void draw_filled_triangle(int x0, int y0, int x1, int y1, int x2, int y2, uint32_t color);
|
||||
|
||||
void draw_textured_triangle(
|
||||
int x0, int y0, float u0, float v0,
|
||||
int x1, int y1, float u1, float v1,
|
||||
int x2, int y2, float u2, float v2,
|
||||
uint32_t* texture);
|
||||
void draw_texel(
|
||||
int x, int y, uint32_t* texture,
|
||||
vec2_t point_a, vec2_t point_b, vec2_t point_c,
|
||||
float u0, float v0, float u1, float v1, float u2, float v2);
|
||||
int x0, int y0, float z0, float w0, float u0, float v0,
|
||||
int x1, int y1, float z1, float w1, float u1, float v1,
|
||||
int x2, int y2, float z2, float w2, float u2, float v2,
|
||||
uint32_t* texture
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
191
scripts/vector.c
191
scripts/vector.c
@ -1,143 +1,158 @@
|
||||
#include <math.h>
|
||||
#include "vector.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// TODO: Implementation of all vector functions
|
||||
vec3_t vec3_rotate_x(vec3_t v, float angle) {
|
||||
return (vec3_t) {
|
||||
.x = v.x,
|
||||
.y = v.y * cos(angle) - v.z * sin(angle),
|
||||
.z = v.y * sin(angle) + v.z * cos(angle),
|
||||
};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Implementations of Vector 2 functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
float vec2_length(vec2_t v) {
|
||||
return sqrt(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
vec3_t vec3_rotate_y(vec3_t v, float angle) {
|
||||
return (vec3_t) {
|
||||
.x = v.x * cos(angle) - v.z * sin(angle),
|
||||
.y = v.y,
|
||||
.z = v.x * sin(angle) + v.z * cos(angle),
|
||||
};
|
||||
}
|
||||
|
||||
vec3_t vec3_rotate_z(vec3_t v, float angle) {
|
||||
return (vec3_t) {
|
||||
.x = v.x * cos(angle) - v.y * sin(angle),
|
||||
.y = v.x * sin(angle) + v.y * cos(angle),
|
||||
.z = v.z,
|
||||
};
|
||||
}
|
||||
|
||||
float vec2_length(const vec2_t vector) {
|
||||
return sqrt((vector.x * vector.x) + (vector.y * vector.y));
|
||||
}
|
||||
|
||||
vec2_t vec2_add(const vec2_t a, const vec2_t b) {
|
||||
return (vec2_t) {
|
||||
vec2_t vec2_add(vec2_t a, vec2_t b) {
|
||||
vec2_t result = {
|
||||
.x = a.x + b.x,
|
||||
.y = a.y + b.y,
|
||||
.y = a.y + b.y
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
vec2_t vec2_subtract(const vec2_t a, const vec2_t b) {
|
||||
return (vec2_t) {
|
||||
vec2_t vec2_sub(vec2_t a, vec2_t b) {
|
||||
vec2_t result = {
|
||||
.x = a.x - b.x,
|
||||
.y = a.y - b.y,
|
||||
.y = a.y - b.y
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
vec2_t vec2_multiply(const vec2_t vector, float scalar) {
|
||||
return (vec2_t) {
|
||||
.x = vector.x * scalar,
|
||||
.y = vector.y * scalar,
|
||||
vec2_t vec2_mul(vec2_t v, float factor) {
|
||||
vec2_t result = {
|
||||
.x = v.x * factor,
|
||||
.y = v.y * factor
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
vec2_t vec2_divide(const vec2_t vector, float scalar) {
|
||||
return (vec2_t) {
|
||||
.x = vector.x / scalar,
|
||||
.y = vector.y / scalar,
|
||||
vec2_t vec2_div(vec2_t v, float factor) {
|
||||
vec2_t result = {
|
||||
.x = v.x / factor,
|
||||
.y = v.y / factor
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
float vec2_dot(const vec2_t a, const vec2_t b) {
|
||||
float vec2_dot(vec2_t a, vec2_t b) {
|
||||
return (a.x * b.x) + (a.y * b.y);
|
||||
}
|
||||
|
||||
float vec3_length(const vec3_t vector) {
|
||||
return sqrtf((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z));
|
||||
void vec2_normalize(vec2_t* v) {
|
||||
float length = sqrt(v->x * v->x + v->y * v->y);
|
||||
v->x /= length;
|
||||
v->y /= length;
|
||||
}
|
||||
|
||||
void vec2_normalize(vec2_t* vertex) {
|
||||
float length = vec2_length(*vertex);
|
||||
vertex->x /= length;
|
||||
vertex->y /= length;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Implementations of Vector 3 functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
float vec3_length(vec3_t v) {
|
||||
return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
}
|
||||
|
||||
vec3_t vec3_add(const vec3_t a, const vec3_t b) {
|
||||
return (vec3_t) {
|
||||
vec3_t vec3_add(vec3_t a, vec3_t b) {
|
||||
vec3_t result = {
|
||||
.x = a.x + b.x,
|
||||
.y = a.y + b.y,
|
||||
.z = a.z + b.z,
|
||||
.z = a.z + b.z
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3_t vec3_subtract(const vec3_t a, const vec3_t b) {
|
||||
return (vec3_t) {
|
||||
vec3_t vec3_sub(vec3_t a, vec3_t b) {
|
||||
vec3_t result = {
|
||||
.x = a.x - b.x,
|
||||
.y = a.y - b.y,
|
||||
.z = a.z - b.z,
|
||||
.z = a.z - b.z
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3_t vec3_multiply(const vec3_t vector, const float scalar) {
|
||||
return (vec3_t) {
|
||||
.x = vector.x * scalar,
|
||||
.y = vector.y * scalar,
|
||||
.z = vector.z * scalar,
|
||||
vec3_t vec3_mul(vec3_t v, float factor) {
|
||||
vec3_t result = {
|
||||
.x = v.x * factor,
|
||||
.y = v.y * factor,
|
||||
.z = v.z * factor
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3_t vec3_divide(const vec3_t vector, const float scalar) {
|
||||
return (vec3_t) {
|
||||
.x = vector.x / scalar,
|
||||
.y = vector.y / scalar,
|
||||
.z = vector.z / scalar,
|
||||
vec3_t vec3_div(vec3_t v, float factor) {
|
||||
vec3_t result = {
|
||||
.x = v.x / factor,
|
||||
.y = v.y / factor,
|
||||
.z = v.z / factor
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3_t vec3_cross(const vec3_t a, const vec3_t b) {
|
||||
return (vec3_t) {
|
||||
vec3_t vec3_cross(vec3_t a, vec3_t b) {
|
||||
vec3_t result = {
|
||||
.x = a.y * b.z - a.z * b.y,
|
||||
.y = a.z * b.x - a.x * b.z,
|
||||
.z = a.x * b.y - a.y * b.x,
|
||||
.z = a.x * b.y - a.y * b.x
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
float vec3_dot(const vec3_t a, const vec3_t b) {
|
||||
float vec3_dot(vec3_t a, vec3_t b) {
|
||||
return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
|
||||
}
|
||||
|
||||
void vec3_normalize(vec3_t* vertex) {
|
||||
float length = vec3_length(*vertex);
|
||||
vertex->x /= length;
|
||||
vertex->y /= length;
|
||||
vertex->z /= length;
|
||||
void vec3_normalize(vec3_t* v) {
|
||||
float length = sqrt(v->x * v->x + v->y * v->y + v->z * v->z);
|
||||
v->x /= length;
|
||||
v->y /= length;
|
||||
v->z /= length;
|
||||
}
|
||||
vec3_t vec3_rotate_x(vec3_t v, float angle) {
|
||||
vec3_t rotated_vector = {
|
||||
.x = v.x,
|
||||
.y = v.y * cos(angle) - v.z * sin(angle),
|
||||
.z = v.y * sin(angle) + v.z * cos(angle)
|
||||
};
|
||||
return rotated_vector;
|
||||
}
|
||||
|
||||
vec4_t vec4_from_vec3(vec3_t vertex) {
|
||||
vec4_t ret;
|
||||
ret.x = vertex.x;
|
||||
ret.y = vertex.y;
|
||||
ret.z = vertex.z;
|
||||
ret.w = 1;
|
||||
vec3_t vec3_rotate_y(vec3_t v, float angle) {
|
||||
vec3_t rotated_vector = {
|
||||
.x = v.x * cos(angle) + v.z * sin(angle),
|
||||
.y = v.y,
|
||||
.z = -v.x * sin(angle) + v.z * cos(angle)
|
||||
};
|
||||
return rotated_vector;
|
||||
}
|
||||
|
||||
return ret;
|
||||
vec3_t vec3_rotate_z(vec3_t v, float angle) {
|
||||
vec3_t rotated_vector = {
|
||||
.x = v.x * cos(angle) - v.y * sin(angle),
|
||||
.y = v.x * sin(angle) + v.y * cos(angle),
|
||||
.z = v.z
|
||||
};
|
||||
return rotated_vector;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Implementations of Vector conversion functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
vec4_t vec4_from_vec3(vec3_t v) {
|
||||
vec4_t result = { v.x, v.y, v.z, 1.0 };
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3_t vec3_from_vec4(vec4_t v) {
|
||||
return (vec3_t) {
|
||||
.x = v.x,
|
||||
.y = v.y,
|
||||
.z = v.z,
|
||||
};
|
||||
}
|
||||
vec3_t result = { v.x, v.y, v.z };
|
||||
return result;
|
||||
}
|
||||
|
||||
vec2_t vec2_from_vec4(vec4_t v) {
|
||||
vec2_t result = { v.x, v.y };
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2,45 +2,47 @@
|
||||
#define VECTOR_H
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float x, y;
|
||||
} vec2_t;
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float x, y, z;
|
||||
} vec3_t;
|
||||
|
||||
typedef struct {
|
||||
float x, y, z, w;
|
||||
} vec4_t;
|
||||
|
||||
// TODO: Add functions to manipulate vectors 2D and 3D
|
||||
// ...
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Vector 2 functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
float vec2_length(vec2_t v);
|
||||
vec2_t vec2_add(vec2_t a, vec2_t b);
|
||||
vec2_t vec2_sub(vec2_t a, vec2_t b);
|
||||
vec2_t vec2_mul(vec2_t v, float factor);
|
||||
vec2_t vec2_div(vec2_t v, float factor);
|
||||
void vec2_normalize(vec2_t* v);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Vector 3 functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
float vec3_length(vec3_t v);
|
||||
vec3_t vec3_add(vec3_t a, vec3_t b);
|
||||
vec3_t vec3_sub(vec3_t a, vec3_t b);
|
||||
vec3_t vec3_mul(vec3_t v, float factor);
|
||||
vec3_t vec3_div(vec3_t v, float factor);
|
||||
vec3_t vec3_cross(vec3_t a, vec3_t b);
|
||||
float vec3_dot(vec3_t a, vec3_t b);
|
||||
void vec3_normalize(vec3_t* v);
|
||||
vec3_t vec3_rotate_x(vec3_t v, float angle);
|
||||
vec3_t vec3_rotate_y(vec3_t v, float angle);
|
||||
vec3_t vec3_rotate_z(vec3_t v, float angle);
|
||||
|
||||
vec2_t vec2_add(const vec2_t a, const vec2_t b);
|
||||
vec2_t vec2_subtract(const vec2_t a, const vec2_t b);
|
||||
vec2_t vec2_multiply(const vec2_t vector, float scalar);
|
||||
vec2_t vec2_divide(const vec2_t vector, float scalar);
|
||||
float vec2_length(const vec2_t vector);
|
||||
float vec2_dot(const vec2_t a, const vec2_t b);
|
||||
void vec2_normalize(vec2_t* vertex);
|
||||
|
||||
vec3_t vec3_add(const vec3_t a, const vec3_t b);
|
||||
vec3_t vec3_subtract(const vec3_t a, const vec3_t b);
|
||||
vec3_t vec3_multiply(const vec3_t vector, const float scalar);
|
||||
vec3_t vec3_divide(const vec3_t vector, const float scalar);
|
||||
vec3_t vec3_cross(const vec3_t a, const vec3_t b);
|
||||
float vec3_length(const vec3_t vector);
|
||||
float vec3_dot(const vec3_t a, const vec3_t b);
|
||||
void vec3_normalize(vec3_t* vertex);
|
||||
|
||||
vec4_t vec4_from_vec3(vec3_t vertex);
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Vector conversion functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
vec4_t vec4_from_vec3(vec3_t v);
|
||||
vec3_t vec3_from_vec4(vec4_t v);
|
||||
vec2_t vec2_from_vec4(vec4_t v);
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user