From a3a74765c9cb9b761faa83f682fe9b6d146170c5 Mon Sep 17 00:00:00 2001 From: Alexander Bass Date: Mon, 22 Apr 2024 00:08:05 -0400 Subject: [PATCH] C donut --- .clangd | 2 - makefile | 17 +----- src/donut.c | 93 +++++++++++++++++++++++++++++++ src/donut.cpp | 94 ------------------------------- src/donut.h | 7 ++- src/main.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 132 -------------------------------------------- src/point.c | 10 ++++ src/point.cpp | 35 ------------ src/point.h | 85 +++------------------------- src/point_list.c | 46 ++++++++++++++++ src/point_list.h | 18 ++++++ src/ppm/ppm.c | 40 ++++++++++++++ src/ppm/ppm.cpp | 29 ---------- src/ppm/ppm.h | 13 ++--- src/rgb.h | 19 ------- src/texture.c | 15 +++++ src/texture.h | 14 +++++ src/types.h | 10 ++-- src/vec3.c | 55 ++++++++++++++++++ src/vec3.h | 18 ++++++ src/vec4.c | 8 +++ src/vec4.h | 13 +++++ test.cpp | 12 ++++ 24 files changed, 507 insertions(+), 419 deletions(-) delete mode 100644 .clangd create mode 100644 src/donut.c delete mode 100644 src/donut.cpp create mode 100644 src/main.c delete mode 100644 src/main.cpp create mode 100644 src/point.c delete mode 100644 src/point.cpp create mode 100644 src/point_list.c create mode 100644 src/point_list.h create mode 100644 src/ppm/ppm.c delete mode 100644 src/ppm/ppm.cpp delete mode 100644 src/rgb.h create mode 100644 src/texture.c create mode 100644 src/texture.h create mode 100644 src/vec3.c create mode 100644 src/vec3.h create mode 100644 src/vec4.c create mode 100644 src/vec4.h create mode 100644 test.cpp diff --git a/.clangd b/.clangd deleted file mode 100644 index 7058e79..0000000 --- a/.clangd +++ /dev/null @@ -1,2 +0,0 @@ -CompileFlags: - Add: [-std=c++20] \ No newline at end of file diff --git a/makefile b/makefile index eb6718b..5b39bf1 100644 --- a/makefile +++ b/makefile @@ -5,17 +5,15 @@ BUILD_DIR := ./build SRC_DIRS := ./src ./includes RESOURCE_DIRS := ./resources -CXX := g++ CC := gcc ld := g++ -BASEFLAGS = -g -Wall -Wextra -Wconversion -Wduplicated-branches -Wduplicated-cond -Wlogical-op -Wnull-dereference -Wuseless-cast -Wdouble-promotion -Wshadow -Wformat=2 -CXXFLAGS = -std=c++20 $(BASEFLAGS) -Wuseless-cast +BASEFLAGS = -g -Wall -Wextra -Wconversion -Wduplicated-branches -Wduplicated-cond -Wlogical-op -Wnull-dereference -Wdouble-promotion -Wshadow -Wformat=2 CFLAGS = $(BASEFLAGS) -Wjump-misses-init # Find all the C and C++ files we want to compile # Note the single quotes around the * expressions. The shell will incorrectly expand these otherwise, but we want to send the * directly to the find command. -SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s') +SRCS := $(shell find $(SRC_DIRS) -name '*.c') # Prepends BUILD_DIR and appends .o to every src file # As an example, ./your_dir/hello.cpp turns into ./build/./your_dir/hello.cpp.o @@ -30,9 +28,6 @@ INC_DIRS := $(shell find $(SRC_DIRS) -type d) # Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag INC_FLAGS := $(addprefix -I,$(INC_DIRS)) -# The -MMD and -MP flags together generate Makefiles for us! -# These files will have .d instead of .o as the output. -CPPFLAGS := $(INC_FLAGS) -MMD -MP # The final build step. $(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) @@ -44,10 +39,6 @@ $(BUILD_DIR)/%.c.o: %.c mkdir -p $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ -# Build step for C++ source -$(BUILD_DIR)/%.cpp.o: %.cpp - mkdir -p $(dir $@) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ @@ -55,7 +46,3 @@ $(BUILD_DIR)/%.cpp.o: %.cpp clean: rm -r $(BUILD_DIR) -# Include the .d makefiles. The - at the front suppresses the errors of missing -# Makefiles. Initially, all the .d files will be missing, and we don't want those -# errors to show up. --include $(DEPS) \ No newline at end of file diff --git a/src/donut.c b/src/donut.c new file mode 100644 index 0000000..8ba5126 --- /dev/null +++ b/src/donut.c @@ -0,0 +1,93 @@ +// Alexander Bass +// Created 4/16/24 +// Modified 4/21/24 + +#include "donut.h" +#include "point.h" +#include "types.h" + +#include "point_list.h" +#include "texture.h" +#include "vec3.h" + +vec3_t sample_rgb(texture_t tex, size_t index) { + u8 red = tex.bytes[index]; + u8 green = tex.bytes[index + 1]; + u8 blue = tex.bytes[index + 2]; + vec3_t color = vec3((f64)red, (f64)green, (f64)blue); + color = mul_vec(color, vec3(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0)); + return color; +}; + +vec3_t mix_transparency(vec3_t transparent, vec3_t solid) { + if (transparent.i == 0.0 && transparent.j == 0.0 && transparent.k == 0.0) { + return solid; + } else { + return transparent; + } +} +void generate_cube(point_list_t *points, texture_t bottom_tex, texture_t top_tex, texture_t side_tex, i32 face_x, i32 face_y) { + const vec3_t grass_color_scale = vec3(0.4, 1.0, 0.4); + const size_t image_size = 16; + const size_t point_count = 32; + const size_t world_width = 16; + for (size_t l_x = 0; l_x < point_count; l_x++) { + for (size_t l_y = 0; l_y < point_count; l_y++) { + + f64 sx = (f64)l_x / (f64)point_count; + f64 sy = (f64)l_y / (f64)point_count; + size_t index = 3 * ((size_t)(sx * (f64)(image_size)) + (size_t)(sy * (f64)(image_size)) * image_size); + vec3_t dirt = sample_rgb(bottom_tex, index); + vec3_t grass = sample_rgb(top_tex, index); + vec3_t side = sample_rgb(side_tex, index); + grass = mul_vec(grass, grass_color_scale); + side = mul_vec(side, grass_color_scale); + + side = mix_transparency(side, dirt); + + f64 x_w = sx * (f64)world_width; + f64 y_w = sy * (f64)world_width; + f64 w_w = (f64)world_width; + + if (face_y == -1 || (face_y == 1 && face_x == 0)) { + push_point(points, point(vec3(x_w, 0, y_w), side)); + } + if (face_x == -1 || (face_x == 1 && face_y == 0)) { + push_point(points, point(vec3(0, x_w, y_w), side)); + } + if (face_x == 1 || (face_x == -1 && face_y == 0)) { + push_point(points, point(vec3(w_w, x_w, y_w), side)); + } + if (face_y == 1 || (face_y == -1 && face_x == 0)) { + push_point(points, point(vec3(x_w, w_w, y_w), side)); + } + + push_point(points, point(vec3(x_w, y_w, w_w), dirt)); + push_point(points, point(vec3(x_w, y_w, 0.0), grass)); + } + } + + for (size_t i = 0; i < points->length; i++) { + point_t *p = &points->list[i]; + p->pos.i += ((f64)(face_x) * (f64)(world_width) - (f64)(world_width) / 2.0); + p->pos.j += ((f64)(face_y) * (f64)(world_width) - (f64)(world_width) / 2.0); + p->pos.k += (-(f64)world_width / 2.0); + rotate_j(&p->pos, 180 * 3.14159265 / 180); + } +} + +point_list_t generate_donut(texture_t bottom, texture_t top, texture_t side) { + point_list_t donut_points = point_list(15000); + for (i32 x = -1; x <= 1; x++) { + for (i32 y = -1; y <= 1; y++) { + if (x == y && x == 0) { + continue; + } + point_list_t cube_points = point_list(2000); + generate_cube(&cube_points, bottom, top, side, x, y); + extend_point_list(&donut_points, &cube_points); + free_point_list(&cube_points); + } + } + return donut_points; +} \ No newline at end of file diff --git a/src/donut.cpp b/src/donut.cpp deleted file mode 100644 index 91ff945..0000000 --- a/src/donut.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Alexander Bass -// Created 4/16/24 - -#include "donut.h" -#include "point.h" -#include "types.h" -#include - -#include "rgb.h" - -rgb sample_rgb(u8 *texture, usize index) { - u8 d_red = texture[index * 3]; - u8 d_green = texture[index * 3 + 1]; - u8 d_blue = texture[index * 3 + 2]; - f64 d_r = (f64)d_red / 255.0; - f64 d_g = (f64)d_green / 255.0; - f64 d_b = (f64)d_blue / 255.0; - return rgb(d_r, d_g, d_b); -}; - -inline rgb mix_transparency(rgb transparent, rgb solid) { - if (transparent.r == 0.0 && transparent.g == 0.0 && transparent.b == 0.0) { - return solid; - } - return transparent; -} - -std::vector generate_cube(u8 *bottom_texture, u8 *top_texture, u8 *side_texture, i32 face_x, i32 face_y) { - std::vector out = {}; - const usize image_size = 16; - const usize point_count = 22; - const usize world_width = 16; - for (usize l_x = 0; l_x < point_count; l_x++) { - for (usize l_y = 0; l_y < point_count; l_y++) { - - f64 sx = (f64)l_x / (f64)point_count; - f64 sy = (f64)l_y / (f64)point_count; - usize index = (usize)(sx * (f64)(image_size)) + usize(sy * (f64)(image_size)) * image_size; - rgb dirt = sample_rgb(bottom_texture, index); - rgb grass = sample_rgb(top_texture, index); - rgb sides = sample_rgb(side_texture, index); - grass.mix(rgb(0.4, 1.0, 0.4)); - sides.mix(rgb(0.4, 1.0, 0.4)); - - sides = mix_transparency(sides, dirt); - - f64 x_w = sx * (f64)world_width; - f64 y_w = sy * (f64)world_width; - f64 w_w = (f64)world_width; - - if (face_y == -1 || (face_y == 1 && face_x == 0)) { - out.push_back(*Point(x_w, 0, y_w).set_rgb(sides)); - } - if (face_x == -1 || (face_x == 1 && face_y == 0)) { - out.push_back(*Point(0, x_w, y_w).set_rgb(sides)); - } - if (face_x == 1 || (face_x == -1 && face_y == 0)) { - out.push_back(*Point(w_w, x_w, y_w).set_rgb(sides)); - } - if (face_y == 1 || (face_y == -1 && face_x == 0)) { - out.push_back(*Point(x_w, w_w, y_w).set_rgb(sides)); - } - - out.push_back(*Point(x_w, y_w, w_w).set_rgb(dirt)); - out.push_back(*Point(x_w, y_w, 0.0).set_rgb(grass)); - } - } - for (usize i = 0; i < out.size(); i++) { - Point *p = &out[i]; - p->translate_x((f64)face_x * (f64)world_width - (f64)world_width / 2.0); - p->translate_y((f64)face_y * (f64)world_width - (f64)world_width / 2.0); - p->translate_z(-(f64)world_width / 2.0); - } - return out; -} - -std::vector generate_donut(u8 *bottom_texture, u8 *top_texture, u8 *side_texture, f64 offset) { - std::vector points = {}; - for (i32 x = -1; x <= 1; x++) { - for (i32 y = -1; y <= 1; y++) { - if (x == y && x == 0) { - continue; - } - std::vector pt = generate_cube(bottom_texture, top_texture, side_texture, x, y); - points.insert(points.end(), pt.begin(), pt.end()); - } - } - for (usize i = 0; i < points.size(); i++) { - Point *point = &points[i]; - point->translate_z(offset); - } - - return points; -} \ No newline at end of file diff --git a/src/donut.h b/src/donut.h index 9ad7930..6234870 100644 --- a/src/donut.h +++ b/src/donut.h @@ -1,8 +1,9 @@ // Alexander Bass // Created 4/16/24 +// Modified 4/21/24 #pragma once -#include "point.h" -#include +#include "point_list.h" +#include "texture.h" -std::vector generate_donut(u8 *bottom_texture, u8 *top_texture, u8 *side_texture, f64); +point_list_t generate_donut(texture_t bottom, texture_t top, texture_t side); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..6eae782 --- /dev/null +++ b/src/main.c @@ -0,0 +1,141 @@ +// Alexander Bass +// Created 4/16/24 +// Modified 4/21/24 + +#include "donut.h" +#include "point.h" +#include "point_list.h" +#include "ppm/ppm.h" +#include "texture.h" +#include "types.h" +#include "vec3.h" +#include "vec4.h" +#include +#include +#include +#include +#include +#include + +const i32 WIDTH = 120; +const i32 HEIGHT = 90; +const i32 DEPTH = WIDTH; + +void draw(vec4_t *, const point_list_t *); +void update(point_list_t *); + +int main() { + texture_t dirt = load_ppm_file("dirt.ppm"); + texture_t grass = load_ppm_file("grass_top.ppm"); + texture_t grass_side = load_ppm_file("grass_side.ppm"); + + // point_list_t points = point_list(300); + + point_list_t points = generate_donut(dirt, grass, grass_side); + // extend_point_list(&points, &donut_points); + // free_point_list(&donut_points); + + free_texture(&dirt); + free_texture(&grass); + free_texture(&grass_side); + + vec4_t *pixel_buffer = malloc((size_t)(WIDTH * HEIGHT) * sizeof(vec4_t)); + for (u32 i = 0; i < (u32)(WIDTH * HEIGHT); i++) { + // pixel_buffer[i] = vec4(0.0, 0.0, 0.0, 0.0); + }; + + struct timespec tim; + tim.tv_sec = 0; + tim.tv_nsec = 1000000L * 1000L / 60L; + + while (true) { + // Move cursor to top left + printf("\033[0;0H"); + // Draw points + draw(pixel_buffer, &points); + // Rotate points + update(&points); + // Wait + nanosleep(&tim, NULL); + // Repeat + } + + free_point_list(&points); + free(pixel_buffer); + return 0; +} + +i32 w_x_to_screen(f64 w_x) { + return (i32)(round(w_x)) + WIDTH / 2; +} + +i32 w_y_to_screen(f64 w_y) { + return (i32)(round(w_y)) + HEIGHT / 2; +} + +f64 w_z_to_screen(f64 w_z) { + return (w_z + (f64)(DEPTH) / 2.0) / (f64)(DEPTH); +} + +void draw(vec4_t *pixel_buffer, const point_list_t *points) { + for (u32 i = 0; i < (u32)(WIDTH * HEIGHT); i++) { + pixel_buffer[i].l = 0.0; + }; + + // Pseudo-rasterization + for (size_t i = 0; i < points->length; i++) { + point_t point = points->list[i]; + + vec3_t pos = point.pos; + vec3_t color = point.color; + + f64 p_x = pos.i; + f64 p_y = pos.j; + f64 p_z = pos.k; + + i32 s_x = w_x_to_screen(p_x); + i32 s_y = w_y_to_screen(p_y); + f64 s_z = w_z_to_screen(p_z); + + if (0 <= s_x && s_x < WIDTH && 0 <= s_y && s_y < HEIGHT) { + size_t index = (size_t)(s_x + s_y * WIDTH); + vec4_t existing = pixel_buffer[index]; + if (existing.l < s_z) { + pixel_buffer[index].i = color.i; + pixel_buffer[index].j = color.j; + pixel_buffer[index].k = color.k; + pixel_buffer[index].l = s_z; + } + }; + } + + for (size_t y = 0; y < (size_t)(HEIGHT); y++) { + for (size_t x = 0; x < (size_t)(WIDTH); x++) { + size_t index = x + y * (size_t)(WIDTH); + vec4_t pixel = pixel_buffer[index]; + f64 depth = pixel.l; + if (depth <= 0.0) { + printf(" "); + continue; + } + + assert(depth >= 0.0); + assert(depth <= 1.0); + + u8 red = (u8)(round(pixel.i * depth * 255.0)); + u8 green = (u8)(round(pixel.j * depth * 255.0)); + u8 blue = (u8)(round(pixel.k * depth * 255.0)); + printf("\033[38;2;%u;%u;%um██", red, green, blue); + } + printf("\n"); + } +} + +void update(point_list_t *points) { + for (size_t i = 0; i < points->length; i++) { + vec3_t *pos = &points->list[i].pos; + rotate_i(pos, 0.02); + rotate_j(pos, -0.04); + rotate_k(pos, 0.03); + } +} diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index ecf3a5e..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// Alexander Bass -// Created 4/16/24 -#include "donut.h" -#include "point.h" -#include "ppm/ppm.h" -#include "types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -const i32 WIDTH = 120; -const i32 HEIGHT = 100; -const i32 DEPTH = WIDTH; - -using std::format; -using std::vector, std::ifstream; - -void draw(size_t *grid, vector &points); -void update(vector &points); - -int main() { - - ifstream dirt_file("dirt.ppm"); - u8 *dirt = ppm::load_ppm(dirt_file); - dirt_file.close(); - ifstream grass_file("grass_top.ppm"); - u8 *grass = ppm::load_ppm(grass_file); - grass_file.close(); - ifstream grass_side_file("grass_side.ppm"); - u8 *grass_side = ppm::load_ppm(grass_side_file); - grass_side_file.close(); - - std::vector points = {}; - points.push_back(*Point(0, 0, 0).set_rgb(1.0, 0, 0)); - - std::vector donut = generate_donut(dirt, grass, grass_side, 0.0); - points.insert(points.end(), donut.begin(), donut.end()); - donut = generate_donut(dirt, grass, grass_side, 32.0); - points.insert(points.end(), donut.begin(), donut.end()); - donut = generate_donut(dirt, grass, grass_side, -32.0); - points.insert(points.end(), donut.begin(), donut.end()); - delete[] dirt; - delete[] grass; - delete[] grass_side; - - auto grid = new size_t[WIDTH * HEIGHT]; - - while (true) { - std::cout << "\033c"; - draw(grid, points); - update(points); - std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 60)); - } - - return 0; -} - -i32 w_x_to_screen(f64 w_x) { - return static_cast(std::round(w_x + static_cast(WIDTH) / 2.0)); -} -i32 w_y_to_screen(f64 w_y) { - return static_cast(std::round(w_y + static_cast(HEIGHT) / 2.0)); -} - -f64 w_z_to_screen(f64 w_z) { - return (w_z + static_cast(DEPTH) / 2.0) / static_cast(DEPTH); -} - -void draw(size_t *grid, vector &points) { - for (u32 i = 0; i < static_cast(WIDTH * HEIGHT); i++) { - grid[i] = 0; - }; - - for (size_t i = 0; i < points.size(); i++) { - Point p = points[i]; - f64 p_x = p.get_x(); - f64 p_y = p.get_y(); - f64 p_z = p.get_z(); - - i32 s_x = w_x_to_screen(p_x); - i32 s_y = w_y_to_screen(p_y); - f64 s_z = w_z_to_screen(p_z); - if (0 <= s_x && s_x < HEIGHT && 0 <= s_y && s_y < HEIGHT) { - size_t index = static_cast(s_x + s_y * HEIGHT); - size_t existing_pixel_handle = grid[index]; - if (existing_pixel_handle == 0) { - grid[index] = i + 1; - } else if (points[existing_pixel_handle - 1].get_z() < p_z) { - grid[index] = i + 1; - } - } - } - - std::string line = ""; - for (size_t y = 0; y < static_cast(WIDTH); y++) { - for (size_t x = 0; x < static_cast(HEIGHT); x++) { - size_t index = x + y * HEIGHT; - size_t handle = grid[index]; - if (handle == 0) { - line += " "; - continue; - } - Point p = points[handle - 1]; - f64 depth = w_z_to_screen(p.get_z()); - assert(depth >= 0.0); - assert(depth <= 1.0); - f64 red = p.get_r() * depth; - f64 green = p.get_g() * depth; - f64 blue = p.get_b() * depth; - u8 r8 = static_cast(round(red * 255.0)); - u8 g8 = static_cast(round(green * 255.0)); - u8 b8 = static_cast(round(blue * 255.0)); - line += format("\033[38;2;{};{};{}m██", r8, g8, b8); - } - line += '\n'; - } - std::cout << line; -} - -void update(vector &points) { - for (size_t i = 0; i < points.size(); i++) { - Point *p = &points[i]; - p->rotate_x(0.02); - p->rotate_y(-0.04); - p->rotate_z(0.03); - } -} diff --git a/src/point.c b/src/point.c new file mode 100644 index 0000000..42bc5d1 --- /dev/null +++ b/src/point.c @@ -0,0 +1,10 @@ +// Alexander Bass +// Created 4/16/24 +// Modified 4/21/24 +#include "point.h" +#include "types.h" + +point_t point(vec3_t pos, vec3_t color) { + point_t p = {pos, color}; + return p; +} \ No newline at end of file diff --git a/src/point.cpp b/src/point.cpp deleted file mode 100644 index f5ab6e0..0000000 --- a/src/point.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Alexander Bass -// Created 4/16/24 -#include "point.h" -#include "types.h" - -#include - -void Point::rotate_x(f64 angle) { - f64 cos_a = cos(angle); - f64 sin_a = sin(angle); - f64 y_1 = this->y * cos_a - this->z * sin_a; - f64 z_1 = this->y * sin_a + this->z * cos_a; - this->y = y_1; - this->z = z_1; -} - -void Point::rotate_y(f64 angle) { - f64 cos_a = cos(angle); - f64 sin_a = sin(angle); - - f64 x_1 = this->x * cos_a + this->z * sin_a; - f64 z_1 = this->z * cos_a - this->x * sin_a; - this->x = x_1; - this->z = z_1; -} - -void Point::rotate_z(f64 angle) { - f64 cos_a = cos(angle); - f64 sin_a = sin(angle); - - f64 x_1 = this->x * cos_a - this->y * sin_a; - f64 y_1 = this->x * sin_a + this->y * cos_a; - this->x = x_1; - this->y = y_1; -} \ No newline at end of file diff --git a/src/point.h b/src/point.h index 055dcc3..4824b25 100644 --- a/src/point.h +++ b/src/point.h @@ -1,81 +1,12 @@ // Alexander Bass -// Created 4/16/24 +// Created 4/16/24 +// Modified 4/21/24 #pragma once -#include "rgb.h" #include "types.h" -class Point { - private: - f64 x; - f64 y; - f64 z; - f64 r; - f64 g; - f64 b; +#include "vec3.h" +typedef struct point_t { + vec3_t pos; + vec3_t color; +} point_t; - public: - Point(f64 _x, f64 _y, f64 _z) { - x = _x; - y = _y; - z = _z; - r = 1.0; - g = 1.0; - b = 1.0; - } - void set_xyz(f64 _x, f64 _y, f64 _z) { - x = _x; - y = _y; - z = _z; - }; - void rotate_x(f64 angle); - void rotate_y(f64 angle); - void rotate_z(f64 angle); - Point *translate(f64 dx, f64 dy, f64 dz) { - x += dx; - y += dy; - z += dz; - return this; - }; - - f64 get_x() const { - return x; - }; - f64 get_y() const { - return y; - }; - f64 get_z() const { - return z; - }; - - f64 get_r() const { - return r; - } - f64 get_g() const { - return g; - } - f64 get_b() const { - return b; - } - - void translate_x(f64 dx) { - x += dx; - } - void translate_y(f64 dy) { - y += dy; - } - void translate_z(f64 dz) { - z += dz; - } - - Point *set_rgb(f64 _r, f64 _g, f64 _b) { - r = _r; - g = _g; - b = _b; - return this; - }; - Point *set_rgb(rgb col) { - r = col.r; - g = col.g; - b = col.b; - return this; - }; -}; \ No newline at end of file +point_t point(vec3_t, vec3_t); \ No newline at end of file diff --git a/src/point_list.c b/src/point_list.c new file mode 100644 index 0000000..67fb7ba --- /dev/null +++ b/src/point_list.c @@ -0,0 +1,46 @@ +// Alexander Bass +// Created 4/21/24 +// Modified 4/21/24 +#include "point_list.h" +#include "point.h" +#include +#include + +point_list_t point_list(size_t capacity) { + point_t *points = (point_t *)(malloc(sizeof(point_t) * capacity)); + point_list_t point_list = {points, 0, capacity}; + return point_list; +} + +void push_point(point_list_t *points, point_t point) { + // Dynamic length list + size_t length = points->length; + size_t capacity = points->capacity; + if (length == capacity) { + size_t new_capacity = capacity + 100; + points->list = realloc(points->list, new_capacity * sizeof(point_t)); + points->capacity = new_capacity; + } + points->list[length] = point; + (points->length)++; +} + +void free_point_list(point_list_t *points) { + free(points->list); +} + +void extend_point_list(point_list_t *points, point_list_t *extension) { + // Dynamic length list + size_t length = points->length; + size_t capacity = points->capacity; + size_t new_length = length + extension->length; + if (new_length >= capacity) { + size_t new_capacity = new_length + 100; + points->list = realloc(points->list, new_capacity * sizeof(point_t)); + points->capacity = new_capacity; + } + for (size_t i = 0; i < extension->length; i++) { + points->list[i + length] = extension->list[i]; + (points->length)++; + } +} \ No newline at end of file diff --git a/src/point_list.h b/src/point_list.h new file mode 100644 index 0000000..a0e420d --- /dev/null +++ b/src/point_list.h @@ -0,0 +1,18 @@ +#pragma once +// Alexander Bass +// Created 4/21/24 +// Modified 4/21/24 +#include "point.h" +#include + +typedef struct point_list_t { + point_t *list; + size_t length; + size_t capacity; +} point_list_t; + +point_list_t point_list(size_t capacity); + +void push_point(point_list_t *points, point_t point); +void free_point_list(point_list_t *points); +void extend_point_list(point_list_t *list, point_list_t *extension); \ No newline at end of file diff --git a/src/ppm/ppm.c b/src/ppm/ppm.c new file mode 100644 index 0000000..8419718 --- /dev/null +++ b/src/ppm/ppm.c @@ -0,0 +1,40 @@ +// Alexander Bass +// Created 4/16/24 +// Modified 4/21/24 +#include "ppm.h" + +#include "../texture.h" +#include "../types.h" +#include +#include + +texture_t load_ppm(FILE *file) { + assert(fgetc(file) == 'P'); + assert(fgetc(file) == '3'); + + u32 width, height; + u32 color; + + fscanf(file, "%d %d", &width, &height); + fscanf(file, "%d", &color); + + assert(width == 16 && height == 16); + assert(color == 255); + + texture_t tex = texture(width, height); + + for (size_t i = 0; i < width * height * 3; i++) { + u8 byte; + fscanf(file, "%hhd", &byte); + tex.bytes[i] = byte; + } + + return tex; +} + +texture_t load_ppm_file(const char *file_name) { + FILE *file = fopen(file_name, "r"); + texture_t tex = load_ppm(file); + fclose(file); + return tex; +} \ No newline at end of file diff --git a/src/ppm/ppm.cpp b/src/ppm/ppm.cpp deleted file mode 100644 index 542dc7b..0000000 --- a/src/ppm/ppm.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// Alexander Bass -// Created 4/16/24 -#include "ppm.h" -using std::string; -#include -#include -#include -u8 *ppm::load_ppm(std::istream &input) { - string header; - input >> header; - assert(header == "P3"); - u32 width, height; - u32 color; - input >> width; - input >> height; - assert(width == 16 && height == 16); - input >> color; - assert(color == 255); - - u8 *buffer = new u8[width * height * 3]; - for (size_t i = 0; i < width * height * 3; i++) { - u16 val = 0; - - input >> val; - buffer[i] = val; - } - - return buffer; -} \ No newline at end of file diff --git a/src/ppm/ppm.h b/src/ppm/ppm.h index 052d546..f07fe21 100644 --- a/src/ppm/ppm.h +++ b/src/ppm/ppm.h @@ -1,12 +1,11 @@ // Alexander Bass -// Created 4/16/24 +// Created 4/16/24 +// Modified 4/21/24 #pragma once +#include "../texture.h" #include "../types.h" +#include -#include - -namespace ppm { - - u8 *load_ppm(std::istream &input); -} // namespace ppm \ No newline at end of file +texture_t load_ppm(FILE *file_stream); +texture_t load_ppm_file(const char *file_name); \ No newline at end of file diff --git a/src/rgb.h b/src/rgb.h deleted file mode 100644 index 68bb9ae..0000000 --- a/src/rgb.h +++ /dev/null @@ -1,19 +0,0 @@ -// Alexander Bass -// Created 4/16/24 -#pragma once -#include "types.h" -struct rgb { - f64 r; - f64 g; - f64 b; - rgb(f64 _r, f64 _g, f64 _b) { - r = _r; - g = _g; - b = _b; - } - void mix(rgb rhs) { - r *= rhs.r; - g *= rhs.g; - b *= rhs.b; - } -}; \ No newline at end of file diff --git a/src/texture.c b/src/texture.c new file mode 100644 index 0000000..8b041bc --- /dev/null +++ b/src/texture.c @@ -0,0 +1,15 @@ +#include "texture.h" +// Alexander Bass +// Created 4/21/24 +// Modified 4/21/24 +#include + +texture_t texture(u32 width, u32 height) { + u8 *bytes = (u8 *)(malloc(sizeof(u8) * width * height * 3)); + texture_t tex = {bytes, width, height}; + return tex; +} + +void free_texture(texture_t *texture) { + free(texture->bytes); +} \ No newline at end of file diff --git a/src/texture.h b/src/texture.h new file mode 100644 index 0000000..cc2a4d9 --- /dev/null +++ b/src/texture.h @@ -0,0 +1,14 @@ +#pragma once +// Alexander Bass +// Created 4/21/24 +// Modified 4/21/24 +#include "types.h" + +typedef struct texture_t { + u8 *const bytes; + const u32 width; + const u32 height; +} texture_t; + +texture_t texture(u32 width, u32 height); +void free_texture(texture_t *); \ No newline at end of file diff --git a/src/types.h b/src/types.h index 5d697a1..2bb1aba 100644 --- a/src/types.h +++ b/src/types.h @@ -1,8 +1,8 @@ // Alexander Bass // Created 4/15/24 -// Modified 4/14/24 +// Modified 4/21/24 #pragma once -#include +#include typedef uint8_t u8; typedef uint16_t u16; @@ -10,11 +10,9 @@ typedef uint32_t u32; typedef uint64_t u64; typedef int8_t i8; -typedef std::int16_t i16; +typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; typedef float f32; -typedef double f64; - -typedef std::size_t usize; \ No newline at end of file +typedef double f64; \ No newline at end of file diff --git a/src/vec3.c b/src/vec3.c new file mode 100644 index 0000000..debaf24 --- /dev/null +++ b/src/vec3.c @@ -0,0 +1,55 @@ +// Alexander Bass +// Created 4/16/24 +// Modified 4/21/24 +#include "vec3.h" +#include "types.h" + +#include + +void rotate_i(vec3_t *point, f64 angle) { + f64 cos_a = cos(angle); + f64 sin_a = sin(angle); + f64 y_1 = point->j * cos_a - point->k * sin_a; + f64 z_1 = point->j * sin_a + point->k * cos_a; + point->j = y_1; + point->k = z_1; +} + +void rotate_j(vec3_t *point, f64 angle) { + f64 cos_a = cos(angle); + f64 sin_a = sin(angle); + + f64 x_1 = point->i * cos_a + point->k * sin_a; + f64 z_1 = point->k * cos_a - point->i * sin_a; + point->i = x_1; + point->k = z_1; +} + +void rotate_k(vec3_t *point, f64 angle) { + f64 cos_a = cos(angle); + f64 sin_a = sin(angle); + + f64 x_1 = point->i * cos_a - point->j * sin_a; + f64 y_1 = point->i * sin_a + point->j * cos_a; + point->i = x_1; + point->j = y_1; +} + +vec3_t vec3(f64 i, f64 j, f64 k) { + vec3_t vector = {i, j, k}; + return vector; +} + +vec3_t mul_vec(vec3_t lhs, vec3_t rhs) { + lhs.i *= rhs.i; + lhs.j *= rhs.j; + lhs.k *= rhs.k; + return lhs; +} + +vec3_t mul_scalar(vec3_t lhs, f64 rhs) { + lhs.i *= rhs; + lhs.j *= rhs; + lhs.k *= rhs; + return lhs; +} \ No newline at end of file diff --git a/src/vec3.h b/src/vec3.h new file mode 100644 index 0000000..900d847 --- /dev/null +++ b/src/vec3.h @@ -0,0 +1,18 @@ +// Alexander Bass +// Created 4/16/24 +// Modified 4/21/24 +#pragma once +#include "types.h" +typedef struct vec3_t { + f64 i; + f64 j; + f64 k; +} vec3_t; + +vec3_t vec3(f64 i, f64 j, f64 k); +vec3_t mul_vec(vec3_t lhs, vec3_t rhs); +vec3_t mul_scalar(vec3_t lhs, f64 rhs); + +void rotate_i(vec3_t *point, f64 angle); +void rotate_j(vec3_t *point, f64 angle); +void rotate_k(vec3_t *point, f64 angle); \ No newline at end of file diff --git a/src/vec4.c b/src/vec4.c new file mode 100644 index 0000000..36f6a82 --- /dev/null +++ b/src/vec4.c @@ -0,0 +1,8 @@ +// Alexander Bass +// Created 4/21/24 +// Modified 4/21/24 +#include "vec4.h" +vec4_t vec4(f64 i, f64 j, f64 k, f64 l) { + vec4_t vector = {i, j, k, l}; + return vector; +} \ No newline at end of file diff --git a/src/vec4.h b/src/vec4.h new file mode 100644 index 0000000..76a0006 --- /dev/null +++ b/src/vec4.h @@ -0,0 +1,13 @@ +// Alexander Bass +// Created 4/21/24 +// Modified 4/21/24 +#pragma once +#include "types.h" +typedef struct vec4_t { + f64 i; + f64 j; + f64 k; + f64 l; +} vec4_t; + +vec4_t vec4(f64 i, f64 j, f64 k, f64 l); \ No newline at end of file diff --git a/test.cpp b/test.cpp new file mode 100644 index 0000000..9a945d0 --- /dev/null +++ b/test.cpp @@ -0,0 +1,12 @@ +#include + +using namespace std; + +int test() { + return 0; +} + +int main() { + + cout << test(); +}