X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=csgray;a=blobdiff_plain;f=src%2Fcsgray.c;h=47f2a8b25ad33c416d4d5700f0c9becc034239e9;hp=0713c06da99f69aede545c961f652199c3ae47a1;hb=07ca36e28aa10804ba5a544276eb5a25f8105e0f;hpb=40a4c5772ab19e7f27c62768d40f697bf5d80a12 diff --git a/src/csgray.c b/src/csgray.c index 0713c06..47f2a8b 100644 --- a/src/csgray.c +++ b/src/csgray.c @@ -2,67 +2,22 @@ #include #include #include -#include "csgray.h" +#include "csgimpl.h" #include "matrix.h" +#include "geom.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 void calc_primary_ray(struct ray *ray, int x, int y, int w, int h, float aspect); +static int ray_trace(struct ray *ray, float *col); +static void shade(float *col, struct ray *ray, struct hit *hit); +static void background(float *col, struct ray *ray); +static int find_intersection(struct ray *ray, struct hit *best); static struct camera cam; -static csg_object *root; +static csg_object *oblist; int csg_init(void) { - if(!(root = csg_null(0, 0, 0))) { - return -1; - } - + oblist = 0; csg_view(0, 0, 5, 0, 0, 0); csg_fov(50); @@ -71,8 +26,12 @@ int csg_init(void) void csg_destroy(void) { - csg_free_object(root); - root = 0; + while(oblist) { + csg_object *o = oblist; + oblist = oblist->ob.next; + csg_free_object(o); + } + oblist = 0; } void csg_view(float x, float y, float z, float tx, float ty, float tz) @@ -101,63 +60,47 @@ int csg_save(const char *fname) return 0; /* TODO */ } -#define OBPTR(o) ((struct object*)(o)) - -void csg_add_object(csg_object *parent, csg_object *child) +void csg_add_object(csg_object *o) { - if(!parent) { - parent = root; - } - - if(parent->ob.clist) { - parent->ob.ctail->next = OBPTR(child); - parent->ob.ctail = OBPTR(child); - } else { - parent->ob.clist = parent->ob.ctail = OBPTR(child); - } - child->ob.parent = OBPTR(parent); + o->ob.next = oblist; + oblist = o; } -void csg_remove_object(csg_object *parent, csg_object *child) +int csg_remove_object(csg_object *o) { - csg_object *c; + csg_object dummy, *n; - if(!parent) { - parent = root; - } + dummy.ob.next = oblist; + n = &dummy; - c = (csg_object*)parent->ob.clist; - while(c->ob.next) { - if(c->ob.next == OBPTR(child)) { - c->ob.next = child->ob.next; - child->ob.next = 0; - child->ob.parent = 0; - return; + while(n->ob.next) { + if(n->ob.next == o) { + n->ob.next = o->ob.next; + return 1; } - c = (csg_object*)c->ob.next; + n = n->ob.next; } + return 0; } void csg_free_object(csg_object *o) { - csg_object *c = (csg_object*)o->ob.clist; - while(c) { - csg_object *tmp = c; - c = (csg_object*)c->ob.next; - csg_free_object(tmp); + if(o->ob.destroy) { + o->ob.destroy(o); } free(o); } -static union csg_object *alloc_object(void) +static union csg_object *alloc_object(int type) { csg_object *o; if(!(o = calloc(sizeof *o, 1))) { return 0; } - o->ob.type = OB_NULL; + o->ob.type = type; mat4_identity(o->ob.xform); + mat4_identity(o->ob.inv_xform); csg_emission(o, 0, 0, 0); csg_color(o, 1, 1, 1); @@ -169,29 +112,74 @@ static union csg_object *alloc_object(void) csg_object *csg_null(float x, float y, float z) { - return alloc_object(); + return alloc_object(OB_NULL); } csg_object *csg_sphere(float x, float y, float z, float r) { csg_object *o; - if(!(o = alloc_object())) { + if(!(o = alloc_object(OB_SPHERE))) { return 0; } o->sph.rad = r; mat4_translation(o->ob.xform, x, y, z); + mat4_copy(o->ob.inv_xform, o->ob.xform); + mat4_inverse(o->ob.inv_xform); return o; } csg_object *csg_cylinder(float x0, float y0, float z0, float x1, float y1, float z1, float r) { - return 0; + csg_object *o; + float dx, dy, dz; + int major; + + if(!(o = alloc_object(OB_CYLINDER))) { + return 0; + } + + dx = x1 - x0; + dy = y1 - y0; + dz = z1 - z0; + + if(fabs(dx) > fabs(dy) && fabs(dx) > fabs(dz)) { + major = 0; + } else if(fabs(dy) > fabs(dz)) { + major = 1; + } else { + major = 2; + } + + o->cyl.rad = r; + mat4_lookat(o->ob.xform, x0, y0, z0, x1, y1, z1, 0, major == 2 ? 1 : 0, major == 2 ? 0 : 1); + mat4_copy(o->ob.inv_xform, o->ob.xform); + mat4_inverse(o->ob.inv_xform); + return o; } csg_object *csg_plane(float x, float y, float z, float nx, float ny, float nz) { + csg_object *o; + float len; + + if(!(o = alloc_object(OB_PLANE))) { + return 0; + } + + len = sqrt(nx * nx + ny * ny + nz * nz); + if(len != 0.0f) { + float s = 1.0f / len; + nx *= s; + ny *= s; + nz *= s; + } + + o->plane.nx = nx; + o->plane.ny = ny; + o->plane.nz = nz; + o->plane.d = x * nx + y * ny + z * nz; return 0; } @@ -200,44 +188,144 @@ csg_object *csg_box(float x, float y, float z, float xsz, float ysz, float zsz) return 0; } - csg_object *csg_union(csg_object *a, csg_object *b) { - return 0; + csg_object *o; + + if(!(o = alloc_object(OB_UNION))) { + return 0; + } + o->un.a = a; + o->un.b = b; + return o; } csg_object *csg_intersection(csg_object *a, csg_object *b) { - return 0; + csg_object *o; + + if(!(o = alloc_object(OB_INTERSECTION))) { + return 0; + } + o->isect.a = a; + o->isect.b = b; + return o; } csg_object *csg_subtraction(csg_object *a, csg_object *b) { - return 0; + csg_object *o; + + if(!(o = alloc_object(OB_SUBTRACTION))) { + return 0; + } + o->sub.a = a; + o->sub.b = b; + return o; } void csg_emission(csg_object *o, float r, float g, float b) { + o->ob.emr = r; + o->ob.emg = g; + o->ob.emb = b; } void csg_color(csg_object *o, float r, float g, float b) { + o->ob.r = r; + o->ob.g = g; + o->ob.b = b; } void csg_roughness(csg_object *o, float r) { + o->ob.roughness = r; } void csg_opacity(csg_object *o, float p) { + o->ob.opacity = p; } -void csg_render_pixel(int x, int y, float *color) +void csg_render_pixel(int x, int y, int width, int height, float aspect, float *color) { + struct ray ray; + + calc_primary_ray(&ray, x, y, width, height, aspect); + ray_trace(&ray, color); } void csg_render_image(float *pixels, int width, int height) { + int i, j; + float aspect = (float)width / (float)height; + + for(i=0; ix = px; + ray->y = py; + ray->z = cam.z; + + ray->dx = ray->dy = 0.0f; + ray->dz = -1.0f; +} + +static int ray_trace(struct ray *ray, float *col) +{ + struct hit hit; + + if(!find_intersection(ray, &hit)) { + background(col, ray); + return 0; + } + + shade(col, ray, &hit); + return 1; +} + +static void shade(float *col, struct ray *ray, struct hit *hit) +{ + col[0] = 1.0f; + col[1] = col[2] = 0.0f; +} + +static void background(float *col, struct ray *ray) +{ + col[0] = col[1] = col[2] = 0.0f; +} + +static int find_intersection(struct ray *ray, struct hit *best) +{ + csg_object *o; + struct hit *hit; + + best->t = 1e-6f; + best->o = 0; + + o = oblist; + while(o) { + if((hit = ray_intersect(ray, o)) && hit->t < best->t) { + *best = *hit; + } + free_hit(hit); + o = o->ob.next; + } + + return best->o != 0; }