clray

annotate src/clray.cc @ 50:d3c46803242e

- added button to stop the timing messages
author John Tsiombikas
date Tue, 31 Aug 2010 02:54:37 +0100
parents 1ae68d46cfda
children 55b30d8b6805
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@3 2 #include <stdlib.h>
nuclear@2 3 #include <string.h>
nuclear@27 4 #include <ctype.h>
nuclear@2 5 #include <errno.h>
nuclear@3 6 #ifndef __APPLE__
nuclear@3 7 #include <GL/glut.h>
nuclear@3 8 #else
nuclear@3 9 #include <GLUT/glut.h>
nuclear@3 10 #endif
nuclear@3 11 #include "rt.h"
nuclear@12 12 #include "matrix.h"
nuclear@22 13 #include "scene.h"
nuclear@39 14 #include "ocl.h"
John@49 15 #include "ogl.h"
John@49 16
John@49 17 #ifdef _MSC_VER
John@49 18 #define snprintf _snprintf
John@49 19 #endif
nuclear@0 20
nuclear@3 21 void cleanup();
nuclear@3 22 void disp();
nuclear@3 23 void reshape(int x, int y);
nuclear@3 24 void keyb(unsigned char key, int x, int y);
nuclear@3 25 void mouse(int bn, int status, int x, int y);
nuclear@3 26 void motion(int x, int y);
nuclear@47 27 bool capture(const char *namefmt);
nuclear@2 28 bool write_ppm(const char *fname, float *fb, int xsz, int ysz);
nuclear@2 29
nuclear@3 30 static int xsz, ysz;
nuclear@3 31 static bool need_update = true;
nuclear@3 32
nuclear@8 33 static float cam_theta, cam_phi = 25.0;
nuclear@8 34 static float cam_dist = 10.0;
nuclear@8 35
nuclear@32 36 static bool dbg_glrender = false;
nuclear@27 37 static bool dbg_show_kdtree = false;
nuclear@27 38 static bool dbg_show_obj = true;
John@50 39 bool dbg_frame_time = true;
nuclear@13 40
nuclear@13 41 static Scene scn;
nuclear@39 42 static unsigned int tex;
nuclear@12 43
nuclear@3 44 int main(int argc, char **argv)
nuclear@0 45 {
nuclear@3 46 glutInitWindowSize(800, 600);
nuclear@3 47 glutInit(&argc, argv);
nuclear@13 48
nuclear@13 49 int loaded = 0;
nuclear@13 50 for(int i=1; i<argc; i++) {
nuclear@27 51 if(argv[i][0] == '-' && argv[i][2] == 0) {
nuclear@27 52 switch(argv[i][1]) {
nuclear@27 53 case 'i':
nuclear@27 54 if(!argv[++i] || !isdigit(argv[i][0])) {
nuclear@27 55 fprintf(stderr, "-i must be followed by the intersection cost\n");
nuclear@27 56 return 1;
nuclear@27 57 }
nuclear@27 58
nuclear@27 59 set_accel_param(ACCEL_PARAM_COST_INTERSECT, atoi(argv[i]));
nuclear@27 60 break;
nuclear@27 61
nuclear@27 62 case 't':
nuclear@27 63 if(!argv[++i] || !isdigit(argv[i][0])) {
nuclear@27 64 fprintf(stderr, "-t must be followed by the traversal cost\n");
nuclear@27 65 return 1;
nuclear@27 66 }
nuclear@27 67
nuclear@27 68 set_accel_param(ACCEL_PARAM_COST_TRAVERSE, atoi(argv[i]));
nuclear@27 69 break;
nuclear@27 70
nuclear@27 71 case 'c':
nuclear@27 72 if(!argv[++i] || !isdigit(argv[i][0])) {
nuclear@27 73 fprintf(stderr, "-c must be followed by the max number of items per leaf node\n");
nuclear@27 74 return 1;
nuclear@27 75 }
nuclear@27 76
nuclear@27 77 set_accel_param(ACCEL_PARAM_MAX_NODE_ITEMS, atoi(argv[i]));
nuclear@27 78 break;
nuclear@27 79
nuclear@46 80 case 'd':
nuclear@46 81 dbg_glrender = true;
nuclear@46 82 break;
nuclear@46 83
nuclear@27 84 default:
nuclear@27 85 fprintf(stderr, "unrecognized option: %s\n", argv[i]);
nuclear@27 86 return 1;
nuclear@27 87 }
nuclear@27 88 } else {
nuclear@27 89 if(!scn.load(argv[i])) {
nuclear@27 90 fprintf(stderr, "failed to load scene: %s\n", argv[i]);
nuclear@27 91 return false;
nuclear@27 92 }
nuclear@27 93 loaded++;
nuclear@13 94 }
nuclear@13 95 }
nuclear@13 96
nuclear@13 97 if(!loaded) {
nuclear@13 98 fprintf(stderr, "you must specify a scene file to load\n");
nuclear@13 99 return false;
nuclear@13 100 }
nuclear@13 101 if(!scn.get_num_faces()) {
nuclear@13 102 fprintf(stderr, "didn't load any polygons\n");
nuclear@13 103 return false;
nuclear@13 104 }
nuclear@13 105
nuclear@18 106 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
nuclear@3 107 glutCreateWindow("OpenCL Raytracer");
nuclear@0 108
nuclear@3 109 xsz = glutGet(GLUT_WINDOW_WIDTH);
nuclear@3 110 ysz = glutGet(GLUT_WINDOW_HEIGHT);
nuclear@2 111
nuclear@3 112 glutDisplayFunc(disp);
nuclear@3 113 glutReshapeFunc(reshape);
nuclear@3 114 glutKeyboardFunc(keyb);
nuclear@3 115 glutMouseFunc(mouse);
nuclear@3 116 glutMotionFunc(motion);
nuclear@0 117
nuclear@32 118 unsigned int *test_pattern = new unsigned int[xsz * ysz];
nuclear@32 119 for(int i=0; i<ysz; i++) {
nuclear@32 120 for(int j=0; j<xsz; j++) {
nuclear@32 121 test_pattern[i * xsz + j] = ((i >> 4) & 1) == ((j >> 4) & 1) ? 0xff0000 : 0xff00;
nuclear@32 122 }
nuclear@32 123 }
nuclear@27 124
nuclear@39 125 glGenTextures(1, &tex);
nuclear@39 126 glBindTexture(GL_TEXTURE_2D, tex);
nuclear@3 127 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
nuclear@3 128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
nuclear@3 129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@3 130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@39 131 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, test_pattern);
nuclear@32 132 delete [] test_pattern;
nuclear@2 133
nuclear@39 134 if(!init_opencl()) {
nuclear@39 135 return 1;
nuclear@39 136 }
nuclear@39 137
nuclear@39 138 if(!init_renderer(xsz, ysz, &scn, tex)) {
nuclear@39 139 return 1;
nuclear@39 140 }
nuclear@39 141 atexit(cleanup);
nuclear@39 142
nuclear@3 143 glutMainLoop();
nuclear@0 144 return 0;
nuclear@0 145 }
nuclear@2 146
nuclear@3 147 void cleanup()
nuclear@2 148 {
nuclear@41 149 printf("destroying renderer ...\n");
nuclear@3 150 destroy_renderer();
nuclear@40 151
nuclear@41 152 printf("shutting down OpenCL ...\n");
nuclear@40 153 destroy_opencl();
nuclear@40 154
nuclear@41 155 printf("cleaning up OpenGL resources ...\n");
nuclear@41 156 glDeleteTextures(1, &tex);
nuclear@3 157 }
nuclear@2 158
nuclear@12 159 static Matrix4x4 mat, inv_mat, inv_trans;
nuclear@12 160
nuclear@3 161 void disp()
nuclear@3 162 {
nuclear@8 163 glMatrixMode(GL_MODELVIEW);
nuclear@8 164 glLoadIdentity();
nuclear@8 165
nuclear@3 166 if(need_update) {
nuclear@12 167 glPushMatrix();
nuclear@12 168 glRotatef(-cam_theta, 0, 1, 0);
nuclear@12 169 glRotatef(-cam_phi, 1, 0, 0);
nuclear@12 170 glTranslatef(0, 0, cam_dist);
nuclear@8 171
nuclear@12 172 glGetFloatv(GL_MODELVIEW_MATRIX, mat.m);
nuclear@8 173
nuclear@12 174 inv_mat = mat;
nuclear@12 175 inv_mat.invert();
nuclear@12 176
nuclear@12 177 /*inv_trans = inv_mat;
nuclear@12 178 inv_trans.transpose();*/
nuclear@12 179 inv_trans = mat;
nuclear@12 180 inv_trans.m[3] = inv_trans.m[7] = inv_trans.m[11] = 0.0;
nuclear@12 181 inv_trans.m[12] = inv_trans.m[13] = inv_trans.m[14] = 0.0;
nuclear@12 182 inv_trans.m[15] = 1.0;
nuclear@12 183
nuclear@12 184 set_xform(mat.m, inv_trans.m);
nuclear@8 185 glPopMatrix();
nuclear@8 186
nuclear@13 187 if(!dbg_glrender) {
nuclear@13 188 if(!render()) {
nuclear@13 189 exit(1);
nuclear@13 190 }
nuclear@13 191 need_update = false;
nuclear@12 192 }
nuclear@3 193 }
nuclear@2 194
nuclear@12 195 if(dbg_glrender) {
nuclear@12 196 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@12 197 glLoadMatrixf(inv_mat.m);
nuclear@27 198 dbg_render_gl(&scn, dbg_show_kdtree, dbg_show_obj);
nuclear@12 199 } else {
nuclear@12 200 glEnable(GL_TEXTURE_2D);
nuclear@22 201 glDisable(GL_LIGHTING);
nuclear@2 202
nuclear@12 203 glBegin(GL_QUADS);
nuclear@12 204 glColor3f(1, 1, 1);
nuclear@12 205 glTexCoord2f(0, 1); glVertex2f(-1, -1);
nuclear@12 206 glTexCoord2f(1, 1); glVertex2f(1, -1);
nuclear@12 207 glTexCoord2f(1, 0); glVertex2f(1, 1);
nuclear@12 208 glTexCoord2f(0, 0); glVertex2f(-1, 1);
nuclear@12 209 glEnd();
nuclear@2 210
nuclear@12 211 glDisable(GL_TEXTURE_2D);
nuclear@12 212 }
nuclear@3 213
nuclear@3 214 glutSwapBuffers();
nuclear@3 215 }
nuclear@3 216
nuclear@3 217 void reshape(int x, int y)
nuclear@3 218 {
nuclear@3 219 glViewport(0, 0, x, y);
nuclear@3 220
nuclear@3 221 /* reallocate the framebuffer */
nuclear@3 222 /*delete [] fb;
nuclear@3 223 fb = new float[x * y * 4];
nuclear@3 224 set_framebuffer(fb, x, y);*/
nuclear@3 225 }
nuclear@3 226
nuclear@47 227 void idle()
nuclear@47 228 {
nuclear@47 229 need_update = true;
nuclear@47 230 glutPostRedisplay();
nuclear@47 231 }
nuclear@47 232
nuclear@3 233 void keyb(unsigned char key, int x, int y)
nuclear@3 234 {
nuclear@3 235 switch(key) {
nuclear@3 236 case 27:
nuclear@3 237 exit(0);
nuclear@3 238
nuclear@47 239 case '\b':
nuclear@47 240 {
nuclear@47 241 static bool busyloop;
nuclear@47 242
nuclear@47 243 busyloop = !busyloop;
nuclear@47 244 printf("%s busy-looping\n", busyloop ? "WARNING: enabling" : "disabling");
nuclear@47 245 glutIdleFunc(busyloop ? idle : 0);
nuclear@47 246 }
nuclear@3 247 break;
nuclear@3 248
nuclear@12 249 case 'd':
nuclear@12 250 dbg_glrender = !dbg_glrender;
nuclear@12 251 if(dbg_glrender) {
nuclear@21 252 printf("Debug OpenGL rendering\n");
nuclear@21 253 } else {
nuclear@21 254 printf("Raytracing\n");
nuclear@12 255 }
nuclear@3 256 glutPostRedisplay();
nuclear@3 257 break;
nuclear@3 258
nuclear@27 259 case 'k':
nuclear@27 260 dbg_show_kdtree = !dbg_show_kdtree;
nuclear@27 261 if(dbg_glrender) {
nuclear@27 262 glutPostRedisplay();
nuclear@27 263 }
nuclear@27 264 break;
nuclear@27 265
nuclear@27 266 case 'o':
nuclear@27 267 dbg_show_obj = !dbg_show_obj;
nuclear@27 268 if(dbg_glrender) {
nuclear@27 269 glutPostRedisplay();
nuclear@27 270 }
nuclear@27 271 break;
nuclear@27 272
nuclear@47 273 case 's':
nuclear@47 274 {
nuclear@47 275 bool shadows = get_render_option_bool(ROPT_SHAD);
nuclear@47 276 shadows = !shadows;
nuclear@47 277 printf("%s shadows\n", shadows ? "enabling" : "disabling");
nuclear@47 278 set_render_option(ROPT_SHAD, shadows);
nuclear@47 279 need_update = true;
nuclear@47 280 glutPostRedisplay();
nuclear@47 281 }
nuclear@47 282 break;
nuclear@47 283
nuclear@47 284 case 'r':
nuclear@47 285 {
nuclear@47 286 bool refl = get_render_option_bool(ROPT_REFL);
nuclear@47 287 refl = !refl;
nuclear@47 288 printf("%s reflections\n", refl ? "enabling" : "disabling");
nuclear@47 289 set_render_option(ROPT_REFL, refl);
nuclear@47 290 need_update = true;
nuclear@47 291 glutPostRedisplay();
nuclear@47 292 }
nuclear@47 293 break;
nuclear@47 294
nuclear@47 295 case ']':
nuclear@47 296 {
nuclear@47 297 int iter = get_render_option_int(ROPT_ITER);
nuclear@47 298 printf("setting max iterations: %d\n", iter + 1);
nuclear@47 299 set_render_option(ROPT_ITER, iter + 1);
nuclear@47 300 need_update = true;
nuclear@47 301 glutPostRedisplay();
nuclear@47 302 }
nuclear@47 303 break;
nuclear@47 304
nuclear@47 305 case '[':
nuclear@47 306 {
nuclear@47 307 int iter = get_render_option_int(ROPT_ITER);
nuclear@47 308 if(iter-- > 0) {
nuclear@47 309 printf("setting max iterations: %d\n", iter);
nuclear@47 310 set_render_option(ROPT_ITER, iter);
nuclear@47 311 need_update = true;
nuclear@47 312 glutPostRedisplay();
nuclear@47 313 }
nuclear@47 314 }
nuclear@47 315 break;
nuclear@47 316
nuclear@47 317 case '`':
nuclear@47 318 capture("shot%03d.ppm");
nuclear@47 319 break;
nuclear@47 320
John@50 321 case 't':
John@50 322 dbg_frame_time = !dbg_frame_time;
John@50 323 break;
John@50 324
nuclear@3 325 default:
nuclear@3 326 break;
nuclear@3 327 }
nuclear@3 328 }
nuclear@3 329
nuclear@8 330 static bool bnstate[32];
nuclear@8 331 static int prev_x, prev_y;
nuclear@8 332
nuclear@3 333 void mouse(int bn, int state, int x, int y)
nuclear@3 334 {
nuclear@8 335 if(state == GLUT_DOWN) {
nuclear@8 336 prev_x = x;
nuclear@8 337 prev_y = y;
nuclear@8 338 bnstate[bn] = true;
nuclear@8 339 } else {
nuclear@8 340 bnstate[bn] = false;
nuclear@8 341 }
nuclear@3 342 }
nuclear@3 343
nuclear@8 344 #define ROT_SCALE 0.5
nuclear@8 345 #define PAN_SCALE 0.1
nuclear@8 346
nuclear@3 347 void motion(int x, int y)
nuclear@3 348 {
nuclear@8 349 int dx = x - prev_x;
nuclear@8 350 int dy = y - prev_y;
nuclear@8 351 prev_x = x;
nuclear@8 352 prev_y = y;
nuclear@8 353
nuclear@8 354 if(bnstate[0]) {
nuclear@8 355 cam_theta += dx * ROT_SCALE;
nuclear@8 356 cam_phi += dy * ROT_SCALE;
nuclear@8 357
nuclear@12 358 if(cam_phi < -89) cam_phi = -89;
nuclear@8 359 if(cam_phi > 89) cam_phi = 89;
nuclear@8 360
nuclear@8 361 need_update = true;
nuclear@8 362 glutPostRedisplay();
nuclear@8 363 }
nuclear@8 364 if(bnstate[2]) {
nuclear@8 365 cam_dist += dy * PAN_SCALE;
nuclear@8 366 if(cam_dist < 0) cam_dist = 0;
nuclear@8 367
nuclear@8 368 need_update = true;
nuclear@8 369 glutPostRedisplay();
nuclear@8 370 }
nuclear@2 371 }
nuclear@2 372
nuclear@47 373 bool capture(const char *namefmt)
nuclear@47 374 {
nuclear@47 375 static int num;
nuclear@47 376 char fname[256];
nuclear@47 377
nuclear@47 378 num++;
nuclear@47 379 snprintf(fname, sizeof fname, namefmt, num);
nuclear@47 380 printf("saving image %s\n", fname);
nuclear@47 381
nuclear@47 382 float *pixels = new float[4 * xsz * ysz];
nuclear@47 383 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, pixels);
nuclear@47 384
nuclear@47 385 bool res = write_ppm("shot.ppm", pixels, xsz, ysz);
nuclear@47 386 if(!res) {
nuclear@47 387 num--;
nuclear@47 388 }
nuclear@47 389 delete [] pixels;
nuclear@47 390 return res;
nuclear@47 391 }
nuclear@47 392
nuclear@2 393 bool write_ppm(const char *fname, float *fb, int xsz, int ysz)
nuclear@2 394 {
nuclear@2 395 FILE *fp;
nuclear@2 396
nuclear@2 397 if(!(fp = fopen(fname, "wb"))) {
nuclear@2 398 fprintf(stderr, "write_ppm: failed to open file %s for writing: %s\n", fname, strerror(errno));
nuclear@2 399 return false;
nuclear@2 400 }
nuclear@2 401 fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
nuclear@2 402
nuclear@2 403 for(int i=0; i<xsz * ysz * 4; i++) {
nuclear@2 404 if(i % 4 == 3) continue;
nuclear@2 405
nuclear@2 406 unsigned char c = (unsigned char)(fb[i] * 255.0);
nuclear@2 407 fputc(c, fp);
nuclear@2 408 }
nuclear@2 409 fclose(fp);
nuclear@2 410 return true;
nuclear@2 411 }