working hack. now do it properly with intervals
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 27 Mar 2018 16:47:08 +0000 (19:47 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 27 Mar 2018 16:47:08 +0000 (19:47 +0300)
RUN
src/csgray.c
src/geom.c
src/main.c

diff --git a/RUN b/RUN
index 728ad5c..7cf8029 100755 (executable)
--- a/RUN
+++ b/RUN
@@ -1,4 +1,4 @@
 #!/bin/sh
 
 rm -f output.ppm
-./csgray && display output.ppm
+./csgray $* && display output.ppm
index 53b0146..fe0228a 100644 (file)
@@ -23,7 +23,7 @@ int csg_init(void)
        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);
 
@@ -198,7 +198,7 @@ csg_object *csg_plane(float x, float y, float z, float nx, float ny, float nz)
        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)
@@ -326,7 +326,7 @@ static int ray_trace(struct ray *ray, float *col)
 
 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];
@@ -350,24 +350,25 @@ static void shade(float *col, struct ray *ray, struct hit *hit)
                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];
index dba62ed..1961aed 100644 (file)
@@ -101,9 +101,6 @@ struct hit *ray_sphere(struct ray *ray, csg_object *o)
                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};
@@ -139,15 +136,16 @@ struct hit *ray_plane(struct ray *ray, csg_object *o)
 
        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);
@@ -186,9 +184,50 @@ struct hit *ray_csg_isect(struct ray *ray, csg_object *o)
        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;
 }
 
 
index 44f4900..d6aac1c 100644 (file)
@@ -1,18 +1,25 @@
 #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) {
@@ -31,15 +38,19 @@ int main(int argc, char **argv)
        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);
@@ -58,22 +69,19 @@ static int save_image(const char *fname, float *pix, int xsz, int ysz)
                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);
@@ -84,9 +92,10 @@ 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");
+       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)
@@ -104,6 +113,14 @@ 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;