diff -r ffe83ca074f3 -r 574c34441a1c ccdemos/realtime_bunny.cc --- /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 + +#include "raytracer.h" +#include +#include +#include + +int w = 320; +int h = 200; +Float *render_buffer; + +Raytracer rt; +Camera cam; + +void load_ply(const char *filename, Material *mat, Float scale) +{ + vector vertices; + vector normals; + vector vertex_face_num; + ifstream f(filename); + string token = "a"; + if (!f.is_open()) + { + cout << "File not found: " << filename <> 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); +}