X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=scene.cc;h=a415ab084d0354342a420c3cd0a3876ca5d804f5;hb=a737ad45e690daa3b39b8885e2b6574d2ea48833;hp=f0635d800a6bc10de5a53aa6af8be680ce085443;hpb=03be53bf14d0c2e1e3e19356376491945cdd78c8;p=chaz%2Frasterize diff --git a/scene.cc b/scene.cc index f0635d8..a415ab0 100644 --- a/scene.cc +++ b/scene.cc @@ -6,9 +6,13 @@ */ #include +#include +#include "contact.hh" #include "light.hh" -#include "list.hh" +#include "plane.hh" +#include "sphere.hh" +#include "triangle.hh" #include "vec.hh" #include "scene.hh" @@ -17,17 +21,18 @@ static int _scene_add_light(scene_t* s, FILE* file); static int _scene_add_sphere(scene_t* s, FILE* file); static int _scene_add_plane(scene_t* s, FILE* file); +static int _scene_add_triangle(scene_t* s, FILE* file); struct scene { int w, h; vec_t eye; - vec_t spot; - vec_t up; + vec_t screenCenter; + vec_t screenU; + vec_t screenV; list_t* lights; - list_t* spheres; - list_t* planes; + list_t* objects; color_t ambient; }; @@ -47,16 +52,26 @@ scene_t* scene_alloc(FILE* file) return NULL; } + vec_t eye = vec_new(eyeX, eyeY, eyeZ); + vec_t spot = vec_new(spotX, spotY, spotZ); + vec_t up = vec_new(upX, upY, upZ); + scal_t d = S(1.0) / scal_tan((scal_t)fovy * S(0.5)); + + vec_t look = vec_normalize(vec_sub(spot, eye)); + vec_t screenCenter = vec_scale(look, d); + vec_t screenU = vec_normalize(vec_cross(look, up)); + vec_t screenV = vec_cross(screenU, look); + screenU = vec_scale(screenU, (scal_t)aspect); + scene_t* s = (scene_t*)mem_alloc(sizeof(scene_t)); s->w = w; s->h = h; - s->eye = vec_new(eyeX, eyeY, eyeZ); - s->spot = vec_new(spotX, spotY, spotZ); - s->up = vec_new(upX, upY, upZ); - // what to do with fovy and aspect... + s->eye = eye; + s->screenCenter = screenCenter; + s->screenU = screenU; + s->screenV = screenV; s->lights = NULL; - s->spheres = NULL; - s->planes = NULL; + s->objects = NULL; s->ambient = color_new((scal_t)aR, (scal_t)aG, (scal_t)aB, S(1.0)); char type; @@ -80,6 +95,12 @@ scene_t* scene_alloc(FILE* file) } break; + case 't': + if (_scene_add_triangle(s, file) != 0) { + goto fail; + } + break; + case 'X': goto done; @@ -87,11 +108,9 @@ scene_t* scene_alloc(FILE* file) fprintf(stderr, "Unknown identifier: %c\n", type); } } -#undef _ASSERT_G done: - if (s->spheres) list_reverse(&s->spheres); - if (s->planes) list_reverse(&s->planes); + if (s->objects) list_reverse(&s->objects); return s; fail: @@ -102,8 +121,7 @@ fail: void scene_destroy(scene_t* s) { if (s->lights) list_destroy(&s->lights); - if (s->spheres) list_destroy(&s->spheres); - if (s->planes) list_destroy(&s->planes); + if (s->objects) list_destroy(&s->objects); mem_free(s); } @@ -121,7 +139,6 @@ static int _scene_add_light(scene_t* s, FILE* file) } light_t* l = light_alloc( vec_new(lx, ly, lz), - color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0)), color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0)) ); list_push2(&s->lights, l, mem_free); @@ -136,7 +153,12 @@ static int _scene_add_sphere(scene_t* s, FILE* file) fprintf(stderr, "Cannot read sphere values from scene.\n"); return -1; } - /*list_push2(&s->spheres, s, mem_free);*/ + rt::element* sphere = new rt::sphere( + vec_new((scal_t)x, (scal_t)y, (scal_t)z), + (scal_t)radius, + color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0)) + ); + list_push2(&s->objects, sphere, DTOR(rt::sphere_destroy)); return 0; } @@ -148,12 +170,51 @@ static int _scene_add_plane(scene_t* s, FILE* file) fprintf(stderr, "Cannot read plane values from scene.\n"); return -1; } - /*list_push2(&s->planes, s, mem_free);*/ + rt::element* plane = new rt::plane( + vec_new((scal_t)x, (scal_t)y, (scal_t)z), + vec_new((scal_t)nx, (scal_t)ny, (scal_t)nz), + color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0)) + ); + list_push2(&s->objects, plane, DTOR(rt::plane_destroy)); + return 0; +} + +static int _scene_add_triangle(scene_t* s, FILE* file) +{ + double x1, y1, z1, x2, y2, z2, x3, y3, z3, r, g, b; + if (fscanf(file, " %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", + &x1, &y1, &z1, &x2, &y2, &z2, &x3, &y3, &z3, &r, &g, &b) != 12) { + fprintf(stderr, "Cannot read triangle values from scene.\n"); + return -1; + } + rt::element* triangle = new rt::triangle( + vec_new((scal_t)x1, (scal_t)y1, (scal_t)z1), + vec_new((scal_t)x2, (scal_t)y2, (scal_t)z2), + vec_new((scal_t)x3, (scal_t)y3, (scal_t)z3), + color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0)) + ); + list_push2(&s->objects, triangle, DTOR(rt::triangle_destroy)); return 0; } -raster_t* scene_render(scene_t* s) +list_t* scene_elements(const scene_t* s) +{ + return s->objects; +} + +list_t* scene_lights(const scene_t* s) +{ + return s->lights; +} + +color_t scene_ambient(const scene_t* s) +{ + return s->ambient; +} + + +raster_t* scene_render(const scene_t* s) { #if VERBOSITY >= 3 timer_start(); @@ -169,7 +230,37 @@ raster_t* scene_render(scene_t* s) printf("rendering scene...\n"); #endif - // RENDER IT + scal_t wh = S(2.0) / (scal_t)s->w; + scal_t hh = S(2.0) / (scal_t)s->h; + + for (int y = 0; y < s->h; ++y) { + for (int x = 0; x < s->w; ++x) { + color_t* pixel = raster_color(p, x, y); + scal_t u = (scal_t)x * wh - S(1.0); + scal_t v = (scal_t)y * hh - S(1.0); + vec_t rayDirection = vec_add2(s->screenCenter, + vec_scale(s->screenU, u), vec_scale(s->screenV, v)); + + ray_t ray = ray_normalize(ray_new(s->eye, rayDirection)); + + rt::element* nearestObj = 0; + contact_t nearestHit; + + // find the nearest object along the ray + for (list_t* i = s->objects; i; i = i->link) { + rt::element* obj = (rt::element*)i->val; + contact_t hit; + if (obj->intersect(ray, hit) && (!nearestObj || hit.d < nearestHit.d)) { + nearestObj = obj; + nearestHit = hit; + } + } + + if (nearestObj) { + *pixel = nearestObj->cast(nearestHit, s); + } + } + } #if VERBOSITY >= 3 long dt = timer_stop();