new space partitioning structure: octree
realtime_bunny updated to use octree
plus other files updated to be container type independent (only user programs are supposed to include and use special containers)
#include <SDL.h>#include "raytracer.h"#include "kdtree.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<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; if (token == "element") { f >> token; if (token == "vertex") f >> vertex_num; if (token == "face") f >> face_num; } } // read vertices Vector3 P; int num = vertex_num; while (num--) { f >> P.x >> P.y >> P.z; P.x = -scale*P.x; P.y = scale*P.y - 3.6; P.z = -scale*P.z; vertices.push_back(new NormalVertex(P)); normals.push_back(Vector3()); vertex_face_num.push_back(0); } // 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); return; } f >> v1 >> v2 >> v3; face = new Triangle(vertices.at(v1), vertices.at(v2), vertices.at(v3), 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)++; } 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/dragon/dragon_vrip_res4.ply", &mat, 29); rt.setCamera(&cam); cam.setEye(Vector3(0,0,10)); /* build kd-tree */ top.setMaxDepth(30); 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);}