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
#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);}