summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Nystrom <sam@samnystrom.dev>2024-02-14 15:38:50 +0000
committerSam Nystrom <sam@samnystrom.dev>2024-02-14 16:49:26 -0500
commit3fb09ad03aa464d21b0f75ba1e4bc1bdcedb7d5f (patch)
tree5ad4380ce336372d91632d8e7aa1ae883bfb82f9
parent51f632349a9cba58b35c0d6c771826983dcfb922 (diff)
Move rendering code into function
-rw-r--r--pineapple.c75
1 files 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