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
--- 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
#########
--- 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
--- 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
--- 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();
}
--- 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 <stdlib.h>
+
#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));
--- 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;
--- 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;
--- 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)
--- 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
--- 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)
--- 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; };
--- 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
--- 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++) {
--- 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<Float> &allts) const
{
//allts = new vector<Float>();
@@ -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