new C++ demo: realtime_bunny pyrit
authorRadek Brich <radek.brich@devl.cz>
Sat, 08 Dec 2007 14:07:42 +0100
branchpyrit
changeset 29 574c34441a1c
parent 28 ffe83ca074f3
child 30 33f95441790e
new C++ demo: realtime_bunny obj/ply loading functions moved to *reader.py from Python demos
.bzrignore
ccdemos/Makefile
ccdemos/realtime_bunny.cc
demos/buddha.py
demos/bunny.py
demos/dragon.py
demos/objreader.py
demos/plyreader.py
demos/triangles_monkey.py
demos/triangles_sphere.py
src/kdtree.cc
--- a/.bzrignore	Sat Dec 08 12:37:45 2007 +0100
+++ b/.bzrignore	Sat Dec 08 14:07:42 2007 +0100
@@ -5,6 +5,7 @@
 ccdemos/spheres_shadow
 ccdemos/realtime
 ccdemos/realtime_dragon
+ccdemos/realtime_bunny
 models/bunny
 models/happy
 models/dragon
--- a/ccdemos/Makefile	Sat Dec 08 12:37:45 2007 +0100
+++ b/ccdemos/Makefile	Sat Dec 08 14:07:42 2007 +0100
@@ -6,7 +6,7 @@
 
 
 ### Targets ###
