# HG changeset patch # User Radek Brich # Date 1197925430 -3600 # Node ID 929aad02c5f2a9f373dd2821ed5c7b80bc3153e6 # Parent 7079dcc3bd74c5b1b1f5f8241964dd876dcabe94 Makefile: added help and distclean target, plus small fixes ccdemos/common_sdl.h: print fps to window caption instead of console update and key callbacks fixed segfault when resizing window pressing c now causes print out of camera coordinates ccdemos/spheres_shadow.cc: controlling position of a light and focal length of camera diff -r 7079dcc3bd74 -r 929aad02c5f2 Makefile --- a/Makefile Fri Dec 14 16:51:22 2007 +0100 +++ b/Makefile Mon Dec 17 22:03:50 2007 +0100 @@ -1,7 +1,24 @@ ROOT=$(shell pwd) include config.mk -all: python-module demos ccdemos models +nomodels: libs-float libs-double python-module demos ccdemos + +all: nomodels models + +.PHONY : all nomodels clean distclean help + +help: + @echo 'available targets:' + @echo ' all make everything' + @echo ' nomodels make everything except models' + @echo ' models download models' + @echo ' python-module build the Python module' + @echo ' demos prepare Python demos' + @echo ' ccdemos build C++ demos' + @echo ' help this help message' + @echo ' clean remove auxiliary files and executables' + @echo ' distclean remove all non-distribution files (use with care)' + @echo 'default target is nomodels' python-module: libs-float $(MAKE) -C src python-module @@ -26,6 +43,11 @@ $(MAKE) -C demos clean $(MAKE) -C ccdemos clean +distclean: clean + $(MAKE) -C demos distclean + $(MAKE) -C ccdemos distclean + $(MAKE) -C models distclean + # TARGETS ######### diff -r 7079dcc3bd74 -r 929aad02c5f2 TODO --- a/TODO Fri Dec 14 16:51:22 2007 +0100 +++ b/TODO Mon Dec 17 22:03:50 2007 +0100 @@ -7,8 +7,8 @@ * kd-tree: - optimize structures - optimize construction: do not use bounding boxes of shapes, instead implement box-shape intersection + - optimize traversal -- no std::vector - save/load - * uniform grid, octree * textures (3D procedural, pixmaps later) * update Python binding: Camera, new classes * namespace diff -r 7079dcc3bd74 -r 929aad02c5f2 ccdemos/Makefile --- a/ccdemos/Makefile Fri Dec 14 16:51:22 2007 +0100 +++ b/ccdemos/Makefile Mon Dec 17 22:03:50 2007 +0100 @@ -4,26 +4,29 @@ include $(ROOT)/config.mk +RTLIBS=libs-double +DEFS+=-DPYRIT_DOUBLE + ### Rules ### %.o: %.cc - $(CXX) -c -o $@ $(CCFLAGS) $(SDL_CCFLAGS) $< $(DEFS) -DPYRIT_DOUBLE + $(CXX) -c -o $@ $(CCFLAGS) $(SDL_CCFLAGS) $< $(DEFS) %: %.o - $(CXX) -o $@ $(ROOT)/bin/libs-double/*.o $< image.o $(LDFLAGS) $(SDL_LDFLAGS) -lpng + $(CXX) -o $@ $(ROOT)/bin/$(RTLIBS)/*.o $< image.o $(LDFLAGS) $(SDL_LDFLAGS) -lpng ### Targets ### all: realtime realtime_dragon realtime_bunny spheres_shadow -realtime: realtime.o libs-double image.o -realtime_dragon: realtime_dragon.o libs-double image.o -realtime_bunny: realtime_bunny.o libs-double image.o -spheres_shadow: spheres_shadow.o libs-double image.o +realtime: realtime.o $(RTLIBS) image.o +realtime_dragon: realtime_dragon.o $(RTLIBS) image.o +realtime_bunny: realtime_bunny.o $(RTLIBS) image.o +spheres_shadow: spheres_shadow.o $(RTLIBS) image.o -realtime.o: realtime.cc +realtime.o: realtime.cc common_sdl.h realtime_dragon.o: realtime_dragon.cc common_sdl.h common_ply.h realtime_bunny.o: realtime_bunny.cc common_sdl.h common_ply.h -spheres_shadow.o: spheres_shadow.cc +spheres_shadow.o: spheres_shadow.cc common_sdl.h libs-float: $(MAKE) -C ../src libs-float @@ -36,3 +39,6 @@ clean: rm -f spheres_shadow realtime realtime_dragon realtime_bunny *.o + +distclean: clean + rm -rf *.png diff -r 7079dcc3bd74 -r 929aad02c5f2 ccdemos/common_sdl.h --- a/ccdemos/common_sdl.h Fri Dec 14 16:51:22 2007 +0100 +++ b/ccdemos/common_sdl.h Mon Dec 17 22:03:50 2007 +0100 @@ -17,8 +17,9 @@ ++fp10s_acc_samples; } t = tnow; - printf("\b\b\b\b\b\b\b\b\bfps:%3d.%1d", fp10s/10, fp10s%10); - fflush(stdout); + char s[40]; + sprintf(s, "fps:%3d.%1d", fp10s/10, fp10s%10); + SDL_WM_SetCaption(s, NULL); rt.render(w, h, render_buffer); @@ -50,14 +51,8 @@ SDL_UpdateRect(screen, 0, 0, w, h); } -void quit() -{ - Uint32 fp100s_aver = fp10s_acc*10/fp10s_acc_samples; - printf("\naverlage fps: %3d.%2d\n", fp100s_aver/100, fp100s_aver%100); - SDL_Quit(); -} - -void loop_sdl(Raytracer &rt, Camera &cam) +void loop_sdl(Raytracer &rt, Camera &cam, + void (*update_callback)() = NULL, void (*key_callback)(int, int) = NULL) { SDL_Surface *screen; Float *render_buffer; @@ -69,9 +64,7 @@ fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); exit(1); } - - atexit(quit); - + screen = SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE); if ( screen == NULL ) { fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError()); @@ -87,8 +80,8 @@ { switch (event.type) { case SDL_VIDEORESIZE: - w = event.resize.w; - h = event.resize.h; + w = (event.resize.w-1) / 8 * 8 + 8; + h = (event.resize.h-1) / 8 * 8 + 8; render_buffer = (Float *) realloc(render_buffer, w*h*3*sizeof(Float)); screen = SDL_SetVideoMode(w, h, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE); break; @@ -121,6 +114,17 @@ move = -0.5; break; } + if (event.key.keysym.sym == SDLK_c) { + // print camera coordinates + cout << "Camera: eye=" << cam.eye + << ", p=" << cam.p + << ", u=" << cam.u + << ", v=" << cam.v + << endl; + break; + } + if (key_callback != NULL) + key_callback(event.key.keysym.sym, 1); break; case SDL_KEYUP: if (event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) { @@ -132,9 +136,11 @@ break; } if (event.key.keysym.sym == SDLK_w || event.key.keysym.sym == SDLK_s) { - move = 0.0; - break; - } + move = 0.0; + break; + } + if (key_callback != NULL) + key_callback(event.key.keysym.sym, 0); break; case SDL_QUIT: quit = true; @@ -144,8 +150,15 @@ cam.rotate(Quaternion(cos(rotx),cam.u[0]*sin(rotx),0,cam.u[2]*sin(rotx)).normalize()); cam.u.y = 0; cam.u.normalize(); - cam.move(move,0,0); + if (move != 0.0) + cam.move(move,0,0); + if (update_callback != NULL) + update_callback(); update(rt, screen, render_buffer); } free(render_buffer); + + Uint32 fp100s_aver = fp10s_acc*10/fp10s_acc_samples; + printf("averlage fps: %3d.%2d\n\n", fp100s_aver/100, fp100s_aver%100); + SDL_Quit(); } diff -r 7079dcc3bd74 -r 929aad02c5f2 ccdemos/realtime.cc --- a/ccdemos/realtime.cc Fri Dec 14 16:51:22 2007 +0100 +++ b/ccdemos/realtime.cc Mon Dec 17 22:03:50 2007 +0100 @@ -1,9 +1,11 @@ +#include + #include "raytracer.h" #include "octree.h" #include "common_sdl.h" -int main() +int main(int argc, char **argv) { Raytracer rt; Octree top; @@ -23,7 +25,7 @@ Material mat_sph(Colour(1.0, 1.0, 1.0)); for (int y=0; y<10; y++) for (int x=0; x<10; x++) - rt.addshape(new Sphere(Vector3(x*2-10, (Float)random()/RAND_MAX*5.0, y*2-10), 0.45, &mat_sph)); + rt.addshape(new Sphere(Vector3(x*2-10, (Float)rand()/RAND_MAX*5.0, y*2-10), 0.45, &mat_sph)); rt.setCamera(&cam); cam.setEye(Vector3(0,0,10)); diff -r 7079dcc3bd74 -r 929aad02c5f2 ccdemos/realtime_bunny.cc --- a/ccdemos/realtime_bunny.cc Fri Dec 14 16:51:22 2007 +0100 +++ b/ccdemos/realtime_bunny.cc Mon Dec 17 22:03:50 2007 +0100 @@ -4,7 +4,7 @@ #include "common_sdl.h" #include "common_ply.h" -int main() +int main(int argc, char **argv) { Raytracer rt; Octree top; diff -r 7079dcc3bd74 -r 929aad02c5f2 ccdemos/realtime_dragon.cc --- a/ccdemos/realtime_dragon.cc Fri Dec 14 16:51:22 2007 +0100 +++ b/ccdemos/realtime_dragon.cc Mon Dec 17 22:03:50 2007 +0100 @@ -4,7 +4,7 @@ #include "common_sdl.h" #include "common_ply.h" -int main() +int main(int argc, char **argv) { Raytracer rt; Octree top; diff -r 7079dcc3bd74 -r 929aad02c5f2 ccdemos/spheres_shadow.cc --- a/ccdemos/spheres_shadow.cc Fri Dec 14 16:51:22 2007 +0100 +++ b/ccdemos/spheres_shadow.cc Mon Dec 17 22:03:50 2007 +0100 @@ -4,6 +4,55 @@ #include "image.h" #include "common_sdl.h" +Camera cam; +Light light(Vector3(-2.0, 10.0, -2.0), Colour(0.9, 0.9, 0.9)); + +Float lx, ly, lz, cf; + +void update_callback() +{ + if (lx != 0.0) + light.pos.x += lx; + if (ly != 0.0) + light.pos.y += ly; + if (lz != 0.0) + light.pos.z += lz; + if (cf != 0.0) + cam.f += cf; +} + +void key_callback(int key, int down) +{ + switch (key) + { + case SDLK_r: + lx = -0.1 * down; + break; + case SDLK_t: + lx = +0.1 * down; + break; + case SDLK_f: + ly = -0.1 * down; + break; + case SDLK_g: + ly = +0.1 * down; + break; + case SDLK_v: + lz = -0.1 * down; + break; + case SDLK_b: + lz = +0.1 * down; + break; + + case SDLK_z: + cf = -0.02 * down; + break; + case SDLK_x: + cf = +0.02 * down; + break; + } +} + int main(int argc, char **argv) { Raytracer rt; @@ -13,16 +62,21 @@ Octree top; rt.setTop(&top); - Light light1(Vector3(0.0, 5.0, -5.0), Colour(0.7, 0.3, 0.6)); - rt.addlight(&light1); + rt.addlight(&light); + + //Light light2; + //light2.colour = Colour(0.7, 0.3, 0.6); + //rt.addlight(&light2); - Light light2(Vector3(-2.0, 10.0, -2.0), Colour(0.4, 0.6, 0.3)); - rt.addlight(&light2); + Material mat0a(Colour(0.7, 0.7, 0.7)); + mat0a. setReflectivity(0.0); + Box box(Vector3(-10.0, -1.2, -20.0), Vector3(10.0, -1.0, 0.0), &mat0a); + rt.addshape(&box); - Material mat0(Colour(0.7, 0.7, 0.7)); - - Box box(Vector3(-20.0, -1.2, -20.0), Vector3(20.0, -1.0, 20.0), &mat0); - rt.addshape(&box); + Material mat0b(Colour(0.1, 0.7, 0.8)); + mat0b.setReflectivity(0.7); + Box box2(Vector3(-10.0, -1.2, -20.0), Vector3(10.0, 10.0, -20.2), &mat0b); + rt.addshape(&box2); Material mat1(Colour(1.0, 0.0, 0.0)); Sphere bigsphere(Vector3(3.0, 2.0, -7.0), 3.0, &mat1); @@ -33,28 +87,36 @@ rt.addshape(&smallsphere); Material mat3(Colour(0.0, 0.0, 1.0)); - Sphere tinysphere(Vector3(-1.2, 0.0, -2.0), 0.5, &mat3); + mat3.setReflectivity(0.1); + mat3.setTransmissivity(0.8, 1.5); + Sphere tinysphere(Vector3(-1.2, 0.0, -2.0), 0.7, &mat3); rt.addshape(&tinysphere); top.optimize(); - Camera cam; - cam.setEye(Vector3(0,0,15)); + cam.setEye(Vector3(-2.28908, 4.30992, 12.3051)); + cam.p = Vector3(0.0988566, -0.139543, -0.985269); + cam.u = Vector3(-0.995004, 0, -0.0998334); + cam.v = Vector3(0.0139311, 0.990216, -0.138846); rt.setCamera(&cam); w = 800; h = 600; - if (argc == 2 && !strcmp(argv[1], "-i")) - loop_sdl(rt, cam); - else + /* run interactive mode */ + loop_sdl(rt, cam, update_callback, key_callback); + + /* render image */ + if (argc == 2 && !strcmp(argv[1], "-r")) { + pyrit_verbosity = 2; Float *fdata = (Float *) malloc(w*h*3*sizeof(Float)); + rt.setOversample(2); rt.render(w, h, fdata); - + struct image *img; new_image(&img, w, h, 3); - + Float *fd = fdata; for (char *cd = img->data; cd != img->data + w*h*3; cd++, fd++) { if (*fd > 1.0) diff -r 7079dcc3bd74 -r 929aad02c5f2 demos/Makefile --- a/demos/Makefile Fri Dec 14 16:51:22 2007 +0100 +++ b/demos/Makefile Mon Dec 17 22:03:50 2007 +0100 @@ -15,3 +15,8 @@ $(MAKE) -C .. models clean: ; + +distclean: clean + rm -f *.png + rm -f *.pyc + rm -f kdtree.obj diff -r 7079dcc3bd74 -r 929aad02c5f2 demos/bunny.py --- a/demos/bunny.py Fri Dec 14 16:51:22 2007 +0100 +++ b/demos/bunny.py Mon Dec 17 22:03:50 2007 +0100 @@ -28,9 +28,11 @@ rt.addshape(box2) light = Light(position=(-5.0, 3.0, 10.0), colour=(0.9, 0.3, 0.6)) +#light.castshadows(0) rt.addlight(light) light2 = Light(position=(4.0, 1.0, 10.0), colour=(0.2, 0.9, 0.5)) +#light2.castshadows(0) rt.addlight(light2) imagesize = (800, 600) diff -r 7079dcc3bd74 -r 929aad02c5f2 include/scene.h --- a/include/scene.h Fri Dec 14 16:51:22 2007 +0100 +++ b/include/scene.h Mon Dec 17 22:03:50 2007 +0100 @@ -72,6 +72,8 @@ Colour colour; bool cast_shadows; + Light(): + pos(Vector3(0,0,0)), colour(Colour(1,1,1)), cast_shadows(true) {}; Light(const Vector3 &position, const Colour &acolour): pos(position), colour(acolour), cast_shadows(true) {}; void castShadows(bool cast) { cast_shadows = cast; }; diff -r 7079dcc3bd74 -r 929aad02c5f2 models/Makefile --- a/models/Makefile Fri Dec 14 16:51:22 2007 +0100 +++ b/models/Makefile Mon Dec 17 22:03:50 2007 +0100 @@ -29,7 +29,7 @@ clean: ; -distclean: +distclean: clean rm -rf bunny rm -rf happy rm -rf dragon diff -r 7079dcc3bd74 -r 929aad02c5f2 src/raytracer.cc --- a/src/raytracer.cc Fri Dec 14 16:51:22 2007 +0100 +++ b/src/raytracer.cc Mon Dec 17 22:03:50 2007 +0100 @@ -190,7 +190,7 @@ } // ambient occlusion - if (ao_samples) + if (!from_inside && ao_samples) { Float miss = 0; for (int i = 0; i < ao_samples; i++) { diff -r 7079dcc3bd74 -r 929aad02c5f2 src/scene.cc --- a/src/scene.cc Fri Dec 14 16:51:22 2007 +0100 +++ b/src/scene.cc Mon Dec 17 22:03:50 2007 +0100 @@ -59,21 +59,21 @@ /* http://www.siggraph.org/education/materials/HyperGraph/raytrace/rtinter3.htm */ bool BBox::intersect(const Ray &ray, Float &a, Float &b) { - Float tnear = -FLT_MAX; - Float tfar = FLT_MAX; - Float t1, t2; + register Float tnear = -Inf; + register Float tfar = Inf; + register Float t1, t2; for (int i = 0; i < 3; i++) { - if (ray.dir.cell[i] == 0) { + if (ray.dir[i] == 0) { /* ray is parallel to these planes */ - if (ray.o.cell[i] < L.cell[i] || ray.o.cell[i] > H.cell[i]) + if (ray.o[i] < L[i] || ray.o[i] > H[i]) return false; } else { /* compute the intersection distance of the planes */ - t1 = (L.cell[i] - ray.o.cell[i]) / ray.dir.cell[i]; - t2 = (H.cell[i] - ray.o.cell[i]) / ray.dir.cell[i]; + t1 = (L[i] - ray.o[i]) / ray.dir[i]; + t2 = (H[i] - ray.o[i]) / ray.dir[i]; if (t1 > t2) swap(t1, t2); @@ -82,10 +82,8 @@ tnear = t1; /* want largest Tnear */ if (t2 < tfar) tfar = t2; /* want smallest Tfar */ - if (tnear > tfar) - return false; /* box missed */ - if (tfar < 0) - return false; /* box is behind ray */ + if (tnear > tfar || tfar < 0) + return false; /* box missed; box is behind ray */ } } @@ -110,6 +108,7 @@ return false; } +/* if there should be CSG sometimes, this may be needed... */ bool Sphere::intersect_all(const Ray &ray, Float dist, vector &allts) const { //allts = new vector(); @@ -167,14 +166,41 @@ bool Box::intersect(const Ray &ray, Float &dist) const { - Float a,b; - if (get_bbox().intersect(ray, a, b) && a < dist) + register Float tnear = -Inf; + register Float tfar = Inf; + register Float t1, t2; + + for (int i = 0; i < 3; i++) { - dist = a; + if (ray.dir[i] == 0) { + /* ray is parallel to these planes */ + if (ray.o[i] < L[i] || ray.o[i] > H[i]) + return false; + } + else + { + /* compute the intersection distance of the planes */ + t1 = (L[i] - ray.o[i]) / ray.dir[i]; + t2 = (H[i] - ray.o[i]) / ray.dir[i]; + + if (t1 > t2) + swap(t1, t2); + + if (t1 > tnear) + tnear = t1; /* want largest Tnear */ + if (t2 < tfar) + tfar = t2; /* want smallest Tfar */ + if (tnear > tfar || tfar < 0) + return false; /* box missed; box is behind ray */ + } + } + + if (tnear < dist) + { + dist = tnear; return true; } - else - return false; + return false; } bool Box::intersect_bbox(const BBox &bbox) const @@ -187,23 +213,50 @@ const Vector3 Box::normal(const Vector3 &P) const { - Vector3 N; - for (int i = 0; i < 3; i++) + register Vector3 l = P - L; + register Vector3 h = H - P; + + if (l.x < h.x) + h.x = -1; + else + { + l.x = h.x; + h.x = +1; + } + + if (l.y < h.y) + h.y = -1; + else { - if (P.cell[i] >= L.cell[i]-Eps && P.cell[i] <= L.cell[i]+Eps) - //if (P.cell[i] == L.cell[i]) - { - N.cell[i] = -1.0; - break; - } - if (P.cell[i] >= H.cell[i]-Eps && P.cell[i] <= H.cell[i]+Eps) - //if (P.cell[i] == H.cell[i]) - { - N.cell[i] = +1.0; - break; - } + l.y = h.y; + h.y = +1; + } + + if (l.z < h.z) + h.z = -1; + else + { + l.z = h.z; + h.z = +1; } - return N; + + if (l.x > l.y) + { + h.x = 0; + if (l.y > l.z) + h.y = 0; + else + h.z = 0; + } + else + { + h.y = 0; + if (l.x > l.z) + h.x = 0; + else + h.z = 0; + } + return h; } #ifdef TRI_PLUCKER