oblist = 0;
plights = 0;
- csg_ambient(0.05, 0.05, 0.05);
+ csg_ambient(0, 0, 0);
csg_view(0, 0, 5, 0, 0, 0);
csg_fov(50);
o->plane.ny = ny;
o->plane.nz = nz;
o->plane.d = x * nx + y * ny + z * nz;
- return 0;
+ return o;
}
csg_object *csg_box(float x, float y, float z, float xsz, float ysz, float zsz)
static void shade(float *col, struct ray *ray, struct hit *hit)
{
- float ndotl, len;
+ float ndotl, len, falloff;
csg_object *o, *lt = plights;
float dcol[3], scol[3] = {0};
float ldir[3];
sray.dy = ldir[1];
sray.dz = ldir[2];
- if(!find_intersection(&sray, &tmphit) || tmphit.t < 1.0f) {
+ if(1) {//!find_intersection(&sray, &tmphit) || tmphit.t > 1.0f) {
if((len = sqrt(ldir[0] * ldir[0] + ldir[1] * ldir[1] + ldir[2] * ldir[2])) != 0.0f) {
float s = 1.0f / len;
ldir[0] *= s;
ldir[1] *= s;
ldir[2] *= s;
}
+ falloff = 1.0f / (len * len);
if((ndotl = hit->nx * ldir[0] + hit->ny * ldir[1] + hit->nz * ldir[2]) < 0.0f) {
ndotl = 0.0f;
}
- dcol[0] += o->ob.r * lt->ob.emr * ndotl;
- dcol[1] += o->ob.g * lt->ob.emg * ndotl;
- dcol[2] += o->ob.b * lt->ob.emb * ndotl;
+ dcol[0] += o->ob.r * lt->ob.emr * ndotl * falloff;
+ dcol[1] += o->ob.g * lt->ob.emg * ndotl * falloff;
+ dcol[2] += o->ob.b * lt->ob.emb * ndotl * falloff;
}
- lt = lt->ob.next;
+ lt = lt->ob.plt_next;
}
col[0] = dcol[0] + scol[0];
t[1] = tmp;
}
- if(t[0] < EPSILON) t[0] = EPSILON;
- if(t[1] < EPSILON) t[1] = EPSILON;
-
hitlist = hit = alloc_hits(2);
for(i=0; i<2; i++) {
float c[3] = {0, 0, 0};
xform_ray(&locray, o->ob.inv_xform);
+ ndotr = o->plane.nx * locray.dx + o->plane.ny * locray.dy + o->plane.nz * locray.dz;
+ if(fabs(ndotr) < EPSILON) return 0;
+
vx = o->plane.nx * o->plane.d - locray.x;
vy = o->plane.ny * o->plane.d - locray.y;
vz = o->plane.nz * o->plane.d - locray.z;
ndotv = o->plane.nx * vx + o->plane.ny * vy + o->plane.nz * vz;
- if(fabs(ndotv) < EPSILON) return 0;
- ndotr = o->plane.nx * locray.dx + o->plane.ny * locray.dy + o->plane.nz * locray.dz;
- t = ndotr / ndotv;
+ t = ndotv / ndotr;
if(t > EPSILON) {
hit = alloc_hits(1);
return 0;
}
+static struct hit *first(struct hit *hlist)
+{
+ return hlist;
+}
+
+static struct hit *last(struct hit *hlist)
+{
+ while(hlist->next) {
+ hlist = hlist->next;
+ }
+ return hlist;
+}
+
struct hit *ray_csg_sub(struct ray *ray, csg_object *o)
{
- return 0;
+ struct hit *hita, *hitb, *lasthit, tmp;
+
+ hita = ray_intersect(ray, o->sub.a);
+ hitb = ray_intersect(ray, o->sub.b);
+
+ if(!hita) return 0;
+ if(!hitb) return hita;
+
+ if(first(hita)->t < first(hitb)->t) {
+ free_hit_list(hitb);
+ return hita;
+ }
+ if(first(hita)->t < (lasthit = last(hitb))->t) {
+ /* overlapping */
+ tmp = *hitb;
+ *hitb = *lasthit;
+
+ free_hit_list(tmp.next);
+
+ hitb->nx = -hitb->nx;
+ hitb->ny = -hitb->ny;
+ hitb->nz = -hitb->nz;
+
+ free_hit_list(hita);
+ return hitb;
+ }
+
+ free_hit_list(hitb);
+ return hita;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include <errno.h>
#include "csgray.h"
+#define DFL_WIDTH 800
+#define DFL_HEIGHT 600
+#define DFL_GAMMA 2.2f
+#define DFL_OUTFILE "output.ppm"
+
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";
+static int width = DFL_WIDTH, height = DFL_HEIGHT;
+static float inv_gamma = 1.0f / DFL_GAMMA;
+static const char *out_fname = DFL_OUTFILE;
int main(int argc, char **argv)
{
- csg_object *oa, *ob, *oc, *lt;
+ csg_object *oa, *ob, *oc, *obj;
float *pixels;
if(parse_opt(argc, argv) == -1) {
csg_view(0, 0, 5, 0, 0, 0);
oa = csg_sphere(0, 0, 0, 1);
- csg_color(oa, 1, 0, 0);
- ob = csg_sphere(-0.3, 0.7, 0.7, 0.7);
- csg_color(ob, 0, 0, 1);
- oc = csg_union(oa, ob);
+ csg_color(oa, 1, 0.1, 0.05);
+ ob = csg_sphere(0.3, 0.7, 0.7, 0.7);
+ csg_color(ob, 0.2, 0.3, 1);
+ oc = csg_subtraction(oa, ob);
csg_add_object(oc);
- lt = csg_null(-4, 10, 20);
- csg_emission(lt, 1, 1, 1);
- csg_add_object(lt);
+ obj = csg_plane(0, -1, 0, 0, 1, 0);
+ csg_color(obj, 0.4, 0.7, 0.4);
+ csg_add_object(obj);
+
+ obj = csg_null(-6, 10, 10);
+ csg_emission(obj, 80, 80, 80);
+ csg_add_object(obj);
csg_render_image(pixels, width, height);
save_image(out_fname, pixels, width, height);
return -1;
}
- fprintf(fp, "P6\n%d %d\n65535\n", xsz, ysz);
+ fprintf(fp, "P6\n%d %d\n255\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;
+ unsigned int r = pow(*pix++, inv_gamma) * 255.0f;
+ unsigned int g = pow(*pix++, inv_gamma) * 255.0f;
+ unsigned int b = pow(*pix++, inv_gamma) * 255.0f;
- if(r > 0xffff) r = 0xffff;
- if(g > 0xffff) g = 0xffff;
- if(b > 0xffff) b = 0xffff;
+ if(r > 255) r = 255;
+ if(g > 255) g = 255;
+ if(b > 255) b = 255;
- fputc(r >> 8, fp);
fputc(r, fp);
- fputc(g >> 8, fp);
fputc(g, fp);
- fputc(b >> 8, fp);
fputc(b, fp);
}
fclose(fp);
{
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");
+ printf(" -s <WxH> output image resolution (default: %dx%d)\n", DFL_WIDTH, DFL_HEIGHT);
+ printf(" -g <gamma> set output gamma (default: %g)\n", DFL_GAMMA);
+ printf(" -o <file> output image file (default: %s)\n", DFL_OUTFILE);
+ printf(" -h print usage information and exit\n");
}
static int parse_opt(int argc, char **argv)
}
break;
+ case 'g':
+ if((inv_gamma = atof(argv[++i])) == 0.0f) {
+ fprintf(stderr, "-g must be followed by a non-zero gamma value\n");
+ return -1;
+ }
+ inv_gamma = 1.0f / inv_gamma;
+ break;
+
case 'o':
out_fname = argv[++i];
break;