-all: realtime realtime_dragon spheres_shadow
+all: realtime realtime_dragon realtime_bunny spheres_shadow
 
 realtime: realtime.o libs-double
 	$(CXX) -o $@ $(ROOT)/bin/libs-double/*.o $< $(LDFLAGS) $(SDL_LDFLAGS)
@@ -14,6 +14,9 @@
 realtime_dragon: realtime_dragon.o libs-double
 	$(CXX) -o $@ $(ROOT)/bin/libs-double/*.o $< $(LDFLAGS) $(SDL_LDFLAGS)
 
+realtime_bunny: realtime_bunny.o libs-double
+	$(CXX) -o $@ $(ROOT)/bin/libs-double/*.o $< $(LDFLAGS) $(SDL_LDFLAGS)
+
 spheres_shadow: spheres_shadow.o image.o libs-float
 	$(CXX) -o $@ $(ROOT)/bin/libs-float/*.o $< image.o $(LDFLAGS) -lpng
 
@@ -29,6 +32,9 @@
 realtime_dragon.o: realtime_dragon.cc
 	$(CXX) -c -o $@ $(CCFLAGS) $(SDL_CCFLAGS) $< $(DEFS) -DPYRIT_DOUBLE
 
+realtime_bunny.o: realtime_bunny.cc
+	$(CXX) -c -o $@ $(CCFLAGS) $(SDL_CCFLAGS) $< $(DEFS) -DPYRIT_DOUBLE
+
 image.o: image.c
 	$(CXX) -c -o $@ $*.c
 
@@ -36,4 +42,4 @@
 	$(CXX) -c -o $@ $*.cc $(CCFLAGS) $(DEFS)
 
 clean:
-	rm -f spheres_shadow realtime realtime_dragon *.o
+	rm -f spheres_shadow realtime realtime_dragon realtime_bunny *.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ccdemos/realtime_bunny.cc	Sat Dec 08 14:07:42 2007 +0100
@@ -0,0 +1,243 @@
+#include <SDL.h>
+
+#include "raytracer.h"
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+
+int w = 320;
+int h = 200;
+Float *render_buffer;
+
+Raytracer rt;
+Camera cam;
+
+void load_ply(const char *filename, Material *mat, Float scale)
+{
+	vector<NormalVertex*> vertices;
+	vector<Vector3> normals;
+	vector<int> vertex_face_num;
+	ifstream f(filename);
+	string token = "a";
+	if (!f.is_open())
+	{
+		cout << "File not found: " << filename <<endl;
+		exit(1);
+	}
+	// read header
+	int vertex_num, face_num;
+	while (token != "end_header")
+	{
+		f >> token;
+		cout << token << endl;
+		if (token == "element")
+		{
+			f >> token;
+			if (token == "vertex")
+				f >> vertex_num;
+			if (token == "face")
+				f >> face_num;
+		}
+		f.ignore(1000,'\n');
+	}
+
+	// read vertices
+	Vector3 P;
+	int num = vertex_num;
+	while (num--)
+	{
+		f >> P.x >> P.y >> P.z;
+		P.x = -scale*P.x - 1.0;
+		P.y = scale*P.y - 3.0;
+		P.z = scale*P.z;
+		vertices.push_back(new NormalVertex(P));
+		normals.push_back(Vector3());
+		vertex_face_num.push_back(0);
+		f.ignore(1000,'\n');
+	}
+
+	// read faces
+	Triangle *face;
+	int v1, v2, v3;
+	while (face_num--)
+	{
+		f >> num;
+		if (num != 3)
+		{
+			printf("ply error: faces of %d vertices not supported", num);
+			continue;
+		}
+		f >> v1 >> v2 >> v3;
+		face = new Triangle(vertices.at(v1), vertices.at(v3), vertices.at(v2), mat);
+		rt.addshape(face);
+		face->setSmooth();
+
+		normals.at(v1) += face->getNormal();
+		vertex_face_num.at(v1)++;
+		normals.at(v2) += face->getNormal();
+		vertex_face_num.at(v2)++;
+		normals.at(v3) += face->getNormal();
+		vertex_face_num.at(v3)++;
+		f.ignore(1000,'\n');
+	}
+
+	for (int i; i < vertex_num; i++)
+	{
+		normals.at(i) /= vertex_face_num.at(i);
+		normals.at(i).normalize();
+		vertices.at(i)->N = normals.at(i);
+	}
+
+	f.close();
+}
+
+void update(SDL_Surface *screen)
+{
+	rt.render(w, h, render_buffer);
+
+	if (SDL_MUSTLOCK(screen))
+		if (SDL_LockSurface(screen) < 0)
+			return;
+
+	Uint32 *bufp = (Uint32 *)screen->pixels;
+	unsigned char c[3];
+	for (Float *fd = render_buffer; fd != render_buffer + w*h*3; fd += 3)
+	{
+		for (int i = 0; i < 3; i++)
+		{
+			if (fd[i] > 1.0)
+				c[i] = 255;
+			else
+				c[i] = (unsigned char)(fd[i] * 255.0);
+		}
+		*bufp = SDL_MapRGB(screen->format, c[0], c[1], c[2]);
+		bufp++;
+	}
+
+	if (SDL_MUSTLOCK(screen))
+		SDL_UnlockSurface(screen);
+
+	if (screen->flags & SDL_DOUBLEBUF)
+		SDL_Flip(screen);
+	else
+		SDL_UpdateRect(screen, 0, 0, w, h);
+}
+
+int main()
+{
+	/* initialize SDL */
+	SDL_Surface *screen;
+
+	if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
+		fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
+		exit(1);
+	}
+
+	atexit(SDL_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());
+		exit(1);
+	}
+
+	/* initialize raytracer and prepare scene */
+	render_buffer = (Float *) malloc(w*h*3*sizeof(Float));
+
+	rt.setThreads(1);
+	rt.setMaxDepth(3);
+
+	KdTree top;
+	rt.setTop(&top);
+
+	Light light1(Vector3(-5.0, 2.0, 8.0), Colour(0.9, 0.3, 0.6));
+	light1.castShadows(false);
+	rt.addlight(&light1);
+
+	//Light light2(Vector3(-2.0, 10.0, 2.0), Colour(0.4, 0.6, 0.3));
+	//light2.castShadows(false);
+	//rt.addlight(&light2);
+
+	Material mat(Colour(0.9, 0.9, 0.9));
+	load_ply("../models/bunny/bun_zipper_res4.ply", &mat, 29);
+
+	rt.setCamera(&cam);
+	cam.setEye(Vector3(0,0,10));
+
+	/* build kd-tree */
+	top.setMaxDepth(100);
+	top.optimize();
+
+	/* loop... */
+	SDL_Event event;
+	bool quit = false;
+	Float roty = 0.0, rotx = 0.0, move = 0.0;
+	while (!quit)
+	{
+		while (SDL_PollEvent(&event))
+		{
+			switch (event.type) {
+				case SDL_VIDEORESIZE:
+					w = event.resize.w;
+					h = event.resize.h;
+					render_buffer = (Float *) realloc(render_buffer, w*h*3*sizeof(Float));
+					screen = SDL_SetVideoMode(w, h, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE);
+					break;
+				case SDL_KEYDOWN:
+					if (event.key.keysym.sym == SDLK_ESCAPE) {
+						quit = true;
+						break;
+					}
+					if (event.key.keysym.sym == SDLK_LEFT) {
+						roty = -0.01;
+						break;
+					}
+					if (event.key.keysym.sym == SDLK_RIGHT) {
+						roty = +0.01;
+						break;
+					}
+					if (event.key.keysym.sym == SDLK_DOWN) {
+						rotx = +0.01;
+						break;
+					}
+					if (event.key.keysym.sym == SDLK_UP) {
+						rotx = -0.01;
+						break;
+					}
+					if (event.key.keysym.sym == SDLK_w) {
+						move = +0.5;
+						break;
+					}
+					if (event.key.keysym.sym == SDLK_s) {
+						move = -0.5;
+						break;
+					}
+					break;
+				case SDL_KEYUP:
+					if (event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) {
+						roty = 0.0;
+						break;
+					}
+					if (event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN) {
+						rotx = 0.0;
+						break;
+					}
+					if (event.key.keysym.sym == SDLK_w || event.key.keysym.sym == SDLK_s) {
+							move = 0.0;
+							break;
+						}
+					break;
+				case SDL_QUIT:
+					quit = true;
+			}
+		}
+		cam.rotate(Quaternion(cos(roty),0,sin(roty),0).normalize());
+		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);
+		update(screen);
+	}
+
+	free(render_buffer);
+}
--- a/demos/buddha.py	Sat Dec 08 12:37:45 2007 +0100
+++ b/demos/buddha.py	Sat Dec 08 14:07:42 2007 +0100
@@ -7,42 +7,13 @@
 sys.path.append(open('ModulePath').read().strip())
 
 from raytracer import Raytracer, Light, Sphere, Triangle, Material
