new C++ demo: realtime_bunny
obj/ply loading functions moved to *reader.py from Python demos
--- 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");