deltatime handling
This commit is contained in:
parent
a3a74765c9
commit
92aa9071fe
2
.clangd
Normal file
2
.clangd
Normal file
|
@ -0,0 +1,2 @@
|
|||
CompileFlags:
|
||||
Add: [-std=c17, -D_POSIX_C_SOURCE=199309L]
|
5
makefile
5
makefile
|
@ -6,10 +6,11 @@ SRC_DIRS := ./src ./includes
|
|||
RESOURCE_DIRS := ./resources
|
||||
|
||||
CC := gcc
|
||||
ld := g++
|
||||
ld := gcc
|
||||
|
||||
|
||||
BASEFLAGS = -g -Wall -Wextra -Wconversion -Wduplicated-branches -Wduplicated-cond -Wlogical-op -Wnull-dereference -Wdouble-promotion -Wshadow -Wformat=2
|
||||
LDFLAGS = -lm
|
||||
BASEFLAGS = -std=c17 -g -O3 -D_POSIX_C_SOURCE=199309L -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.
|
||||
|
|
13
src/donut.c
13
src/donut.c
|
@ -4,17 +4,16 @@
|
|||
|
||||
#include "donut.h"
|
||||
#include "point.h"
|
||||
#include "types.h"
|
||||
|
||||
#include "point_list.h"
|
||||
#include "texture.h"
|
||||
#include "types.h"
|
||||
#include "vec3.h"
|
||||
|
||||
#include <math.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);
|
||||
vec3_t color = {(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;
|
||||
};
|
||||
|
@ -27,16 +26,16 @@ vec3_t mix_transparency(vec3_t transparent, vec3_t solid) {
|
|||
}
|
||||
}
|
||||
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 vec3_t grass_color_scale = {0.4, 1.0, 0.4};
|
||||
const size_t image_size = 16;
|
||||
const size_t point_count = 32;
|
||||
const size_t point_count = 20;
|
||||
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);
|
||||
size_t index = 3 * ((size_t)(round(sx * (f64)(image_size))) + (size_t)(round(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);
|
||||
|
|
132
src/main.c
132
src/main.c
|
@ -1,6 +1,6 @@
|
|||
// Alexander Bass
|
||||
// Created 4/16/24
|
||||
// Modified 4/21/24
|
||||
// Modified 4/23/24
|
||||
|
||||
#include "donut.h"
|
||||
#include "point.h"
|
||||
|
@ -15,49 +15,74 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
const i32 WIDTH = 120;
|
||||
const i32 HEIGHT = 90;
|
||||
const i32 DEPTH = WIDTH;
|
||||
#define WIDTH 120
|
||||
#define HEIGHT 90
|
||||
#define DEPTH WIDTH
|
||||
|
||||
void draw(vec4_t *, const point_list_t *);
|
||||
void update(point_list_t *);
|
||||
#define SECONDS_TO_NANOSECONDS 1000000000
|
||||
#define FRAMERATE 30
|
||||
|
||||
#define LARGEST_PIXEL_CHAR_STRING "\033[38;2;255;255;255m██"
|
||||
#define LARGEST_PIXEL_CHAR_LEN sizeof(LARGEST_PIXEL_CHAR_STRING) - 1
|
||||
|
||||
void draw(vec4_t *, const point_list_t *, char *);
|
||||
void update(point_list_t *, u64);
|
||||
|
||||
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);
|
||||
vec4_t *pixel_buffer = malloc(WIDTH * HEIGHT * sizeof(vec4_t));
|
||||
for (u32 i = 0; i < (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;
|
||||
size_t char_buffer_capacity = (HEIGHT * WIDTH * LARGEST_PIXEL_CHAR_LEN + HEIGHT);
|
||||
char *screen_char_buffer = malloc(char_buffer_capacity * sizeof(char));
|
||||
|
||||
__SYSCALL_SLONG_TYPE frame_budget = SECONDS_TO_NANOSECONDS / FRAMERATE;
|
||||
struct timespec frame_start, frame_end, sleep_time;
|
||||
sleep_time.tv_sec = 0;
|
||||
sleep_time.tv_nsec = frame_budget;
|
||||
u64 counter = 0;
|
||||
|
||||
while (true) {
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &frame_start);
|
||||
|
||||
// Move cursor to top left
|
||||
printf("\033[0;0H");
|
||||
// Draw points
|
||||
draw(pixel_buffer, &points);
|
||||
draw(pixel_buffer, &points, screen_char_buffer);
|
||||
// Rotate points
|
||||
update(&points);
|
||||
// Wait
|
||||
nanosleep(&tim, NULL);
|
||||
// Repeat
|
||||
update(&points, counter);
|
||||
|
||||
// Compute time until next frame
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &frame_end);
|
||||
__SYSCALL_SLONG_TYPE diff_ns = frame_end.tv_nsec - frame_start.tv_nsec;
|
||||
__SYSCALL_SLONG_TYPE diff_s = frame_end.tv_sec - frame_start.tv_sec;
|
||||
diff_ns += SECONDS_TO_NANOSECONDS * diff_s;
|
||||
|
||||
__SYSCALL_SLONG_TYPE excess = diff_ns > frame_budget ? 0 : frame_budget - diff_ns;
|
||||
// if (excess == 0) {
|
||||
// printf("\033[38;2;255;255;255mCan't keep up; Exiting. Ran for %lu frames\n", counter);
|
||||
// exit(0);
|
||||
// }
|
||||
|
||||
sleep_time.tv_nsec = excess;
|
||||
counter += 1;
|
||||
// Wait until next frame
|
||||
nanosleep(&sleep_time, NULL);
|
||||
}
|
||||
|
||||
free_point_list(&points);
|
||||
|
@ -65,20 +90,32 @@ int main() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
i32 w_x_to_screen(f64 w_x) {
|
||||
return (i32)(round(w_x)) + WIDTH / 2;
|
||||
inline size_t w_x_to_screen(f64 w_x) {
|
||||
return (size_t)(round(w_x)) + WIDTH / 2;
|
||||
}
|
||||
|
||||
i32 w_y_to_screen(f64 w_y) {
|
||||
return (i32)(round(w_y)) + HEIGHT / 2;
|
||||
inline size_t w_y_to_screen(f64 w_y) {
|
||||
return (size_t)(round(w_y)) + HEIGHT / 2;
|
||||
}
|
||||
|
||||
f64 w_z_to_screen(f64 w_z) {
|
||||
inline 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++) {
|
||||
inline void push_string(char *to, const char *from, size_t *to_length) {
|
||||
// Assumes `to` has enough room for the string in `from`
|
||||
size_t i = 0;
|
||||
while (from[i] != '\0') {
|
||||
char c = from[i];
|
||||
to[i + *to_length] = c;
|
||||
i++;
|
||||
}
|
||||
(*to_length) += i;
|
||||
}
|
||||
|
||||
void draw(vec4_t *pixel_buffer, const point_list_t *points, char *screen_char_buffer) {
|
||||
// Reset Depth buffer
|
||||
for (size_t i = 0; i < WIDTH * HEIGHT; i++) {
|
||||
pixel_buffer[i].l = 0.0;
|
||||
};
|
||||
|
||||
|
@ -93,12 +130,12 @@ void draw(vec4_t *pixel_buffer, const point_list_t *points) {
|
|||
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);
|
||||
size_t s_x = w_x_to_screen(p_x);
|
||||
size_t 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);
|
||||
if (s_x < WIDTH && s_y < HEIGHT) {
|
||||
size_t index = (s_x + s_y * WIDTH);
|
||||
vec4_t existing = pixel_buffer[index];
|
||||
if (existing.l < s_z) {
|
||||
pixel_buffer[index].i = color.i;
|
||||
|
@ -109,33 +146,44 @@ void draw(vec4_t *pixel_buffer, const point_list_t *points) {
|
|||
};
|
||||
}
|
||||
|
||||
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);
|
||||
size_t char_buffer_length = 0;
|
||||
|
||||
for (size_t y = 0; y < HEIGHT; y++) {
|
||||
for (size_t x = 0; x < WIDTH; x++) {
|
||||
size_t index = x + y * WIDTH;
|
||||
vec4_t pixel = pixel_buffer[index];
|
||||
f64 depth = pixel.l;
|
||||
if (depth <= 0.0) {
|
||||
printf(" ");
|
||||
screen_char_buffer[char_buffer_length] = ' ';
|
||||
screen_char_buffer[char_buffer_length + 1] = ' ';
|
||||
char_buffer_length += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(depth >= 0.0);
|
||||
assert(depth <= 1.0);
|
||||
|
||||
char color_buf[64] = "";
|
||||
|
||||
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);
|
||||
|
||||
snprintf(color_buf, 32, "\033[38;2;%hhu;%hhu;%hhum██", red, green, blue);
|
||||
push_string(screen_char_buffer, color_buf, &char_buffer_length);
|
||||
}
|
||||
printf("\n");
|
||||
screen_char_buffer[char_buffer_length] = '\n';
|
||||
char_buffer_length++;
|
||||
}
|
||||
|
||||
fwrite(screen_char_buffer, 1, char_buffer_length, stdout);
|
||||
}
|
||||
|
||||
void update(point_list_t *points) {
|
||||
void update(point_list_t *points, u64 frame_count) {
|
||||
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);
|
||||
// rotate_i(pos, sin(frame_count / 32.0) / 32.0);
|
||||
rotate_j(pos, 0.04);
|
||||
rotate_k(pos, -0.037);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,10 @@ texture_t load_ppm(FILE *file) {
|
|||
u32 width, height;
|
||||
u32 color;
|
||||
|
||||
fscanf(file, "%d %d", &width, &height);
|
||||
fscanf(file, "%d", &color);
|
||||
int res1 = fscanf(file, "%d %d", &width, &height);
|
||||
assert(res1 > 0);
|
||||
int res2 = fscanf(file, "%d", &color);
|
||||
assert(res2 > 0);
|
||||
|
||||
assert(width == 16 && height == 16);
|
||||
assert(color == 255);
|
||||
|
@ -25,7 +27,8 @@ texture_t load_ppm(FILE *file) {
|
|||
|
||||
for (size_t i = 0; i < width * height * 3; i++) {
|
||||
u8 byte;
|
||||
fscanf(file, "%hhd", &byte);
|
||||
int res3 = fscanf(file, "%hhd", &byte);
|
||||
assert(res3 > 0);
|
||||
tex.bytes[i] = byte;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue