summaryrefslogtreecommitdiff
path: root/meme
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2014-09-12 02:54:30 (GMT)
committerWerner Almesberger <werner@almesberger.net>2014-09-12 03:13:49 (GMT)
commit2bc5b2f3ab23a4f75bbb8c23cf437519bb332808 (patch)
treeae092628f305c449572ce3f5304e6b3164e77e68 /meme
parente41c8e654bbe68360aec22b35b424a8849947a98 (diff)
downloadmisc-2bc5b2f3ab23a4f75bbb8c23cf437519bb332808.zip
misc-2bc5b2f3ab23a4f75bbb8c23cf437519bb332808.tar.gz
misc-2bc5b2f3ab23a4f75bbb8c23cf437519bb332808.tar.bz2
measmesh/: renamed to meme/
Too much typing ;-)
Diffstat (limited to 'meme')
-rw-r--r--meme/Makefile31
-rwxr-xr-xmeme/Makefile.c-common57
-rw-r--r--meme/gui.c194
-rw-r--r--meme/main.c52
-rw-r--r--meme/mesh.c137
-rw-r--r--meme/mesh.h54
-rw-r--r--meme/stl.c107
-rw-r--r--meme/stl.h19
-rw-r--r--meme/util.h33
9 files changed, 684 insertions, 0 deletions
diff --git a/meme/Makefile b/meme/Makefile
new file mode 100644
index 0000000..be00b3b
--- /dev/null
+++ b/meme/Makefile
@@ -0,0 +1,31 @@
+#
+# Makefile - Build Measmesh
+#
+# Written 2014 by Werner Almesberger
+# Copyright 2014 by Werner Almesberger
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+include Makefile.c-common
+
+CFLAGS = -Wall -Wshadow -g -O9
+OBJS = main.o stl.o mesh.o gui.o
+CFLAGS += $(shell sdl-config --cflags)
+LDLIBS = $(shell sdl-config --libs) -lSDL_gfx -lm
+
+NAME = meme
+
+
+.PHONY: all clean spotless
+
+all:: $(NAME)
+
+$(NAME): $(OBJS)
+ $(CC) $(LDFLAGS) -o $(NAME) $(OBJS) $(LDLIBS)
+
+spotless: clean
+ rm -f $(NAME)
diff --git a/meme/Makefile.c-common b/meme/Makefile.c-common
new file mode 100755
index 0000000..4d05ec2
--- /dev/null
+++ b/meme/Makefile.c-common
@@ -0,0 +1,57 @@
+#
+# common/Makefile.c-common - Common Makefile items for C
+#
+# Written 2013, 2014 by Werner Almesberger
+# Copyright 2013, 2014 by Werner Almesberger
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+SHELL = /bin/bash
+
+
+# Make sure "all" comes first
+
+all::
+
+# ----- Verbosity control -----------------------------------------------------
+
+CC_normal := $(CC)
+CPP_normal := $(CPP)
+DEPEND_normal = $(CPP_normal) $(CFLAGS) -MM -MG
+
+ifeq ($(V),1)
+ CC = $(CC_normal)
+ BUILD =
+ DEPEND = $(DEPEND_normal)
+else
+ CC = @echo " CC " $@ && $(CC_normal)
+ BUILD = @echo " BUILD " $@ &&
+ DEPEND = @$(DEPEND_normal)
+endif
+
+# ----- Dependencies ----------------------------------------------------------
+
+-include $(OBJS:.o=.d)
+
+MKDEP = \
+ $(DEPEND) $< | \
+ sed \
+ -e 's|^$(basename $(notdir $<)).o:|$@:|' \
+ -e '/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \
+ -e '$${g;p;}' \
+ -e d >$(basename $@).d; \
+ [ "$${PIPESTATUS[*]}" = "0 0" ] || \
+ { rm -f $(basename $@).d; exit 1; }
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $<
+ $(MKDEP)
+
+# ----- Cleanup ---------------------------------------------------------------
+
+clean::
+ rm -f $(OBJS) $(OBJS:.o=.d)
diff --git a/meme/gui.c b/meme/gui.c
new file mode 100644
index 0000000..9473e46
--- /dev/null
+++ b/meme/gui.c
@@ -0,0 +1,194 @@
+/*
+ * gui.c - User interface
+ *
+ * Written 2014 by Werner Almesberger
+ * Copyright 2014 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "SDL.h"
+#include "SDL_gfxPrimitives.h"
+
+#include "mesh.h"
+
+
+#define XRES 1280
+#define YRES 1024
+
+static int x_orig, y_orig;
+static int x_min, x_max, y_min, y_max, z_min, z_max;
+static int zoom;
+
+
+static bool coord(int w, int h, int x, int y,
+ Sint16 *res_x, Sint16 *res_y)
+{
+ int xc = w >> 1;
+ int yc = h >> 1;
+
+ x = ((x-x_orig) >> zoom)+xc;
+ y = ((y-y_orig) >> zoom)+yc;
+
+ if (x < -32768 || x > 32767)
+ return 0;
+ if (y < -32768 || y > 32767)
+ return 0;
+
+ *res_x = x;
+ *res_y = y;
+
+ return 1;
+}
+
+
+static void grid_draw(SDL_Surface *s, int w, int h)
+{
+ const struct facet *f;
+ const struct edge *e;
+ Sint16 xa, ya, xb, yb, xc, yc;
+ int z3;
+ Uint32 c;
+
+ for (f = facets; f; f = f->next) {
+ if (!coord(w, h, f->v[0]->x, f->v[0]->y, &xa, &ya))
+ continue;
+ if (!coord(w, h, f->v[1]->x, f->v[1]->y, &xb, &yb))
+ continue;
+ if (!coord(w, h, f->v[2]->x, f->v[2]->y, &xc, &yc))
+ continue;
+
+ z3 = f->v[0]->z + f->v[1]->z + f->v[2]->z - z_min*3;
+ c = z3*0x90/3/(z_max-z_min)*0x1010100 + 0x606060ff;
+
+ filledTrigonColor(s, xa, ya, xb, yb, xc, yc, c);
+ }
+ for (e = edges; e; e = e->next) {
+ if (!coord(w, h, e->a->x, e->a->y, &xa, &ya))
+ continue;
+ if (!coord(w, h, e->b->x, e->b->y, &xb, &yb))
+ continue;
+ aalineColor(s, xa, ya, xb, yb, 0x000000ff);
+ }
+}
+
+
+static void draw(SDL_Surface *s)
+{
+ SDL_FillRect(s, NULL, SDL_MapRGB(s->format, 0xff, 0xff, 0xff));
+ grid_draw(s, XRES, YRES);
+}
+
+
+static void button_event(SDL_MouseButtonEvent *button)
+{
+ int x, y; /* model coordinates */
+
+ x = ((button->x - (XRES >> 1)) << zoom)+x_orig;
+ y = ((button->y - (YRES >> 1)) << zoom)+y_orig;
+
+ switch (button->button) {
+ case 4:
+ if (zoom == 1)
+ break;
+ zoom--;
+ x_orig = (x_orig+x)/2;
+ y_orig = (y_orig+y)/2;
+ break;
+ case 5:
+ if (1 << (zoom+1) > x_max-x_min && 1 << (zoom+1) > y_max-y_min)
+ return;
+ zoom++;
+ x_orig = 2*x_orig-x;
+ y_orig = 2*y_orig-y;
+ break;
+ }
+}
+
+
+static bool extrema_vertex(const struct vertex *v, void *user)
+{
+ bool *first = user;
+
+ if (*first) {
+ x_min = x_max = v->x;
+ y_min = y_max = v->y;
+ z_min = z_max = v->z;
+ *first = 0;
+ } else {
+ if (x_min > v->x)
+ x_min = v->x;
+ if (x_max < v->x)
+ x_max = v->x;
+ if (y_min > v->y)
+ y_min = v->y;
+ if (y_max < v->y)
+ y_max = v->y;
+ if (z_min > v->z)
+ z_min = v->z;
+ if (z_max < v->z)
+ z_max = v->z;
+ }
+ return 0;
+}
+
+
+static void extrema(void)
+{
+ bool first = 1;
+
+ vertex_foreach_const(extrema_vertex, &first);
+}
+
+
+void gui(void)
+{
+ SDL_Surface *surf;
+ SDL_Event event;
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ fprintf(stderr, "SDL_init: %s\n", SDL_GetError());
+ exit(1);
+ }
+ atexit(SDL_Quit);
+
+ surf = SDL_SetVideoMode(XRES, YRES, 0, SDL_SWSURFACE);
+ if (!surf) {
+ fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError());
+ exit(1);
+ }
+
+ extrema();
+ x_orig = (x_min+x_max) >> 1;
+ y_orig = (y_min+y_max) >> 1;
+ zoom = 7;
+
+ while (1) {
+ bool redraw;
+
+ SDL_LockSurface(surf);
+ draw(surf);
+ SDL_UnlockSurface(surf);
+ SDL_UpdateRect(surf, 0, 0, 0, 0);
+
+ redraw = 0;
+ while (SDL_WaitEvent(&event) && !redraw) {
+ switch (event.type) {
+ case SDL_MOUSEBUTTONDOWN:
+ button_event(&event.button);
+ redraw = 1;
+ break;
+ case SDL_QUIT:
+ return;
+ }
+ }
+ }
+}
diff --git a/meme/main.c b/meme/main.c
new file mode 100644
index 0000000..9e42adc
--- /dev/null
+++ b/meme/main.c
@@ -0,0 +1,52 @@
+/*
+ * main.c - Measmesh command-line processing and setup
+ *
+ * Written 2014 by Werner Almesberger
+ * Copyright 2014 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "mesh.h"
+#include "stl.h"
+
+
+extern void gui(void);
+
+
+static void usage(const char *name)
+{
+ fprintf(stderr, "usage: %s\n", name);
+ exit(1);
+}
+
+
+int main(int argc, char **argv)
+{
+ switch (argc) {
+ case 1:
+ stl_load(stdin);
+ break;
+ default:
+ usage(*argv);
+ }
+
+ gui();
+{
+ const struct edge *e;
+ int n = 0;
+
+ for (e = edges; e; e = e->next)
+ n++;
+ printf("%d edges\n", n);
+}
+
+ return 0;
+}
diff --git a/meme/mesh.c b/meme/mesh.c
new file mode 100644
index 0000000..7f1d37c
--- /dev/null
+++ b/meme/mesh.c
@@ -0,0 +1,137 @@
+/*
+ * mesh.c - 3D mesh data structures
+ *
+ * Written 2014 by Werner Almesberger
+ * Copyright 2014 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include "util.h"
+#include "mesh.h"
+
+
+#define VHASH_TABLE (1 << 20)
+#define EHASH_TABLE (1 << 20)
+
+
+struct v {
+ struct vertex v;
+ struct v *next;
+};
+
+struct e {
+ struct edge e;
+ struct e *next;
+};
+
+
+static struct v *vhash[VHASH_TABLE];
+static struct e *ehash[EHASH_TABLE];
+
+
+struct edge *edges = NULL;
+struct facet *facets = NULL;
+
+
+#define VHASH(x, y, z) ((x) % VHASH_TABLE)
+#define EHASH(a, b) ((long) (a) % EHASH_TABLE)
+
+
+const struct vertex *vertex_add(int x, int y, int z)
+{
+ struct v **h = &vhash[VHASH(x, y, z)];
+ struct v *v;
+
+ for (v = *h; v; v = v->next)
+ if (v->v.x == x && v->v.y == y && v->v.z == z)
+ return &v->v;
+
+ v = alloc_type(struct v);
+ v->v.x = x;
+ v->v.y = y;
+ v->v.z = z;
+ v->next = *h;
+ *h = v;
+ return &v->v;
+}
+
+
+void vertex_foreach(bool (*fn)(struct vertex *v, void *user), void *user)
+{
+ struct v *v;
+ int i;
+
+ for (i = 0; i != VHASH_TABLE; i++)
+ for (v = vhash[i]; v; v = v->next)
+ if (fn(&v->v, user))
+ return;
+}
+
+
+void vertex_foreach_const(bool (*fn)(const struct vertex *v, void *user),
+ void *user)
+{
+ const struct v *v;
+ int i;
+
+ for (i = 0; i != VHASH_TABLE; i++)
+ for (v = vhash[i]; v; v = v->next)
+ if (fn(&v->v, user))
+ return;
+}
+
+
+static void edge_add(const struct vertex *a, const struct vertex *b)
+{
+ const struct vertex *tmp;
+ struct e **h;
+ struct e *e;
+
+ if (a > b) {
+ tmp = a;
+ a = b;
+ b = tmp;
+ }
+ h = &ehash[EHASH(a, b)];
+ for (e = *h; e; e = e->next)
+ if (e->e.a == a && e->e.b == b)
+ return;
+
+ e = alloc_type(struct e);
+ e->e.a = a;
+ e->e.b = b;
+ e->e.next = edges;
+ edges = &e->e;
+ e->next = *h;
+ *h = e;
+}
+
+
+const struct facet *facet_add(const struct vertex *a, const struct vertex *b,
+ const struct vertex *c)
+{
+ struct facet *f;
+
+ f = alloc_type(struct facet);
+ f->v[0] = a;
+ f->v[1] = b;
+ f->v[2] = c;
+
+ edge_add(a, b);
+ edge_add(b, c);
+ edge_add(c, a);
+
+ f->next = facets;
+ facets = f;
+ return f;
+}
+
+
+void mesh_init(void)
+{
+}
diff --git a/meme/mesh.h b/meme/mesh.h
new file mode 100644
index 0000000..1927147
--- /dev/null
+++ b/meme/mesh.h
@@ -0,0 +1,54 @@
+/*
+ * mesh.h - 3D mesh data structures
+ *
+ * Written 2014 by Werner Almesberger
+ * Copyright 2014 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#ifndef MESH_H
+#define MESH_H
+
+
+#include <stdbool.h>
+
+
+struct vertex {
+ int x, y, z;
+};
+
+
+struct edge {
+ const struct vertex *a, *b;
+ bool drawn;
+ struct edge *next;
+};
+
+
+struct facet {
+ const struct vertex *v[3];
+ struct facet *next;
+};
+
+
+extern struct edge *edges;
+extern struct facet *facets;
+
+
+const struct vertex *vertex_add(int x, int y, int z);
+
+void vertex_foreach(bool (*fn)(struct vertex *v, void *user), void *user);
+void vertex_foreach_const(bool (*fn)(const struct vertex *v, void *user),
+ void *user);
+
+const struct facet *facet_add(const struct vertex *a, const struct vertex *b,
+ const struct vertex *c);
+
+void mesh_init(void);
+
+#endif /* !MESH_H */
diff --git a/meme/stl.c b/meme/stl.c
new file mode 100644
index 0000000..20f8c3b
--- /dev/null
+++ b/meme/stl.c
@@ -0,0 +1,107 @@
+/*
+ * stl.c - STL file reading
+ *
+ * Written 2014 by Werner Almesberger
+ * Copyright 2014 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+
+#include "mesh.h"
+#include "stl.h"
+
+
+#define MAX_LINE 100
+
+
+enum state {
+ s_init,
+ s_facet,
+ s_loop,
+ s_vertices,
+ s_endloop,
+ s_endfacet,
+};
+
+
+void stl_load(FILE *file)
+{
+ char buf[MAX_LINE+1];
+ enum state state = s_init;
+ const struct vertex *v[3];
+ int num_v = 0;
+ char *s, *e;
+ int n = 0;
+ int end, got;
+ double x, y, z;
+
+ mesh_init();
+ while (fgets(buf, sizeof(buf), file)) {
+ n++;
+ if (!(n & 1023))
+ fprintf(stderr, "%d\r", n);
+
+ for (s = buf; *s && isspace(*s); s++);
+ e = strchr(s, 0);
+ while (e != s && isspace(e[-1]))
+ e--;
+ *e = 0;
+ end = 0;
+
+ switch (state) {
+ case s_init:
+ sscanf(s, "solid %*s%n", &end);
+ state = s_facet;
+ break;
+ case s_facet:
+ if (!strncmp(s, "endsolid", 8))
+ return;
+ sscanf(s, "facet normal %*f %*f %*f%n", &end);
+ state = s_loop;
+ break;
+ case s_loop:
+ sscanf(s, "outer loop%n", &end);
+ state = s_vertices;
+ num_v = 0;
+ break;
+ case s_vertices:
+ got = sscanf(s, "vertex %lf %lf %lf%n",
+ &x,&y, &z, &end);
+ if (got < 3)
+ break;
+ v[num_v] = vertex_add(
+ round(x*1000), round(y*1000), round(z*1000));
+ if (++num_v == 3) {
+ facet_add(v[0], v[1], v[2]);
+ state = s_endloop;
+ }
+ break;
+ case s_endloop:
+ sscanf(s, "endloop%n", &end);
+ state = s_endfacet;
+ break;
+ case s_endfacet:
+ sscanf(s, "endfacet%n", &end);
+ state = s_facet;
+ break;
+ }
+ if (end != e-s) {
+ fprintf(stderr, "cannot parse line %d (%d %ld)\n",
+ n, end, e-s);
+ exit(1);
+ }
+ }
+ fprintf(stderr, "incomplete STL file\n");
+ exit(1);
+
+}
diff --git a/meme/stl.h b/meme/stl.h
new file mode 100644
index 0000000..da90b92
--- /dev/null
+++ b/meme/stl.h
@@ -0,0 +1,19 @@
+/*
+ * stl.h - STL file reading
+ *
+ * Written 2014 by Werner Almesberger
+ * Copyright 2014 by Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#ifndef STL_H
+#define STL_H
+
+void stl_load(FILE *file);
+
+#endif /* !STL_H */
diff --git a/meme/util.h b/meme/util.h
new file mode 100644
index 0000000..ec05995
--- /dev/null
+++ b/meme/util.h
@@ -0,0 +1,33 @@
+/*
+ * util.h - Common utility functions
+ *
+ * Written 2006, 2009, 2010, 2014 by Werner Almesberger
+ * Copyright 2006, 2009, 2010, 2014 Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <stddef.h>
+#include <stdlib.h>
+
+
+#define alloc_size(s) \
+ ({ void *alloc_size_tmp = malloc(s); \
+ if (!alloc_size_tmp) \
+ abort(); \
+ alloc_size_tmp; })
+
+#define alloc_type(t) ((t *) alloc_size(sizeof(t)))
+
+
+#define container(ptr, type, member) \
+ ((type *) ((void *) (ptr) - offsetof(type, member)))
+
+#endif /* !UTIL_H */