This commit is contained in:
Alexander Bass 2024-04-22 00:08:05 -04:00
parent 9809dfccd0
commit a3a74765c9
24 changed files with 507 additions and 419 deletions

View file

@ -1,2 +0,0 @@
CompileFlags:
Add: [-std=c++20]

View file

@ -5,17 +5,15 @@ BUILD_DIR := ./build
SRC_DIRS := ./src ./includes SRC_DIRS := ./src ./includes
RESOURCE_DIRS := ./resources RESOURCE_DIRS := ./resources
CXX := g++
CC := gcc CC := gcc
ld := g++ ld := g++
BASEFLAGS = -g -Wall -Wextra -Wconversion -Wduplicated-branches -Wduplicated-cond -Wlogical-op -Wnull-dereference -Wuseless-cast -Wdouble-promotion -Wshadow -Wformat=2 BASEFLAGS = -g -Wall -Wextra -Wconversion -Wduplicated-branches -Wduplicated-cond -Wlogical-op -Wnull-dereference -Wdouble-promotion -Wshadow -Wformat=2
CXXFLAGS = -std=c++20 $(BASEFLAGS) -Wuseless-cast
CFLAGS = $(BASEFLAGS) -Wjump-misses-init CFLAGS = $(BASEFLAGS) -Wjump-misses-init
# Find all the C and C++ files we want to compile # 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. # 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 # 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 # 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 # Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS)) 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. # The final build step.
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) $(BUILD_DIR)/$(TARGET_EXEC): $(OBJS)
@ -44,10 +39,6 @@ $(BUILD_DIR)/%.c.o: %.c
mkdir -p $(dir $@) mkdir -p $(dir $@)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ $(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: clean:
rm -r $(BUILD_DIR) 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)

93
src/donut.c Normal file
View file

@ -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;
}

View file

@ -1,94 +0,0 @@
// Alexander Bass
// Created 4/16/24
#include "donut.h"
#include "point.h"
#include "types.h"
#include <vector>
#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<Point> generate_cube(u8 *bottom_texture, u8 *top_texture, u8 *side_texture, i32 face_x, i32 face_y) {
std::vector<Point> 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<Point> generate_donut(u8 *bottom_texture, u8 *top_texture, u8 *side_texture, f64 offset) {
std::vector<Point> points = {};
for (i32 x = -1; x <= 1; x++) {
for (i32 y = -1; y <= 1; y++) {
if (x == y && x == 0) {
continue;
}
std::vector<Point> 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;
}

View file

@ -1,8 +1,9 @@
// Alexander Bass // Alexander Bass
// Created 4/16/24 // Created 4/16/24
// Modified 4/21/24
#pragma once #pragma once
#include "point.h" #include "point_list.h"
#include <vector> #include "texture.h"
std::vector<Point> 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);

141
src/main.c Normal file
View file

@ -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 <assert.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
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);
}
}

View file

@ -1,132 +0,0 @@
// Alexander Bass
// Created 4/16/24
#include "donut.h"
#include "point.h"
#include "ppm/ppm.h"
#include "types.h"
#include <cassert>
#include <chrono>
#include <cmath>
#include <format>
#include <fstream>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
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<Point> &points);
void update(vector<Point> &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<Point> points = {};
points.push_back(*Point(0, 0, 0).set_rgb(1.0, 0, 0));
std::vector<Point> 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<i32>(std::round(w_x + static_cast<f64>(WIDTH) / 2.0));
}
i32 w_y_to_screen(f64 w_y) {
return static_cast<i32>(std::round(w_y + static_cast<f64>(HEIGHT) / 2.0));
}
f64 w_z_to_screen(f64 w_z) {
return (w_z + static_cast<f64>(DEPTH) / 2.0) / static_cast<f64>(DEPTH);
}
void draw(size_t *grid, vector<Point> &points) {
for (u32 i = 0; i < static_cast<u32>(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<size_t>(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<size_t>(WIDTH); y++) {
for (size_t x = 0; x < static_cast<size_t>(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<u8>(round(red * 255.0));
u8 g8 = static_cast<u8>(round(green * 255.0));
u8 b8 = static_cast<u8>(round(blue * 255.0));
line += format("\033[38;2;{};{};{}m██", r8, g8, b8);
}
line += '\n';
}
std::cout << line;
}
void update(vector<Point> &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);
}
}

10
src/point.c Normal file
View file

@ -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;
}

