ccdemos/realtime_dragon.cc
branchpyrit
changeset 24 d0d76e8a5203
child 28 ffe83ca074f3
--- /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);
+}