+from plyreader import LoadStanfordPlyFile
 import Image
 
-def LoadStanfordPlyFile(rt, mat, filename, scale):
-	vertices = []
-	fp = file(filename)
-	# read header
-	tokens = (0,)
-	while (tokens[0] != "end_header"):
-		tokens = fp.readline().split()
-		if (tokens[0] == "element"):
-			if (tokens[1] == "vertex"):
-				vertex_num = int(tokens[2])
-			if (tokens[1] == "face"):
-				face_num = int(tokens[2])
-
-	# read vertices
-	while (vertex_num):
-		tokens = fp.readline().split()
-		v = [scale*float(x) for x in tokens[0:3]]
-		v[1] = v[1]-3
-		vertices.append(tuple(v))
-		vertex_num -= 1
-
-	# read faces
-	while (face_num):
-		tokens = fp.readline().split()
-		if (tokens[0] != "3"):
-			print "ply warning: faces of %d vertices not supported" % tokens[0]
-		f = [vertices[int(x)] for x in tokens[1:4]]
-		face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat)
-		rt.addshape(face)
-		face_num -= 1
-
 rt = Raytracer()
 mat = Material(colour=(0.9, 0.9, 0.9))
-LoadStanfordPlyFile(rt, mat ,"../models/happy/happy_vrip_res2.ply", 20.0)
+LoadStanfordPlyFile(rt, "../models/happy/happy_vrip_res2.ply",
+	mat, smooth=True, scale=20.0, trans=(-3,0,0))
 
 light = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.6))
 rt.addlight(light)
--- a/demos/bunny.py	Sat Dec 08 12:37:45 2007 +0100
+++ b/demos/bunny.py	Sat Dec 08 14:07:42 2007 +0100
@@ -7,63 +7,13 @@
 sys.path.append(open('ModulePath').read().strip())
 
 from raytracer import Raytracer, Light, Sphere, Triangle, NormalVertex, Material
+from plyreader import LoadStanfordPlyFile
 import Image
 
-def LoadStanfordPlyFile(rt, mat, filename, scale):
-	vertices = []
-	normals = []
-	vertex_face_num = []
-	fp = file(filename)
-	# read header
-	tokens = (0,)
-	while (tokens[0] != "end_header"):
-		tokens = fp.readline().split()
-		if (tokens[0] == "element"):
-			if (tokens[1] == "vertex"):
-				vertex_num = int(tokens[2])
-			if (tokens[1] == "face"):
-				face_num = int(tokens[2])
-
-	# read vertices
-	num = vertex_num
-	while (num):
-		tokens = fp.readline().split()
-		v = [scale*float(x) for x in tokens[0:3]]
-		v[0] = -v[0]-1
-		v[1] = v[1]-3
-		vertices.append(NormalVertex(tuple(v)))
-		normals.append([0.,0.,0.])
-		vertex_face_num.append(0)
-		num -= 1
-
-	# read faces
-	while (face_num):
-		tokens = fp.readline().split()
-		if (tokens[0] != "3"):
-			print "ply warning: faces of %d vertices not supported" % tokens[0]
-		v = [vertices[int(x)] for x in tokens[1:4]]
-		face = Triangle(v[0], v[2], v[1], mat)
-		n = face.getNormal()
-		for x in tokens[1:4]:
-			for i in range(3):
-				normals[int(x)][i] += n[i]
-			vertex_face_num[int(x)] += 1
-		face.setSmooth()
-		rt.addshape(face)
-		face_num -= 1
-
-	# interpolate normals at vertices
-	num = 0
-	while (num < vertex_num):
-		if (vertex_face_num[num] > 0):
-			for i in range(3):
-				normals[num][i] /= vertex_face_num[num]
-		vertices[num].setNormal(tuple(normals[num]))
-		num += 1
-
 rt = Raytracer()
 mat = Material(colour=(0.9, 0.9, 0.9))