View file

@ -1,35 +0,0 @@
// Alexander Bass
// Created 4/16/24
#include "point.h"
#include "types.h"
#include <cmath>
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;
}

View file

@ -1,81 +1,12 @@
// Alexander Bass // Alexander Bass
// Created 4/16/24 // Created 4/16/24
// Modified 4/21/24
#pragma once #pragma once
#include "rgb.h"
#include "types.h" #include "types.h"
class Point { #include "vec3.h"
private: typedef struct point_t {
f64 x; vec3_t pos;
f64 y; vec3_t color;
f64 z; } point_t;
f64 r;
f64 g;
f64 b;
public: point_t point(vec3_t, vec3_t);
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;
};
};

46
src/point_list.c Normal file
View file

@ -0,0 +1,46 @@
// Alexander Bass
// Created 4/21/24
// Modified 4/21/24
#include "point_list.h"
#include "point.h"
#include <stddef.h>
#include <stdlib.h>
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)++;
}
}

18
src/point_list.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
// Alexander Bass
// Created 4/21/24
// Modified 4/21/24
#include "point.h"
#include <stddef.h>
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);

40
src/ppm/ppm.c Normal file
View file

@ -0,0 +1,40 @@
// Alexander Bass
// Created 4/16/24
// Modified 4/21/24
#include "ppm.h"
#include "../texture.h"
#include "../types.h"
#include <assert.h>
#include <stdio.h>
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;
}

View file

@ -1,29 +0,0 @@
// Alexander Bass
// Created 4/16/24
#include "ppm.h"
using std::string;
#include <cassert>
#include <iostream>
#include <string>
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;
}

View file

@ -1,12 +1,11 @@
// Alexander Bass // Alexander Bass
// Created 4/16/24 // Created 4/16/24
// Modified 4/21/24
#pragma once #pragma once
#include "../texture.h"
#include "../types.h" #include "../types.h"
#include <stdio.h>
#include <istream> texture_t load_ppm(FILE *file_stream);
texture_t load_ppm_file(const char *file_name);
namespace ppm {
u8 *load_ppm(std::istream &input);
} // namespace ppm

View file

@ -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;
}
};

15
src/texture.c Normal file
View file

@ -0,0 +1,15 @@
#include "texture.h"
// Alexander Bass
// Created 4/21/24
// Modified 4/21/24
#include <stdlib.h>
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);
}

14
src/texture.h Normal file
View file

@ -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 *);

View file

@ -1,8 +1,8 @@
// Alexander Bass // Alexander Bass
// Created 4/15/24 // Created 4/15/24
// Modified 4/14/24 // Modified 4/21/24
#pragma once #pragma once
#include <cstdint> #include <stdint.h>
typedef uint8_t u8; typedef uint8_t u8;
typedef uint16_t u16; typedef uint16_t u16;
@ -10,11 +10,9 @@ typedef uint32_t u32;
typedef uint64_t u64; typedef uint64_t u64;
typedef int8_t i8; typedef int8_t i8;
typedef std::int16_t i16; typedef int16_t i16;
typedef int32_t i32; typedef int32_t i32;
typedef int64_t i64; typedef int64_t i64;
typedef float f32; typedef float f32;
typedef double f64; typedef double f64;
typedef std::size_t usize;

55
src/vec3.c Normal file
View file

@ -0,0 +1,55 @@
// Alexander Bass
// Created 4/16/24
// Modified 4/21/24
#include "vec3.h"
#include "types.h"
#include <math.h>
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;
}

18
src/vec3.h Normal file
View file

@ -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);

8
src/vec4.c Normal file
View file

@ -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;
}

13
src/vec4.h Normal file
View file

@ -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);

12
test.cpp Normal file
View file

@ -0,0 +1,12 @@
#include <iostream>
using namespace std;
int test() {
return 0;
}
int main() {
cout << test();
}