nuclear@0: #include nuclear@3: #include nuclear@2: #include nuclear@27: #include nuclear@2: #include nuclear@3: #ifndef __APPLE__ nuclear@3: #include nuclear@3: #else nuclear@3: #include nuclear@3: #endif nuclear@3: #include "rt.h" nuclear@12: #include "matrix.h" nuclear@22: #include "scene.h" nuclear@39: #include "ocl.h" John@49: #include "ogl.h" John@49: John@49: #ifdef _MSC_VER John@49: #define snprintf _snprintf John@49: #endif nuclear@0: nuclear@3: void cleanup(); nuclear@3: void disp(); nuclear@3: void reshape(int x, int y); nuclear@3: void keyb(unsigned char key, int x, int y); nuclear@3: void mouse(int bn, int status, int x, int y); nuclear@3: void motion(int x, int y); nuclear@47: bool capture(const char *namefmt); nuclear@2: bool write_ppm(const char *fname, float *fb, int xsz, int ysz); nuclear@2: nuclear@3: static int xsz, ysz; nuclear@3: static bool need_update = true; nuclear@3: nuclear@8: static float cam_theta, cam_phi = 25.0; nuclear@8: static float cam_dist = 10.0; nuclear@8: nuclear@32: static bool dbg_glrender = false; nuclear@27: static bool dbg_show_kdtree = false; nuclear@27: static bool dbg_show_obj = true; John@50: bool dbg_frame_time = true; nuclear@13: nuclear@13: static Scene scn; nuclear@39: static unsigned int tex; nuclear@12: nuclear@3: int main(int argc, char **argv) nuclear@0: { nuclear@3: glutInitWindowSize(800, 600); nuclear@3: glutInit(&argc, argv); nuclear@13: nuclear@13: int loaded = 0; nuclear@13: for(int i=1; i> 4) & 1) == ((j >> 4) & 1) ? 0xff0000 : 0xff00; nuclear@32: } nuclear@32: } nuclear@27: nuclear@39: glGenTextures(1, &tex); nuclear@39: glBindTexture(GL_TEXTURE_2D, tex); nuclear@3: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); nuclear@3: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); nuclear@3: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@3: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@39: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, test_pattern); nuclear@32: delete [] test_pattern; nuclear@2: nuclear@39: if(!init_opencl()) { nuclear@39: return 1; nuclear@39: } nuclear@39: nuclear@39: if(!init_renderer(xsz, ysz, &scn, tex)) { nuclear@39: return 1; nuclear@39: } nuclear@39: atexit(cleanup); nuclear@39: nuclear@3: glutMainLoop(); nuclear@0: return 0; nuclear@0: } nuclear@2: nuclear@3: void cleanup() nuclear@2: { nuclear@41: printf("destroying renderer ...\n"); nuclear@3: destroy_renderer(); nuclear@40: nuclear@41: printf("shutting down OpenCL ...\n"); nuclear@40: destroy_opencl(); nuclear@40: nuclear@41: printf("cleaning up OpenGL resources ...\n"); nuclear@41: glDeleteTextures(1, &tex); nuclear@3: } nuclear@2: nuclear@12: static Matrix4x4 mat, inv_mat, inv_trans; nuclear@12: nuclear@3: void disp() nuclear@3: { nuclear@8: glMatrixMode(GL_MODELVIEW); nuclear@8: glLoadIdentity(); nuclear@8: nuclear@3: if(need_update) { nuclear@12: glPushMatrix(); nuclear@12: glRotatef(-cam_theta, 0, 1, 0); nuclear@12: glRotatef(-cam_phi, 1, 0, 0); nuclear@12: glTranslatef(0, 0, cam_dist); nuclear@8: nuclear@12: glGetFloatv(GL_MODELVIEW_MATRIX, mat.m); nuclear@8: nuclear@12: inv_mat = mat; nuclear@12: inv_mat.invert(); nuclear@12: nuclear@12: /*inv_trans = inv_mat; nuclear@12: inv_trans.transpose();*/ nuclear@12: inv_trans = mat; nuclear@12: inv_trans.m[3] = inv_trans.m[7] = inv_trans.m[11] = 0.0; nuclear@12: inv_trans.m[12] = inv_trans.m[13] = inv_trans.m[14] = 0.0; nuclear@12: inv_trans.m[15] = 1.0; nuclear@12: nuclear@12: set_xform(mat.m, inv_trans.m); nuclear@8: glPopMatrix(); nuclear@8: nuclear@13: if(!dbg_glrender) { nuclear@13: if(!render()) { nuclear@13: exit(1); nuclear@13: } nuclear@13: need_update = false; nuclear@12: } nuclear@3: } nuclear@2: nuclear@12: if(dbg_glrender) { nuclear@12: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@12: glLoadMatrixf(inv_mat.m); nuclear@27: dbg_render_gl(&scn, dbg_show_kdtree, dbg_show_obj); nuclear@12: } else { nuclear@12: glEnable(GL_TEXTURE_2D); nuclear@22: glDisable(GL_LIGHTING); nuclear@2: nuclear@12: glBegin(GL_QUADS); nuclear@12: glColor3f(1, 1, 1); nuclear@12: glTexCoord2f(0, 1); glVertex2f(-1, -1); nuclear@12: glTexCoord2f(1, 1); glVertex2f(1, -1); nuclear@12: glTexCoord2f(1, 0); glVertex2f(1, 1); nuclear@12: glTexCoord2f(0, 0); glVertex2f(-1, 1); nuclear@12: glEnd(); nuclear@2: nuclear@12: glDisable(GL_TEXTURE_2D); nuclear@12: } nuclear@3: nuclear@3: glutSwapBuffers(); nuclear@3: } nuclear@3: nuclear@3: void reshape(int x, int y) nuclear@3: { nuclear@3: glViewport(0, 0, x, y); nuclear@3: nuclear@3: /* reallocate the framebuffer */ nuclear@3: /*delete [] fb; nuclear@3: fb = new float[x * y * 4]; nuclear@3: set_framebuffer(fb, x, y);*/ nuclear@3: } nuclear@3: nuclear@47: void idle() nuclear@47: { nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: nuclear@3: void keyb(unsigned char key, int x, int y) nuclear@3: { nuclear@3: switch(key) { nuclear@3: case 27: nuclear@3: exit(0); nuclear@3: nuclear@47: case '\b': nuclear@47: { nuclear@47: static bool busyloop; nuclear@47: nuclear@47: busyloop = !busyloop; nuclear@47: printf("%s busy-looping\n", busyloop ? "WARNING: enabling" : "disabling"); nuclear@47: glutIdleFunc(busyloop ? idle : 0); nuclear@47: } nuclear@3: break; nuclear@3: nuclear@12: case 'd': nuclear@12: dbg_glrender = !dbg_glrender; nuclear@12: if(dbg_glrender) { nuclear@21: printf("Debug OpenGL rendering\n"); nuclear@21: } else { nuclear@21: printf("Raytracing\n"); nuclear@12: } nuclear@3: glutPostRedisplay(); nuclear@3: break; nuclear@3: nuclear@27: case 'k': nuclear@27: dbg_show_kdtree = !dbg_show_kdtree; nuclear@27: if(dbg_glrender) { nuclear@27: glutPostRedisplay(); nuclear@27: } nuclear@27: break; nuclear@27: nuclear@27: case 'o': nuclear@27: dbg_show_obj = !dbg_show_obj; nuclear@27: if(dbg_glrender) { nuclear@27: glutPostRedisplay(); nuclear@27: } nuclear@27: break; nuclear@27: nuclear@47: case 's': nuclear@47: { nuclear@47: bool shadows = get_render_option_bool(ROPT_SHAD); nuclear@47: shadows = !shadows; nuclear@47: printf("%s shadows\n", shadows ? "enabling" : "disabling"); nuclear@47: set_render_option(ROPT_SHAD, shadows); nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: break; nuclear@47: nuclear@47: case 'r': nuclear@47: { nuclear@47: bool refl = get_render_option_bool(ROPT_REFL); nuclear@47: refl = !refl; nuclear@47: printf("%s reflections\n", refl ? "enabling" : "disabling"); nuclear@47: set_render_option(ROPT_REFL, refl); nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: break; nuclear@47: nuclear@47: case ']': nuclear@47: { nuclear@47: int iter = get_render_option_int(ROPT_ITER); nuclear@47: printf("setting max iterations: %d\n", iter + 1); nuclear@47: set_render_option(ROPT_ITER, iter + 1); nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: break; nuclear@47: nuclear@47: case '[': nuclear@47: { nuclear@47: int iter = get_render_option_int(ROPT_ITER); nuclear@47: if(iter-- > 0) { nuclear@47: printf("setting max iterations: %d\n", iter); nuclear@47: set_render_option(ROPT_ITER, iter); nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: } nuclear@47: break; nuclear@47: nuclear@47: case '`': nuclear@47: capture("shot%03d.ppm"); nuclear@47: break; nuclear@47: John@50: case 't': John@50: dbg_frame_time = !dbg_frame_time; John@50: break; John@50: nuclear@3: default: nuclear@3: break; nuclear@3: } nuclear@3: } nuclear@3: nuclear@8: static bool bnstate[32]; nuclear@8: static int prev_x, prev_y; nuclear@8: nuclear@3: void mouse(int bn, int state, int x, int y) nuclear@3: { nuclear@8: if(state == GLUT_DOWN) { nuclear@8: prev_x = x; nuclear@8: prev_y = y; nuclear@8: bnstate[bn] = true; nuclear@8: } else { nuclear@8: bnstate[bn] = false; nuclear@8: } nuclear@3: } nuclear@3: nuclear@8: #define ROT_SCALE 0.5 nuclear@8: #define PAN_SCALE 0.1 nuclear@8: nuclear@3: void motion(int x, int y) nuclear@3: { nuclear@8: int dx = x - prev_x; nuclear@8: int dy = y - prev_y; nuclear@8: prev_x = x; nuclear@8: prev_y = y; nuclear@8: nuclear@8: if(bnstate[0]) { nuclear@8: cam_theta += dx * ROT_SCALE; nuclear@8: cam_phi += dy * ROT_SCALE; nuclear@8: nuclear@12: if(cam_phi < -89) cam_phi = -89; nuclear@8: if(cam_phi > 89) cam_phi = 89; nuclear@8: nuclear@8: need_update = true; nuclear@8: glutPostRedisplay(); nuclear@8: } nuclear@8: if(bnstate[2]) { nuclear@8: cam_dist += dy * PAN_SCALE; nuclear@8: if(cam_dist < 0) cam_dist = 0; nuclear@8: nuclear@8: need_update = true; nuclear@8: glutPostRedisplay(); nuclear@8: } nuclear@2: } nuclear@2: nuclear@47: bool capture(const char *namefmt) nuclear@47: { nuclear@47: static int num; nuclear@47: char fname[256]; nuclear@47: nuclear@47: num++; nuclear@47: snprintf(fname, sizeof fname, namefmt, num); nuclear@47: printf("saving image %s\n", fname); nuclear@47: nuclear@47: float *pixels = new float[4 * xsz * ysz]; nuclear@47: glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, pixels); nuclear@47: nuclear@47: bool res = write_ppm("shot.ppm", pixels, xsz, ysz); nuclear@47: if(!res) { nuclear@47: num--; nuclear@47: } nuclear@47: delete [] pixels; nuclear@47: return res; nuclear@47: } nuclear@47: nuclear@2: bool write_ppm(const char *fname, float *fb, int xsz, int ysz) nuclear@2: { nuclear@2: FILE *fp; nuclear@2: nuclear@2: if(!(fp = fopen(fname, "wb"))) { nuclear@2: fprintf(stderr, "write_ppm: failed to open file %s for writing: %s\n", fname, strerror(errno)); nuclear@2: return false; nuclear@2: } nuclear@2: fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz); nuclear@2: nuclear@2: for(int i=0; i