initial commit
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 26 Mar 2018 17:53:19 +0000 (20:53 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 26 Mar 2018 17:53:19 +0000 (20:53 +0300)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
src/csgray.c [new file with mode: 0644]
src/csgray.h [new file with mode: 0644]
src/main.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..9c71b18
--- /dev/null
@@ -0,0 +1,4 @@
+*.o
+*.d
+*.swp
+csgray
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..68895e3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,23 @@
+src = $(wildcard src/*.c)
+obj = $(src:.c=.o)
+dep = $(obj:.o=.d)
+bin = csgray
+
+CFLAGS = -pedantic -Wall -g
+LDFLAGS = -lm
+
+$(bin): $(obj)
+       $(CC) -o $@ $(obj) $(LDFLAGS)
+
+-include $(dep)
+
+%.d: %.c
+       @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@
+
+.PHONY: clean
+clean:
+       rm -f $(obj) $(bin)
+
+.PHONY: cleandep
+cleandep:
+       rm -f $(dep)
diff --git a/src/csgray.c b/src/csgray.c
new file mode 100644 (file)
index 0000000..2c60be3
--- /dev/null
@@ -0,0 +1,211 @@
+#include "csgray.h"
+
+enum {
+       OB_NULL,
+       OB_SPHERE,
+       OB_CYLINDER,
+       OB_PLANE,
+       OB_BOX,
+       OB_UNION,
+       OB_INTERSECTION,
+       OB_SUBTRACTION
+};
+
+struct object {
+       int type;
+
+       float r, g, b;
+       float emr, emg, emb;
+       float roughness;
+       float opacity;
+
+       float xform[16];
+
+       struct object *next;
+       struct object *clist, *ctail;
+       struct object *parent;
+};
+
+struct sphere {
+       struct object ob;
+       float rad;
+};
+
+struct plane {
+       struct object ob;
+       float nx, ny, nz;
+       float d;
+};
+
+union csg_object {
+       struct object ob;
+       struct sphere sph;
+       struct plane plane;
+};
+
+struct camera {
+       float x, y, z;
+       float tx, ty, tz;
+       float fov;
+};
+
+static camera cam;
+static object *root;
+static float identity[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
+
+int csg_init(void)
+{
+       if(!(root = csg_null(0, 0, 0))) {
+               return -1;
+       }
+
+       csg_view(0, 0, 5, 0, 0, 0);
+       csg_fov(50);
+
+       return 0;
+}
+
+void csg_destroy(void)
+{
+       csg_free_object(root);
+       root = 0;
+}
+
+void csg_view(float x, float y, float z, float tx, float ty, float tz)
+{
+       cam.x = x;
+       cam.y = y;
+       cam.z = z;
+       cam.tx = tx;
+       cam.ty = ty;
+       cam.tz = tz;
+}
+
+void csg_fov(float fov)
+{
+       cam.fov = M_PI * fov / 180.0f;
+}
+
+
+int csg_load(const char *fname)
+{
+       return 0;       /* TODO */
+}
+
+int csg_save(const char *fname)
+{
+       return 0;       /* TODO */
+}
+
+void csg_add_object(csg_object *parent, csg_object *child)
+{
+       if(parent->clist) {
+               parent->ctail->next = child;
+               parent->ctail = child;
+       } else {
+               parent->clist = parent->ctail = child;
+       }
+       child->parent = parent;
+}
+
+void csg_remove_object(csg_object *parent, csg_object *child)
+{
+       csg_object *c = parent->clist;
+       while(c->next) {
+               if(c->next == child) {
+                       c->next = child->next;
+                       child->next = 0;
+                       child->parent = 0;
+                       return;
+               }
+               c = c->next;
+       }
+}
+
+void csg_free_object(csg_object *o)
+{
+       csg_object *c = o->clist;
+       while(c) {
+               csg_object *tmp = c;
+               c = c->next;
+               csg_free_object(tmp);
+       }
+       free(o);
+}
+
+static void init_object(union csg_object *o)
+{
+       o->ob.type = OBJ_NULL;
+       memcpy(o->ob.xform, identity, sizeof identity);
+
+       csg_emission(o, 0, 0, 0);
+       csg_color(o, 1, 1, 1);
+       csg_roughness(o, 1);
+       csg_opacity(o, 1);
+}
+
+csg_object *csg_null(float x, float y, float z)
+{
+       csg_object *o;
+
+       if(!(o = calloc(sizeof *o, 1))) {
+               return 0;
+       }
+       init_object(o);
+       return o;
+}
+
+csg_object *csg_sphere(float x, float y, float z, float r)
+{
+}
+
+csg_object *csg_cylinder(float x0, float y0, float z0, float x1, float y1, float z1, float r)
+{
+}
+
+csg_object *csg_plane(float x, float y, float z, float nx, float ny, float nz)
+{
+}
+
+csg_object *csg_box(float x, float y, float z, float xsz, float ysz, float zsz)
+{
+}
+
+
+csg_object *csg_union(csg_object *a, csg_object *b)
+{
+}
+
+csg_object *csg_intersection(csg_object *a, csg_object *b)
+{
+}
+
+csg_object *csg_subtraction(csg_object *a, csg_object *b)
+{
+}
+
+
+void csg_emission(csg_object *o, float r, float g, float b)
+{
+}
+
+void csg_color(csg_object *o, float r, float g, float b)
+{
+}
+
+void csg_roughness(csg_object *o, float r)
+{
+}
+
+void csg_opacity(csg_object *o, float p)
+{
+}
+
+
+void csg_render_pixel(int x, int y, float *color)
+{
+}
+
+void csg_render_image(float *pixels, int width, int height)
+{
+}
diff --git a/src/csgray.h b/src/csgray.h
new file mode 100644 (file)
index 0000000..651b64e
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef CSGRAY_H_
+#define CSGRAY_H_
+
+typedef union csg_object csg_object;
+
+int csg_init(void);
+void csg_destroy(void);
+
+void csg_view(float x, float y, float z, float tx, float ty, float tz);
+void csg_fov(float fov);
+
+int csg_load(const char *fname);
+int csg_save(const char *fname);
+
+void csg_add_object(csg_object *parent, csg_object *child);
+void csg_remove_object(csg_object *parent, csg_object *child);
+void csg_free_object(csg_object *o);
+
+csg_object *csg_null(float x, float y, float z);
+csg_object *csg_sphere(float x, float y, float z, float r);
+csg_object *csg_cylinder(float x0, float y0, float z0, float x1, float y1, float z1, float r);
+csg_object *csg_plane(float x, float y, float z, float nx, float ny, float nz);
+csg_object *csg_box(float x, float y, float z, float xsz, float ysz, float zsz);
+
+csg_object *csg_union(csg_object *a, csg_object *b);
+csg_object *csg_intersection(csg_object *a, csg_object *b);
+csg_object *csg_subtraction(csg_object *a, csg_object *b);
+
+void csg_emission(csg_object *o, float r, float g, float b);
+void csg_color(csg_object *o, float r, float g, float b);
+void csg_roughness(csg_object *o, float r);
+void csg_opacity(csg_object *o, float p);
+
+void csg_render_pixel(int x, int y, float *color);
+void csg_render_image(float *pixels, int width, int height);
+
+#endif /* CSGRAY_H_ */
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..9ea196e
--- /dev/null
@@ -0,0 +1,122 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "csgray.h"
+
+static int save_image(const char *fname, float *pix, int xsz, int ysz);
+static int parse_opt(int argc, char **argv);
+
+static int width = 800, height = 600;
+static const char *out_fname = "output.ppm";
+
+int main(int argc, char **argv)
+{
+       csg_object *oa, *ob, *oc;
+       float *pixels;
+
+       if(parse_opt(argc, argv) == -1) {
+               return 1;
+       }
+
+       if(csg_init() == -1) {
+               return 1;
+       }
+
+       if(!(pixels = malloc(width * height * 3 * sizeof *pixels))) {
+               perror("failed to allocate framebuffer");
+               return 1;
+       }
+
+       oa = csg_sphere(0, 0, 0, 1);
+       ob = csg_sphere(0, 1, 0, 0.8);
+       oc = csg_intersection(oa, ob);
+
+       csg_add_object(oc);
+
+       csg_render_image(pixels, width, height);
+       save_image(out_fname, pixels, width, height);
+
+       csg_destroy();
+       return 0;
+}
+
+static int save_image(const char *fname, float *pix, int xsz, int ysz)
+{
+       int i;
+       FILE *fp;
+
+       if(!(fp = fopen(fname, "wb"))) {
+               fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
+               return -1;
+       }
+
+       fprintf(fp, "P6\n%d %d\n65535\n", xsz, ysz);
+
+       for(i=0; i<xsz * ysz; i++) {
+               unsigned int r = *pix++ * 65535.0f;
+               unsigned int g = *pix++ * 65535.0f;
+               unsigned int b = *pix++ * 65535.0f;
+
+               if(r > 0xffff) r = 0xffff;
+               if(g > 0xffff) g = 0xffff;
+               if(b > 0xffff) b = 0xffff;
+
+               fputc(r >> 8, fp);
+               fputc(r, fp);
+               fputc(g >> 8, fp);
+               fputc(g, fp);
+               fputc(b >> 8, fp);
+               fputc(b, fp);
+       }
+       fclose(fp);
+       return 0;
+}
+
+static void print_usage(const char *argv0)
+{
+       printf("Usage: %s [options] <csg file>\n", argv0);
+       printf("Options:\n");
+       printf(" -s <WxH>  output image resolution\n");
+       printf(" -o <file> output image file\n");
+       printf(" -h        print usage information and exit\n");
+}
+
+static int parse_opt(int argc, char **argv)
+{
+       int i;
+
+       for(i=1; i<argc; i++) {
+               if(argv[i][0] == '-') {
+                       if(argv[i][2] == 0) {
+                               switch(argv[i][1]) {
+                               case 's':
+                                       if(sscanf(argv[++i], "%dx%d", &width, &height) != 2) {
+                                               fprintf(stderr, "-s must be followed by WIDTHxHEIGHT\n");
+                                               return -1;
+                                       }
+                                       break;
+
+                               case 'o':
+                                       out_fname = argv[++i];
+                                       break;
+
+                               case 'h':
+                                       print_usage(argv[0]);
+                                       exit(0);
+
+                               default:
+                                       fprintf(stderr, "invalid option: %s\n", argv[i]);
+                                       return -1;
+                               }
+                       } else {
+                               fprintf(stderr, "invalid option: %s\n", argv[i]);
+                               return -1;
+                       }
+               } else {
+                       fprintf(stderr, "unexpected argument: %s\n", argv[i]);
+                       return -1;
+               }
+       }
+       return 0;
+}