new C++ demo: realtime_dragon.cc
class Container moved to its own source file (from kdtree.*)
new directory for models and Makefile which downloads and prepares them
fixed python module path in some forgotten demos
ShapeList moved to scene.h
--- a/.bzrignore Tue Dec 04 08:58:05 2007 +0100
+++ b/.bzrignore Wed Dec 05 18:54:23 2007 +0100
@@ -1,8 +1,11 @@
demos/ModulePath
demos/*.png
demos/kdtree.obj
-demos/*.ply
ccdemos/*.png
ccdemos/spheres_shadow
ccdemos/realtime
-bin/*
\ No newline at end of file
+ccdemos/realtime_dragon
+models/bunny
+models/happy
+models/dragon
+bin/*
--- a/Makefile Tue Dec 04 08:58:05 2007 +0100
+++ b/Makefile Wed Dec 05 18:54:23 2007 +0100
@@ -1,17 +1,20 @@
ROOT=$(shell pwd)
include config.mk
-all: python-module demos ccdemos
+all: python-module demos ccdemos models
python-module: libs-float
$(MAKE) -C src python-module
-demos: python-module
+demos: python-module models
$(MAKE) -C demos
-ccdemos: libs-float libs-double
+ccdemos: libs-float libs-double models
$(MAKE) -C ccdemos
+models:
+ $(MAKE) -C models
+
libs-float:
$(MAKE) -C src libs-float
--- a/ccdemos/Makefile Tue Dec 04 08:58:05 2007 +0100
+++ b/ccdemos/Makefile Wed Dec 05 18:54:23 2007 +0100
@@ -6,11 +6,14 @@
### Targets ###
-all: realtime spheres_shadow
+all: realtime realtime_dragon spheres_shadow
realtime: realtime.o libs-double
$(CXX) -o $@ $(ROOT)/bin/libs-double/*.o $< $(LDFLAGS) $(SDL_LDFLAGS)
+realtime_dragon: realtime_dragon.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
@@ -23,6 +26,9 @@
realtime.o: realtime.cc
$(CXX) -c -o $@ $(CCFLAGS) $(SDL_CCFLAGS) $< $(DEFS) -DPYRIT_DOUBLE
+realtime_dragon.o: realtime_dragon.cc
+ $(CXX) -c -o $@ $(CCFLAGS) $(SDL_CCFLAGS) $< $(DEFS) -DPYRIT_DOUBLE
+
image.o: image.c
$(CXX) -c -o $@ $*.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ccdemos/realtime_dragon.cc Wed Dec 05 18:54:23 2007 +0100
@@ -0,0 +1,218 @@
+#include <SDL.h>
+
+#include "raytracer.h"
+#include <iostream>
+#include <fstream>
+
+int w = 320;
+int h = 200;
+Float *render_buffer;
+
+Raytracer rt;
+Camera cam;
+
+void load_ply(const char *filename, Material *mat, Float scale)
+{
+ vector<Vector3> vertices;
+ 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;
+ if (token == "element")
+ {
+ f >> token;
+ if (token == "vertex")
+ f >> vertex_num;
+ if (token == "face")
+ f >> face_num;
+ }
+ }
+
+ // read vertices
+ Vector3 v;
+ while (vertex_num--)
+ {
+ f >> v.x >> v.y >> v.z;
+ v.x = -scale*v.x;
+ v.y = scale*v.y - 3.6;
+ v.z = -scale*v.z;
+ vertices.push_back(v);
+ }
+
+ // read faces
+ Triangle *face;
+ int num, v1, v2, v3;
+ while (face_num--)
+ {
+ f >> num;
+ if (num != 3)
+ {
+ printf("ply error: faces of %d vertices not supported", num);
+ return;
+ }
+ f >> v1 >> v2 >> v3;
+ face = new Triangle(vertices.at(v1), vertices.at(v2), vertices.at(v3), mat);
+ rt.addshape(face);
+ }
+
+ 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(2);
+ 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/dragon/dragon_vrip_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/Makefile Tue Dec 04 08:58:05 2007 +0100
+++ b/demos/Makefile Wed Dec 05 18:54:23 2007 +0100
@@ -11,6 +11,7 @@
reqs:
$(MAKE) -C .. libs-float python-module
-models: ;
+models:
+ $(MAKE) -C .. models
clean: ;
--- a/demos/buddha.py Tue Dec 04 08:58:05 2007 +0100
+++ b/demos/buddha.py Wed Dec 05 18:54:23 2007 +0100
@@ -4,7 +4,7 @@
# http://graphics.stanford.edu/data/3Dscanrep/
import sys
-sys.path.append("..")
+sys.path.append(open('ModulePath').read().strip())
from raytracer import Raytracer, Light, Sphere, Triangle, Material
import Image
@@ -42,7 +42,7 @@
rt = Raytracer()
mat = Material(colour=(0.9, 0.9, 0.9))
-LoadStanfordPlyFile(rt, mat ,"happy_vrip_res2.ply", 20.0)
+LoadStanfordPlyFile(rt, mat ,"../models/happy/happy_vrip_res2.ply", 20.0)
light = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.6))
rt.addlight(light)
--- a/demos/demo.py Tue Dec 04 08:58:05 2007 +0100
+++ b/demos/demo.py Wed Dec 05 18:54:23 2007 +0100
@@ -1,7 +1,7 @@
#!/usr/bin/python
import sys
-sys.path.append("..")
+sys.path.append(open('ModulePath').read().strip())
from raytracer import Raytracer, Material, Box, Sphere, Light
#, SphericalLight
--- a/demos/dragon.py Tue Dec 04 08:58:05 2007 +0100
+++ b/demos/dragon.py Wed Dec 05 18:54:23 2007 +0100
@@ -4,7 +4,7 @@
# http://graphics.stanford.edu/data/3Dscanrep/
import sys
-sys.path.append("..")
+sys.path.append(open('ModulePath').read().strip())
from raytracer import Raytracer, Light, Sphere, Triangle, Material
import Image
@@ -44,7 +44,7 @@
rt = Raytracer()
mat = Material(colour=(0.9, 0.9, 0.9))
-LoadStanfordPlyFile(rt, mat, "dragon_vrip.ply", 29.0)
+LoadStanfordPlyFile(rt, mat, "../models/dragon/dragon_vrip_res4.ply", 29.0)
light = Light(position=(-5.0, 2.0, 8.0), colour=(0.9, 0.3, 0.6))
rt.addlight(light)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/include/container.h Wed Dec 05 18:54:23 2007 +0100
@@ -0,0 +1,25 @@
+#ifndef CONTAINER_H
+#define CONTAINER_H
+
+#include <vector>
+
+#include "scene.h"
+
+using namespace std;
+
+class Container
+{
+protected:
+ BBox bbox;
+public:
+ ShapeList shapes;
+ Container(): bbox(), shapes() {};
+ virtual ~Container() {};
+ virtual void addShape(Shape* aShape);
+ //void addShapeNoExtend(Shape* aShape) { shapes.push_back(aShape); };
+ virtual Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray,
+ Float &nearest_distance);
+ virtual void optimize() {};
+};
+
+#endif
--- a/include/kdtree.h Tue Dec 04 08:58:05 2007 +0100
+++ b/include/kdtree.h Wed Dec 05 18:54:23 2007 +0100
@@ -1,33 +1,15 @@
#ifndef KDTREE_H
#define KDTREE_H
-#include <vector>
#include <iostream>
#include <fstream>
+#include "container.h"
+#include "vector.h"
#include "scene.h"
using namespace std;
-class ShapeList: public vector<Shape*>
-{
-};
-
-class Container
-{
-protected:
- BBox bbox;
-public:
- ShapeList shapes;
- Container(): bbox(), shapes() {};
- virtual ~Container() {};
- virtual void addShape(Shape* aShape);
- //void addShapeNoExtend(Shape* aShape) { shapes.push_back(aShape); };
- virtual Shape *nearest_intersection(const Shape *origin_shape, const Ray &ray,
- Float &nearest_distance);
- virtual void optimize() {};
-};
-
class KdNode
{
Float split;
--- a/include/scene.h Tue Dec 04 08:58:05 2007 +0100
+++ b/include/scene.h Wed Dec 05 18:54:23 2007 +0100
@@ -151,6 +151,10 @@
virtual BBox get_bbox() = 0;
};
+class ShapeList: public vector<Shape*>
+{
+};
+
class Sphere: public Shape
{
Float sqr_radius;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/models/Makefile Wed Dec 05 18:54:23 2007 +0100
@@ -0,0 +1,35 @@
+ifndef $(ROOT)
+ ROOT=$(shell pwd)/..
+endif
+
+
+all: models
+
+models: bunny happy dragon
+
+bunny:
+ wget ftp://graphics.stanford.edu/pub/3Dscanrep/bunny.tar.gz
+ tar xzf bunny.tar.gz
+ rm bunny.tar.gz
+ rm -rf bunny/data
+ mv bunny/reconstruction/* bunny
+ rmdir bunny/reconstruction
+
+happy:
+ wget ftp://graphics.stanford.edu/pub/3Dscanrep/happy/happy_recon.tar.gz
+ tar xzf happy_recon.tar.gz
+ rm happy_recon.tar.gz
+ mv happy_recon happy
+
+dragon:
+ wget ftp://graphics.stanford.edu/pub/3Dscanrep/dragon/dragon_recon.tar.gz
+ tar xzf dragon_recon.tar.gz
+ rm dragon_recon.tar.gz
+ mv dragon_recon dragon
+
+clean: ;
+
+distclean:
+ rm -rf bunny
+ rm -rf happy
+ rm -rf dragon
--- a/src/Makefile Tue Dec 04 08:58:05 2007 +0100
+++ b/src/Makefile Wed Dec 05 18:54:23 2007 +0100
@@ -6,7 +6,7 @@
vpath %.cc $(ROOT)/src
vpath %.h $(ROOT)/include
-LIBOBJS=raytracer.o scene.o noise.o kdtree.o
+LIBOBJS=raytracer.o scene.o noise.o container.o kdtree.o
CCFLAGS+=-I$(ROOT)/include
### Targets ###
@@ -43,6 +43,7 @@
matrix.o: matrix.cc matrix.h vector.h common.h
noise.o: noise.cc noise.h common.h
scene.o: scene.cc scene.h vector.h noise.h common.h
+container.o: container.cc container.h scene.h common.h
kdtree.o: kdtree.cc kdtree.h scene.h common.h
raytracer.o: raytracer.cc raytracer.h scene.h vector.h noise.h common.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/container.cc Wed Dec 05 18:54:23 2007 +0100
@@ -0,0 +1,31 @@
+#include "common.h"
+#include "container.h"
+
+void Container::addShape(Shape* aShape)
+{
+ shapes.push_back(aShape);
+ if (shapes.size() == 0) {
+ /* initialize bounding box */
+ bbox = aShape->get_bbox();
+ } else {
+ /* adjust bounding box */
+ BBox shapebb = aShape->get_bbox();
+ if (shapebb.L.x < bbox.L.x) bbox.L.x = shapebb.L.x;
+ if (shapebb.L.y < bbox.L.y) bbox.L.y = shapebb.L.y;
+ if (shapebb.L.z < bbox.L.z) bbox.L.z = shapebb.L.z;
+ if (shapebb.H.x > bbox.H.x) bbox.H.x = shapebb.H.x;
+ if (shapebb.H.y > bbox.H.y) bbox.H.y = shapebb.H.y;
+ if (shapebb.H.z > bbox.H.z) bbox.H.z = shapebb.H.z;
+ }
+};
+
+Shape *Container::nearest_intersection(const Shape *origin_shape, const Ray &ray,
+ Float &nearest_distance)
+{
+ Shape *nearest_shape = NULL;
+ ShapeList::iterator shape;
+ for (shape = shapes.begin(); shape != shapes.end(); shape++)
+ if (*shape != origin_shape && (*shape)->intersect(ray, nearest_distance))
+ nearest_shape = *shape;
+ return nearest_shape;
+}
--- a/src/kdtree.cc Tue Dec 04 08:58:05 2007 +0100
+++ b/src/kdtree.cc Wed Dec 05 18:54:23 2007 +0100
@@ -62,35 +62,6 @@
// ----------------------------------------
-void Container::addShape(Shape* aShape)
-{
- shapes.push_back(aShape);
- if (shapes.size() == 0) {
- /* initialize bounding box */
- bbox = aShape->get_bbox();
- } else {
- /* adjust bounding box */
- BBox shapebb = aShape->get_bbox();
- if (shapebb.L.x < bbox.L.x) bbox.L.x = shapebb.L.x;
- if (shapebb.L.y < bbox.L.y) bbox.L.y = shapebb.L.y;
- if (shapebb.L.z < bbox.L.z) bbox.L.z = shapebb.L.z;
- if (shapebb.H.x > bbox.H.x) bbox.H.x = shapebb.H.x;
- if (shapebb.H.y > bbox.H.y) bbox.H.y = shapebb.H.y;
- if (shapebb.H.z > bbox.H.z) bbox.H.z = shapebb.H.z;
- }
-};
-
-Shape *Container::nearest_intersection(const Shape *origin_shape, const Ray &ray,
- Float &nearest_distance)
-{
- Shape *nearest_shape = NULL;
- ShapeList::iterator shape;
- for (shape = shapes.begin(); shape != shapes.end(); shape++)
- if (*shape != origin_shape && (*shape)->intersect(ray, nearest_distance))
- nearest_shape = *shape;
- return nearest_shape;
-}
-
KdNode::~KdNode()
{
if (isLeaf())
--- a/src/scene.cc Tue Dec 04 08:58:05 2007 +0100
+++ b/src/scene.cc Wed Dec 05 18:54:23 2007 +0100
@@ -246,7 +246,7 @@
const Float lnd = 1.0f / (D[k] + nu * D[ku] + nv * D[kv]);
const Float t = (nd - O[k] - nu * O[ku] - nv * O[kv]) * lnd;
- if (!(t < dist && t > 0))
+ if (t < 0 || t >= dist)
return false;
Float hu = O[ku] + t * D[ku] - A[ku];