Makefile: added help and distclean target, plus small fixes pyrit
authorRadek Brich <radek.brich@devl.cz>
Mon, 17 Dec 2007 22:03:50 +0100
branchpyrit
changeset 40 929aad02c5f2
parent 39 7079dcc3bd74
child 41 c1080cb5bd6d
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
Makefile
TODO
ccdemos/Makefile
ccdemos/common_sdl.h
ccdemos/realtime.cc
ccdemos/realtime_bunny.cc
ccdemos/realtime_dragon.cc
ccdemos/spheres_shadow.cc
demos/Makefile
demos/bunny.py
include/scene.h
models/Makefile
src/raytracer.cc
src/scene.cc
--- 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