-LoadStanfordPlyFile(rt, mat, "../models/bunny/bun_zipper.ply", 29.0)
+LoadStanfordPlyFile(rt, "../models/bunny/bun_zipper.ply",
+	mat, smooth=True, scale=(-29.0, 29.0, 29.0), trans=(-1,-3,-3))
 
 light = Light(position=(-5.0, 2.0, 10.0), colour=(0.9, 0.3, 0.6))
 rt.addlight(light)
--- a/demos/dragon.py	Sat Dec 08 12:37:45 2007 +0100
+++ b/demos/dragon.py	Sat Dec 08 14:07:42 2007 +0100
@@ -7,44 +7,13 @@
 sys.path.append(open('ModulePath').read().strip())
 
 from raytracer import Raytracer, Light, Sphere, Triangle, Material
+from plyreader import LoadStanfordPlyFile
 import Image
 
-def LoadStanfordPlyFile(rt, mat, filename, scale):
-	vertices = []
-	fp = file(filename)
-	# read header
-	tokens = (0,)
-	while (tokens[0] != "end_header"):
-		tokens = fp.readline().split()
-		if (tokens[0] == "element"):
-			if (tokens[1] == "vertex"):
-				vertex_num = int(tokens[2])
-			if (tokens[1] == "face"):
-				face_num = int(tokens[2])
-
-	# read vertices
-	while (vertex_num):
-		tokens = fp.readline().split()
-		v = [scale*float(x) for x in tokens[0:3]]
-		v[0] = -v[0]
-		v[1] = v[1]-3.6
-		v[2] = -v[2]
-		vertices.append(tuple(v))
-		vertex_num -= 1
-
-	# read faces
-	while (face_num):
-		tokens = fp.readline().split()
-		if (tokens[0] != "3"):
-			print "ply warning: faces of %d vertices not supported" % tokens[0]
-		f = [vertices[int(x)] for x in tokens[1:4]]
-		face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat)
-		rt.addshape(face)
-		face_num -= 1
-
 rt = Raytracer()
 mat = Material(colour=(0.9, 0.9, 0.9))
-LoadStanfordPlyFile(rt, mat, "../models/dragon/dragon_vrip_res2.ply", 29.0)
+LoadStanfordPlyFile(rt, "../models/dragon/dragon_vrip_res2.ply",
+	mat, smooth=True, scale=(-29.0, 29.0, -29.0), trans=(0.0, -3.6, 0.0))
 
 light1 = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.2))
 rt.addlight(light1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/objreader.py	Sat Dec 08 14:07:42 2007 +0100
@@ -0,0 +1,17 @@
+from raytracer import Triangle, NormalVertex
+
+def LoadWavefrontObjFile(rt, filename, mat, scale):
+	vertices = []
+	fp = file(filename)
+	while True:
+		ln = fp.readline()
+		if ln == "":
+			break;
+		ln = ln.split()
+		if ln[0] == "v":
+			v = [scale*float(x) for x in ln[1:4]]
+			vertices.append(tuple(v))
+		if ln[0] == "f":
+			f = [vertices[int(x)-1] for x in ln[1:4]]
+			face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat)
+			rt.addshape(face)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/plyreader.py	Sat Dec 08 14:07:42 2007 +0100
@@ -0,0 +1,57 @@
+from raytracer import Triangle, NormalVertex
+
+def LoadStanfordPlyFile(rt, filename, mat, smooth, scale=(1,1,1), trans=(0,0,0)):
+	if (type(scale) == float or type(scale) == int):
+		scale = (scale,)*3
+	vertices = []
+	normals = []
+	vertex_face_num = []
+	fp = file(filename)
+	# read header
+	tokens = (0,)
+	while (tokens[0] != "end_header"):
+		tokens = fp.readline().split()
+		if (tokens[0] == "element"):
+			if (tokens[1] == "vertex"):
+				vertex_num = int(tokens[2])
+			if (tokens[1] == "face"):
+				face_num = int(tokens[2])
+
+	# read vertices
+	num = vertex_num
+	while (num):
+		tokens = fp.readline().split()
+		v = [float(x) for x in tokens[0:3]]
+		v[0] = scale[0]*v[0] + trans[0]
+		v[1] = scale[1]*v[1] + trans[1]
+		v[2] = scale[2]*v[2] + trans[2]
+		vertices.append(NormalVertex(tuple(v)))
+		normals.append([0.,0.,0.])
+		vertex_face_num.append(0)
+		num -= 1
+
+	# read faces
+	while (face_num):
+		tokens = fp.readline().split()
+		if (tokens[0] != "3"):
+			print "ply warning: faces of %d vertices not supported" % tokens[0]
+		v = [vertices[int(x)] for x in tokens[1:4]]
+		face = Triangle(v[0], v[2], v[1], mat)
+		n = face.getNormal()
+		for x in tokens[1:4]:
+			for i in range(3):
+				normals[int(x)][i] += n[i]
+			vertex_face_num[int(x)] += 1
+		if (smooth):
+			face.setSmooth()
+		rt.addshape(face)
+		face_num -= 1
+
+	# interpolate normals at vertices
+	num = 0
+	while (num < vertex_num):
+		if (vertex_face_num[num] > 0):
+			for i in range(3):
+				normals[num][i] /= vertex_face_num[num]
+		vertices[num].setNormal(tuple(normals[num]))
+		num += 1
--- a/demos/triangles_monkey.py	Sat Dec 08 12:37:45 2007 +0100
+++ b/demos/triangles_monkey.py	Sat Dec 08 14:07:42 2007 +0100
@@ -3,28 +3,13 @@
 import sys
 sys.path.append(open('ModulePath').read().strip())
 
