From: John Tsiombikas Date: Mon, 26 Mar 2018 17:53:19 +0000 (+0300) Subject: initial commit X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=csgray;a=commitdiff_plain;h=d7bf88ecc329f85167bcb420909773ba21078001 initial commit --- d7bf88ecc329f85167bcb420909773ba21078001 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9c71b18 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.d +*.swp +csgray diff --git a/Makefile b/Makefile new file mode 100644 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 index 0000000..2c60be3 --- /dev/null +++ b/src/csgray.c @@ -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 index 0000000..651b64e --- /dev/null +++ b/src/csgray.h @@ -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 index 0000000..9ea196e --- /dev/null +++ b/src/main.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#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 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] \n", argv0); + printf("Options:\n"); + printf(" -s output image resolution\n"); + printf(" -o 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