From 3fb09ad03aa464d21b0f75ba1e4bc1bdcedb7d5f Mon Sep 17 00:00:00 2001 From: Sam Nystrom Date: Wed, 14 Feb 2024 15:38:50 +0000 Subject: Move rendering code into function --- pineapple.c | 75 ++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/pineapple.c b/pineapple.c index 043904f..772e7b6 100644 --- a/pineapple.c +++ b/pineapple.c @@ -33,6 +33,13 @@ struct __attribute__((__packed__)) triangle_raw { uint16_t _attr_count; /* unused */ }; +struct camera { + vec3 pos; + float theta; + float phi; + float fov; +}; + static inline vec3 vadd(vec3 a, vec3 b) { @@ -96,6 +103,37 @@ ray_triangle_intersect(vec3 P, vec3 d, struct triangle tri) return NAN; } +static void +render_frame(struct camera cam, vec3 light, + const struct triangle *triangles, uint32_t len, + float *pixels, uint32_t width, uint32_t height) +{ + for (int h = height - 1; h >= 0; --h) { + for (uint32_t w = 0; w < width; ++w) { + float theta = cam.theta - cam.fov/2.0 + cam.fov/height*h; + float phi = cam.phi - cam.fov/2.0 + cam.fov/width*w; + vec3 dir = { sinf(theta) * cosf(phi), sinf(theta) * sinf(phi), cosf(theta) }; + dir = vnorm(dir); + + float shortest = INFINITY; + vec3 shortest_norm = {0}; + for (size_t i = 0; i < len; ++i) { + float d = ray_triangle_intersect(cam.pos, dir, triangles[i]); + if (d != NAN && fabs(d) < fabs(shortest)) { + shortest = d; + shortest_norm = triangles[i].n; + } + } + + pixels[w*width + h] = 0.0; + if (shortest != INFINITY) { + float light_angle = acosf(dot(shortest_norm, light) / magnitude(shortest_norm) / magnitude(light)); + pixels[w*width + h] = light_angle / PI; + } + } + } +} + int main(int argc, char *argv[]) { @@ -135,10 +173,12 @@ main(int argc, char *argv[]) } if (verbosity >= 1) fprintf(stderr, "finished reading STL: %d facets\n", len); - vec3 camera_pos = { -70.0, 60.0, 60.0 }; - float camera_phi = PI * 0.8; - float camera_theta = PI * 0.5; - float fov = 80.0 * PI / 180.0; + struct camera cam = { + .pos = { -70.0, 60.0, 60.0 }, + .phi = PI * 0.8, + .theta = PI * 0.5, + .fov = 80.0 * PI / 180.0 + }; vec3 light = { 0.0, 0.0, -1.0 }; if (mode == FARBFELD) { @@ -149,29 +189,13 @@ main(int argc, char *argv[]) fwrite(&hbe, 1, 4, stdout); } + float *pixels = calloc(sizeof(float), width * height); + if (!pixels) diesys(111, "fatal: unable to allocate enough memory for pixel buffer"); + render_frame(cam, light, triangles, len, pixels, width, height); + for (int h = height - 1; h >= 0; --h) { - if (verbosity >= 1) fprintf(stderr, "row %d/%d\r", height - h - 1, height); for (uint32_t w = 0; w < width; ++w) { - float theta = camera_theta - fov/2.0 + fov/height*h; - float phi = camera_phi - fov/2.0 + fov/width*w; - vec3 dir = { sinf(theta) * cosf(phi), sinf(theta) * sinf(phi), cosf(theta) }; - dir = vnorm(dir); - - float shortest = INFINITY; - vec3 shortest_norm = {0}; - for (size_t i = 0; i < len; ++i) { - float d = ray_triangle_intersect(camera_pos, dir, triangles[i]); - if (d != NAN && fabs(d) < fabs(shortest)) { - shortest = d; - shortest_norm = triangles[i].n; - } - } - - float brightness = 0.0; - if (shortest != INFINITY) { - float light_angle = acosf(dot(shortest_norm, light) / magnitude(shortest_norm) / magnitude(light)); - brightness = light_angle / PI; - } + float brightness = pixels[w*width + h]; if (mode == ASCII) { printf("%c", ASCII_CHARS[strlen(ASCII_CHARS) - 1 - (int)(brightness * strlen(ASCII_CHARS))]); } else if (mode == FARBFELD) { @@ -182,6 +206,7 @@ main(int argc, char *argv[]) } if (mode == ASCII) printf("\n"); } + free(pixels); return 0; } \ No newline at end of file -- cgit v1.2.3