-from raytracer import Raytracer, Light, Sphere, Triangle, Material
+from raytracer import Raytracer, Light, Sphere, Triangle, NormalVertex, Material
+from objreader import LoadWavefrontObjFile
 import Image
 
-def LoadWavefrontObjFile(rt, mat, filename):
-	vertices = []
-	fp = file(filename)
-	while True:
-		ln = fp.readline()
-		if ln == "":
-			break;
-		ln = ln.split()
-		if ln[0] == "v":
-			v = [1.5*float(x) for x in ln[1:4]]
-			vertices.append(tuple(v))
-		if ln[0] == "f":
-			f = [vertices[int(x)-1] for x in ln[1:4]]
-			face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat)
-			rt.addshape(face)
-
 rt = Raytracer()
 mat = Material(colour=(0.9, 0.9, 0.9))
-LoadWavefrontObjFile(rt, mat, "monkey.obj")
+LoadWavefrontObjFile(rt, "monkey.obj", mat, 1.5)
 
 light = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.6))
 rt.addlight(light)
--- a/demos/triangles_sphere.py	Sat Dec 08 12:37:45 2007 +0100
+++ b/demos/triangles_sphere.py	Sat Dec 08 14:07:42 2007 +0100
@@ -4,27 +4,12 @@
 sys.path.append(open('ModulePath').read().strip())
 
 from raytracer import Raytracer, Light, Sphere, Triangle, NormalVertex, Material
+from objreader import LoadWavefrontObjFile
 import Image
 
-def LoadWavefrontObjFile(rt, mat, filename):
-	vertices = []
-	fp = file(filename)
-	while True:
-		ln = fp.readline()
-		if ln == "":
-			break;
-		ln = ln.split()
-		if ln[0] == "v":
-			v = [1.5*float(x) for x in ln[1:4]]
-			vertices.append(tuple(v))
-		if ln[0] == "f":
-			f = [vertices[int(x)-1] for x in ln[1:4]]
-			face = Triangle(NormalVertex(f[0]), NormalVertex(f[1]), NormalVertex(f[2]), mat)
-			rt.addshape(face)
-
 rt = Raytracer()
 mat = Material(colour=(0.9, 0.9, 0.9))
-LoadWavefrontObjFile(rt, mat, "sphere.obj")
+LoadWavefrontObjFile(rt, "sphere.obj", mat, 1.5)
 
 light1 = Light(position=(0.0, 2.0, 6.0), colour=(0.9, 0.3, 0.6))
 light1.castshadows(False);
--- a/src/kdtree.cc	Sat Dec 08 12:37:45 2007 +0100
+++ b/src/kdtree.cc	Sat Dec 08 14:07:42 2007 +0100
@@ -183,7 +183,7 @@
 		return;
 	}
 
-#if 1
+#if 0
 // export kd-tree as .obj for visualization
 // this would be hard to reconstruct later
 	static ofstream F("kdtree.obj");