From 336b5505f09dcbc6115d125e7ffdb41da13cb32e Mon Sep 17 00:00:00 2001 From: Sam Nystrom Date: Wed, 14 Feb 2024 14:00:33 +0000 Subject: Read STL from stdin instead of mmapping it This is more portable and ensures that all triangles are aligned in memory. --- pineapple.c | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'pineapple.c') diff --git a/pineapple.c b/pineapple.c index 870fd4c..5137534 100644 --- a/pineapple.c +++ b/pineapple.c @@ -2,20 +2,17 @@ #include #include -#include #include #include #include #include #include #include -#include -#include -#include #define PI 3.14159265358979323846 -#define die(code, msg) do { fprintf(stderr, "pineapple: %s\n", msg); exit(code); } while (0); +#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) #define USAGE "pineapple [-v] [-w width] [-h height] [-f | -a]" #define dieusage() die(100, "usage: " USAGE) @@ -24,9 +21,14 @@ typedef struct { float x, y, z; } vec3; -struct __attribute__((__packed__)) triangle { - vec3 normal; - vec3 vertices[3]; +struct triangle { + vec3 n; + vec3 a, b, c; +}; + +struct __attribute__((__packed__)) triangle_raw { + vec3 n; + vec3 a, b, c; uint16_t _attr_count; /* unused */ }; @@ -76,9 +78,9 @@ vnorm(vec3 v) float ray_triangle_intersect(vec3 P, vec3 d, struct triangle tri) { - vec3 n = tri.normal, A = tri.vertices[0], B = tri.vertices[1], C = tri.vertices[2]; d = vnorm(d); - n = vnorm(n); + vec3 n = vnorm(tri.n); + vec3 A = tri.a, B = tri.b, C = tri.c; if (dot(n, d) == 0.0) return NAN; float t = (dot(n, A) - dot(n, P)) / dot(n, d); vec3 Q = vadd(P, smul(d, t)); @@ -111,20 +113,22 @@ main(int argc, char *argv[]) argv += optind; argc -= optind; if (argc > 0) dieusage(); - const char *stl; - { - int stl_fd = open("pineapple.stl", O_RDONLY); - if (stl_fd < 0) die(111, "fatal: unable to open pineapple.stl"); - struct stat stl_stat; - if (fstat(stl_fd, &stl_stat) < 0) die(111, "fatal: unable to stat pineapple.stl"); - stl = mmap(NULL, stl_stat.st_size, PROT_READ, MAP_PRIVATE, stl_fd, 0); - close(stl_fd); - if (!stl) die(111, "fatal: unable to mmap pineapple.stl"); + char header[80]; + if (fread(header, 1, 80, stdin) < 80) + diesys(111, "fatal: unable to read STL header from stdin"); + uint32_t len; + if (fread(&len, 4, 1, stdin) < 1) + diesys(111, "fatal: unable to read STL length from stdin"); + len = le32toh(len); + struct triangle *triangles = calloc(len, sizeof(struct triangle)); + if (!triangles) diesys(111, "fatal: unable to allocate enough memory for STL facets"); + struct triangle_raw raw; + 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 }; } - stl += 80; - uint32_t len = le32toh(*(uint32_t *)stl); - stl += 4; - const struct triangle *triangles = (const struct triangle *)stl; + 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; @@ -154,7 +158,7 @@ main(int argc, char *argv[]) float d = ray_triangle_intersect(camera_pos, dir, triangles[i]); if (d != NAN && fabs(d) < fabs(shortest)) { shortest = d; - shortest_norm = triangles[i].normal; + shortest_norm = triangles[i].n; } } -- cgit v1.2.3