summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--pineapple.c56
2 files changed, 36 insertions, 22 deletions
diff --git a/Makefile b/Makefile
index 78828dc..d922d90 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
.POSIX:
.SUFFIXES:
-CFLAGS = -O2 -Wall -Wextra -pedantic
+CFLAGS = -O2 -Wall -Wextra -pedantic -D_POSIX_C_SOURCE=199309L -D_XOPEN_SOURCE
LDFLAGS = -static
LDLIBS = -lm
diff --git a/pineapple.c b/pineapple.c
index 772e7b6..5e97901 100644
--- a/pineapple.c
+++ b/pineapple.c
@@ -9,8 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#define PI 3.14159265358979323846
+#include <time.h>
#define die(code, msg) do { fprintf(stderr, "pineapple: %s\n", msg); exit(code); } while (0)
#define diesys(code, msg) do { fprintf(stderr, "pineapple: %s: %s\n", msg, strerror(errno)); exit(code); } while (0)
@@ -20,6 +19,8 @@
#define ASCII_CHARS "$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'. "
+static int verbosity = 0;
+
typedef struct { float x, y, z; } vec3;
struct triangle {
@@ -77,7 +78,7 @@ magnitude(vec3 v)
}
static inline vec3
-vnorm(vec3 v)
+norm(vec3 v)
{
float mag = magnitude(v);
return (vec3){ v.x / mag, v.y / mag, v.z / mag };
@@ -90,7 +91,7 @@ ray_triangle_intersect(vec3 P, vec3 d, struct triangle tri)
vec3 edge2 = vsub(tri.c, tri.a);
vec3 ray_cross_e2 = cross(d, edge2);
float det = dot(edge1, ray_cross_e2);
- if (det > -FLT_EPSILON && det < FLT_EPSILON) return NAN;
+ if (-FLT_EPSILON < det && det < FLT_EPSILON) return NAN;
float inv_det = 1.0 / det;
vec3 s = vsub(P, tri.a);
float u = inv_det * dot(s, ray_cross_e2);
@@ -108,36 +109,50 @@ 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) {
+ struct timespec start, now;
+ if (verbosity >= 1) clock_gettime(CLOCK_MONOTONIC, &start);
+
+ light = norm(light);
+ for (size_t w = 0; w < width; ++w) {
+ if (verbosity >= 1) {
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ int elapsed = now.tv_sec - start.tv_sec;
+ int total = elapsed * width / (w+1);
+ fprintf(stderr, "%ld/%d %02d:%02d/%02d:%02d\r", w, width, elapsed / 60, elapsed % 60, total / 60, total % 60);
+ }
+ for (size_t h = 0; h < height; ++h) {
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);
+ dir = norm(dir);
float shortest = INFINITY;
- vec3 shortest_norm = {0};
+ struct triangle shortest_tri = {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)) {
+ if (d != NAN && d < shortest) {
shortest = d;
- shortest_norm = triangles[i].n;
+ shortest_tri = triangles[i];
}
}
- pixels[w*width + h] = 0.0;
+ pixels[w*height + 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;
+ float light_angle = acosf(dot(shortest_tri.n, light));
+ pixels[w*height + h] = light_angle / M_PI;
}
}
}
+ if (verbosity >= 1) {
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ int elapsed = now.tv_sec - start.tv_sec;
+ fprintf(stderr, "Rendered in %02d:%02d\n", elapsed / 60, elapsed % 60);
+ }
}
int
main(int argc, char *argv[])
{
- int verbosity = 0;
uint32_t width = 80;
uint32_t height = 40;
enum { ASCII, FARBFELD } mode = ASCII;
@@ -169,17 +184,17 @@ main(int argc, char *argv[])
for (size_t i = 0; i < len; ++i) {
if (fread(&raw, sizeof(raw), 1, stdin) < 1)
diesys(111, "fatal: unable to read STL facets");
- triangles[i] = (struct triangle){ .n = raw.n, .a = raw.a, .b = raw.b, .c = raw.c };
+ triangles[i] = (struct triangle){ .n = norm(raw.n), .a = raw.a, .b = raw.b, .c = raw.c };
}
if (verbosity >= 1) fprintf(stderr, "finished reading STL: %d facets\n", len);
struct camera cam = {
.pos = { -70.0, 60.0, 60.0 },
- .phi = PI * 0.8,
- .theta = PI * 0.5,
- .fov = 80.0 * PI / 180.0
+ .phi = M_PI * 0.8,
+ .theta = M_PI * 0.5,
+ .fov = 80.0 * M_PI / 180.0
};
- vec3 light = { 0.0, 0.0, -1.0 };
+ vec3 light = { 0.0, 0.5, -1.0 };
if (mode == FARBFELD) {
uint32_t wbe = htobe32(width);
@@ -195,7 +210,7 @@ main(int argc, char *argv[])
for (int h = height - 1; h >= 0; --h) {
for (uint32_t w = 0; w < width; ++w) {
- float brightness = pixels[w*width + h];
+ float brightness = pixels[w*height + h];
if (mode == ASCII) {
printf("%c", ASCII_CHARS[strlen(ASCII_CHARS) - 1 - (int)(brightness * strlen(ASCII_CHARS))]);
} else if (mode == FARBFELD) {
@@ -206,7 +221,6 @@ main(int argc, char *argv[])
}
if (mode == ASCII) printf("\n");
}
- free(pixels);
return 0;
} \ No newline at end of file