Init ASCII Blocky Donut
This commit is contained in:
commit
9809dfccd0
6
.clang-format
Normal file
6
.clang-format
Normal file
|
@ -0,0 +1,6 @@
|
|||
ColumnLimit: 140
|
||||
IndentWidth: 4
|
||||
NamespaceIndentation: All
|
||||
FixNamespaceComments: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
build
|
61
makefile
Normal file
61
makefile
Normal file
|
@ -0,0 +1,61 @@
|
|||
# Thanks to Job Vranish (https://spin.atomicobject.com/2016/08/26/makefile-c-projects/)
|
||||
TARGET_EXEC := final_program
|
||||
|
||||
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
|
||||
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')
|
||||
|
||||
# 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
|
||||
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
|
||||
|
||||
# String substitution (suffix version without %).
|
||||
# As an example, ./build/hello.cpp.o turns into ./build/hello.cpp.d
|
||||
DEPS := $(OBJS:.o=.d)
|
||||
|
||||
# Every folder in ./src will need to be passed to GCC so that it can find header files
|
||||
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)
|
||||
cp -r resources/. build
|
||||
$(ld) $(OBJS) -o $@ $(LDFLAGS)
|
||||
|
||||
# Build step for C source
|
||||
$(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 $@
|
||||
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
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)
|
19
resources/dirt.ppm
Normal file
19
resources/dirt.ppm
Normal file
|
@ -0,0 +1,19 @@
|
|||
P3
|
||||
16 16
|
||||
255
|
||||
185 133 92 150 108 74 150 108 74 121 85 58 121 85 58 185 133 92 150 108 74 150 108 74 121 85 58 121 85 58 89 61 41 121 85 58 121 85 58 185 133 92 121 85 58 185 133 92
|
||||
121 85 58 150 108 74 89 61 41 121 85 58 121 85 58 150 108 74 135 135 135 89 61 41 121 85 58 185 133 92 150 108 74 121 85 58 185 133 92 150 108 74 89 61 41 89 61 41
|
||||
185 133 92 121 85 58 121 85 58 89 61 41 185 133 92 121 85 58 121 85 58 121 85 58 185 133 92 121 85 58 121 85 58 121 85 58 89 61 41 89 61 41 185 133 92 121 85 58
|
||||
150 108 74 108 108 108 185 133 92 121 85 58 150 108 74 89 61 41 121 85 58 185 133 92 150 108 74 150 108 74 121 85 58 150 108 74 121 85 58 185 133 92 150 108 74 121 85 58
|
||||
150 108 74 121 85 58 150 108 74 185 133 92 89 61 41 150 108 74 121 85 58 121 85 58 150 108 74 89 61 41 121 85 58 108 108 108 121 85 58 150 108 74 89 61 41 121 85 58
|
||||
121 85 58 89 61 41 150 108 74 150 108 74 121 85 58 150 108 74 89 61 41 89 61 41 89 61 41 121 85 58 121 85 58 89 61 41 121 85 58 121 85 58 121 85 58 185 133 92
|
||||
185 133 92 121 85 58 121 85 58 121 85 58 135 135 135 121 85 58 121 85 58 185 133 92 185 133 92 121 85 58 185 133 92 185 133 92 121 85 58 150 108 74 121 85 58 150 108 74
|
||||
121 85 58 121 85 58 185 133 92 185 133 92 150 108 74 150 108 74 121 85 58 121 85 58 150 108 74 89 61 41 150 108 74 150 108 74 121 85 58 121 85 58 150 108 74 150 108 74
|
||||
150 108 74 121 85 58 121 85 58 150 108 74 121 85 58 150 108 74 121 85 58 89 61 41 121 85 58 150 108 74 150 108 74 121 85 58 121 85 58 121 85 58 89 61 41 121 85 58
|
||||
121 85 58 150 108 74 89 61 41 121 85 58 121 85 58 89 61 41 89 61 41 121 85 58 121 85 58 121 85 58 121 85 58 121 85 58 185 133 92 185 133 92 121 85 58 150 108 74
|
||||
121 85 58 150 108 74 121 85 58 185 133 92 185 133 92 121 85 58 185 133 92 150 108 74 89 61 41 185 133 92 185 133 92 89 61 41 150 108 74 150 108 74 135 135 135 121 85 58
|
||||
150 108 74 121 85 58 121 85 58 150 108 74 150 108 74 185 133 92 121 85 58 150 108 74 108 108 108 150 108 74 150 108 74 121 85 58 89 61 41 150 108 74 121 85 58 89 61 41
|
||||
121 85 58 89 61 41 150 108 74 121 85 58 150 108 74 150 108 74 185 133 92 121 85 58 121 85 58 121 85 58 121 85 58 121 85 58 121 85 58 121 85 58 185 133 92 185 133 92
|
||||
121 85 58 150 108 74 121 85 58 121 85 58 116 88 68 121 85 58 150 108 74 150 108 74 121 85 58 89 61 41 185 133 92 89 61 41 121 85 58 185 133 92 150 108 74 150 108 74
|
||||
150 108 74 121 85 58 89 61 41 185 133 92 121 85 58 89 61 41 121 85 58 89 61 41 185 133 92 185 133 92 121 85 58 150 108 74 121 85 58 121 85 58 150 108 74 150 108 74
|
||||
150 108 74 121 85 58 185 133 92 150 108 74 150 108 74 121 85 58 135 135 135 121 85 58 150 108 74 150 108 74 121 85 58 121 85 58 150 108 74 150 108 74 121 85 58 89 61 41
|
19
resources/grass_side.ppm
Normal file
19
resources/grass_side.ppm
Normal file
|
@ -0,0 +1,19 @@
|
|||
P3
|
||||
16 16
|
||||
255
|
||||
169 169 169 144 144 144 150 150 150 140 140 140 169 169 169 144 144 144 169 169 169 150 150 150 150 150 150 159 159 159 169 169 169 159 159 159 178 178 178 129 129 129 159 159 159 150 150 150
|
||||
169 169 169 140 140 140 169 169 169 144 144 144 178 178 178 0 0 0 169 169 169 130 130 130 178 178 178 150 150 150 169 169 169 147 147 147 169 169 169 140 140 140 169 169 169 139 139 139
|
||||
150 150 150 0 0 0 178 178 178 132 132 132 169 169 169 0 0 0 144 144 144 0 0 0 169 169 169 159 159 159 150 150 150 173 173 173 0 0 0 119 119 119 150 150 150 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 145 145 145 0 0 0 0 0 0 0 0 0 127 127 127 0 0 0 141 141 141 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
19
resources/grass_top.ppm
Normal file
19
resources/grass_top.ppm
Normal file
|
@ -0,0 +1,19 @@
|
|||
P3
|
||||
16 16
|
||||
255
|
||||
148 148 148 195 195 195 147 147 147 134 134 134 134 134 134 143 143 143 127 127 127 140 140 140 158 158 158 150 150 150 138 138 138 135 135 135 137 137 137 167 167 167 112 112 112 141 141 141
|
||||
149 149 149 140 140 140 160 160 160 151 151 151 153 153 153 128 128 128 153 153 153 130 130 130 127 127 127 169 169 169 166 166 166 147 147 147 195 195 195 140 140 140 135 135 135 139 139 139
|
||||
163 163 163 141 141 141 125 125 125 132 132 132 137 137 137 136 136 136 144 144 144 144 144 144 148 148 148 159 159 159 168 168 168 173 173 173 135 135 135 119 119 119 128 128 128 182 182 182
|
||||
118 118 118 133 133 133 138 138 138 151 151 151 145 145 145 153 153 153 125 125 125 146 146 146 127 127 127 131 131 131 141 141 141 151 151 151 143 143 143 139 139 139 167 167 167 125 125 125
|
||||
162 162 162 131 131 131 173 173 173 131 131 131 172 172 172 174 174 174 136 136 136 172 172 172 186 186 186 117 117 117 128 128 128 167 167 167 171 171 171 126 126 126 136 136 136 141 141 141
|
||||
153 153 153 152 152 152 120 120 120 166 166 166 129 129 129 150 150 150 149 149 149 155 155 155 135 135 135 149 149 149 136 136 136 131 131 131 120 120 120 136 136 136 142 142 142 148 148 148
|
||||
126 126 126 156 156 156 165 165 165 144 144 144 146 146 146 131 131 131 138 138 138 127 127 127 132 132 132 135 135 135 181 181 181 172 172 172 145 145 145 167 167 167 151 151 151 143 143 143
|
||||
143 143 143 135 135 135 157 157 157 139 139 139 144 144 144 124 124 124 164 164 164 132 132 132 151 151 151 173 173 173 135 135 135 129 129 129 143 143 143 160 160 160 127 127 127 169 169 169
|
||||
167 167 167 155 155 155 182 182 182 170 170 170 172 172 172 129 129 129 173 173 173 156 156 156 179 179 179 170 170 170 130 130 130 146 146 146 133 133 133 147 147 147 158 158 158 126 126 126
|
||||
151 151 151 130 130 130 183 183 183 141 141 141 140 140 140 152 152 152 170 170 170 128 128 128 135 135 135 145 145 145 146 146 146 169 169 169 142 142 142 179 179 179 143 143 143 129 129 129
|
||||
155 155 155 158 158 158 151 151 151 165 165 165 130 130 130 182 182 182 142 142 142 147 147 147 192 192 192 121 121 121 167 167 167 131 131 131 143 143 143 136 136 136 151 151 151 143 143 143
|
||||
132 132 132 173 173 173 134 134 134 163 163 163 151 151 151 132 132 132 146 146 146 137 137 137 151 151 151 146 146 146 140 140 140 123 123 123 179 179 179 127 127 127 125 125 125 138 138 138
|
||||
186 186 186 151 151 151 129 129 129 138 138 138 153 153 153 145 145 145 133 133 133 122 122 122 138 138 138 145 145 145 138 138 138 125 125 125 159 159 159 165 165 165 121 121 121 151 151 151
|
||||
129 129 129 168 168 168 118 118 118 146 146 146 125 125 125 153 153 153 129 129 129 195 195 195 161 161 161 147 147 147 168 168 168 155 155 155 160 160 160 136 136 136 168 168 168 174 174 174
|
||||
163 163 163 161 161 161 192 192 192 123 123 123 179 179 179 171 171 171 148 148 148 147 147 147 126 126 126 149 149 149 149 149 149 135 135 135 169 169 169 157 157 157 139 139 139 121 121 121
|
||||
133 133 133 150 150 150 136 136 136 137 137 137 164 164 164 152 152 152 148 148 148 147 147 147 142 142 142 191 191 191 124 124 124 169 169 169 132 132 132 144 144 144 136 136 136 158 158 158
|
94
src/donut.cpp
Normal file
94
src/donut.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
// 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;
|
||||
}
|
8
src/donut.h
Normal file
8
src/donut.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Alexander Bass
|
||||
// Created 4/16/24
|
||||
#pragma once
|
||||
|
||||
#include "point.h"
|
||||
#include <vector>
|
||||
|
||||
std::vector<Point> generate_donut(u8 *bottom_texture, u8 *top_texture, u8 *side_texture, f64);
|
132
src/main.cpp
Normal file
132
src/main.cpp
Normal file
|
@ -0,0 +1,132 @@
|
|||
// 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);
|
||||
}
|
||||
}
|
35
src/point.cpp
Normal file
35
src/point.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
// 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;
|
||||
}
|
81
src/point.h
Normal file
81
src/point.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
// Alexander Bass
|
||||
// Created 4/16/24
|
||||
#pragma once
|
||||
#include "rgb.h"
|
||||
#include "types.h"
|
||||
class Point {
|
||||
private:
|
||||
f64 x;
|
||||
f64 y;
|
||||
f64 z;
|
||||
f64 r;
|
||||
f64 g;
|
||||
f64 b;
|
||||
|
||||
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;
|
||||
};
|
||||
};
|
29
src/ppm/ppm.cpp
Normal file
29
src/ppm/ppm.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
// 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;
|
||||
}
|
12
src/ppm/ppm.h
Normal file
12
src/ppm/ppm.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Alexander Bass
|
||||
// Created 4/16/24
|
||||
#pragma once
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
#include <istream>
|
||||
|
||||
namespace ppm {
|
||||
|
||||
u8 *load_ppm(std::istream &input);
|
||||
} // namespace ppm
|
19
src/rgb.h
Normal file
19
src/rgb.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
// 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;
|
||||
}
|
||||
};
|
20
src/types.h
Normal file
20
src/types.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Alexander Bass
|
||||
// Created 4/15/24
|
||||
// Modified 4/14/24
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef std::int16_t i16;
|
||||
typedef int32_t i32;
|
||||
typedef int64_t i64;
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
typedef std::size_t usize;
|
Loading…
Reference in a new issue