Subversion Repositories gelsvn

Rev

Rev 417 | Rev 596 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
305 jab 1
#include <iostream>
2
#include <vector>
3
#include <algorithm>
4
#include <cmath>
5
 
322 jab 6
#include "GLGraphics/gel_glut.h"
305 jab 7
 
8
#include "CGLA/Vec2f.h"
9
#include "CGLA/Vec3i.h"
10
#include "CGLA/Vec3f.h"
11
#include "CGLA/Vec3d.h"
12
#include "CGLA/Mat4x4f.h"
309 jab 13
 
14
#include "HMesh/build_manifold.h"
305 jab 15
#include "Geometry/TriMesh.h"
16
#include "Geometry/obj_load.h"
17
#include "Geometry/Ray.h"
18
#include "Geometry/BSPTree.h"
309 jab 19
#include "GLGraphics/GLViewController.h"
305 jab 20
 
309 jab 21
#include "Geometry/build_bbtree.h"
22
#include "Geometry/AABox.h"
23
#include "Geometry/OBox.h"
24
#include "Util/Timer.h"
305 jab 25
#include "Camera.h"
26
 
313 jrf 27
#define USE_BSP
309 jab 28
 
305 jab 29
using namespace std;
30
using namespace CGLA;
31
using namespace Geometry;
309 jab 32
using namespace HMesh;
305 jab 33
using namespace GLGraphics;
34
 
309 jab 35
/*
36
 * TODO: 
37
 * - BBOX remove HMesh dependency - that is crazy.
38
 * - BBox visit child nodes in order of how far away the intersection point on
39
 *        the bbox is. Closest nodes visited first. Cull nodes farther than
40
 *        an actual intersection point.
41
 * - BBox Smooth interpolation of triangle normals. Straightforward.
42
 */
43
 
44
 
305 jab 45
namespace
46
{
310 jrf 47
  const int MAX_OBJECTS = 4;   // Maximum number of triangles in a BSP tree node
305 jab 48
  const int MAX_LEVEL = 20;    // Maximum number of BSP tree subdivisions
49
 
50
  const unsigned int TEX_SIZE = 512;
51
 
52
  bool raytrace = false;
53
  bool done = false;
54
  bool shadow = false;
55
 
56
  unsigned int winx = TEX_SIZE;     // Screen width
57
  unsigned int winy = TEX_SIZE;     // Screen height
58
 
59
  unsigned int PIXEL_SUBDIVS = 1;
60
 
61
  int mouse_state = GLUT_UP;
62
  int mouse_button = 0;
63
  int spin_timer = 20;
64
 
310 jrf 65
  GLViewController *vctrl;
305 jab 66
 
67
  TriMesh mesh;
322 jab 68
  vector<const TriMesh*> mesh_vector(1, &mesh);
305 jab 69
  vector<Mat4x4f> transforms(1, identity_Mat4x4f());
70
 
71
  double light_pow = 1.0;
72
  Vec3f light_dir = normalize(Vec3f(1.0, 1.0, 1.0));
73
  Vec3d background(0.8, 0.9, 1.0);
74
 
75
  BSPTree tree;
76
  Camera* cam;
77
 
78
  Vec3f image[TEX_SIZE][TEX_SIZE];
79
  unsigned int image_tex;
80
 
81
  // Function to generate a random number between 0 and 1.
417 jrf 82
  // gel_rand() returns a random number ranging from 0 to GEL_RAND_MAX.
305 jab 83
  inline double my_random()
84
  {
417 jrf 85
    return gel_rand()/static_cast<double>(GEL_RAND_MAX);
305 jab 86
  }
309 jab 87
 
310 jrf 88
  AABBTree bb_tree;		
305 jab 89
}
90
 
91
void spin(int x);
92
 
93
//////////////////////////////////////////////////////////////
94
//      I N I T I A L I Z A T I O N               
95
//////////////////////////////////////////////////////////////
96
 
97
void init_texture(unsigned int& tex)
98
{
322 jab 99
  glGenTextures(1, reinterpret_cast<GLuint*>(&tex));
305 jab 100
 
101
  glBindTexture(GL_TEXTURE_2D, tex);
102
 
103
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
104
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
105
 
106
  // load the texture image
107
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 
418 jrf 108
	             TEX_SIZE, TEX_SIZE,
109
	             0, GL_RGB, GL_FLOAT, image[0][0].get());
305 jab 110
}
111
 
112
void initRaytracer()
113
{
114
  Vec3f c;
115
  float r;
116
  mesh.get_bsphere(c, r);
117
  r *= 1.5;
118
 
119
  // Initialize track ball
310 jrf 120
  vctrl = new GLViewController(winx, winy, c, r);
305 jab 121
 
122
  // Initialize corresponding camera
418 jrf 123
  cam = new Camera(c - Vec3f(r), c, Vec3f(0.0f, 1.0f, 0.0f), 1.0f);
305 jab 124
 
312 jrf 125
#ifdef USE_BSP
309 jab 126
   cout << "Constructing BSP tree..." << endl;
127
   tree.init(mesh_vector, transforms, MAX_OBJECTS, MAX_LEVEL);
128
   tree.build();
129
#else
130
	// AABB TREE
131
	Manifold m;
132
	vector<int> faces(mesh.geometry.no_faces(), 3);
133
	cout << "Creating manifold" << endl;
134
	build_manifold(m, 
418 jrf 135
				         mesh.geometry.no_vertices(), 
136
				         &mesh.geometry.vertex(0), 
137
				         faces.size(), &faces[0], 
138
				         reinterpret_cast<const int*>(&mesh.geometry.face(0)));
309 jab 139
	cout << "Building tree" << endl;
140
	build_AABBTree(m, bb_tree);
141
#endif
305 jab 142
}
143
 
144
void initGL()
145
{
146
  glShadeModel(GL_SMOOTH); 
309 jab 147
  glDisable(GL_CULL_FACE);
305 jab 148
  glFrontFace(GL_CCW);
149
 
150
  glClearColor(1.0, 1.0, 1.0, 1.0);
151
  glColor3f(0.0, 0.0, 0.0);
152
}
153
 
154
 
155
//////////////////////////////////////////////////////////////
156
//      S H A D E   F U N C T I O N S
157
//////////////////////////////////////////////////////////////
158
 
159
double shadow_shade(Ray& r)
160
{
161
  r.compute_position();
162
  Ray shadow(r.hit_pos, light_dir);
163
  double s = tree.intersect(shadow) ? 0.0 : 1.0;
164
 
165
  r.compute_normal();
166
  return s*light_pow*dot(r.hit_normal, light_dir);
167
}
168
 
169
double lambertian_shade(Ray& r)
170
{
312 jrf 171
#ifdef USE_BSP
418 jrf 172
	r.compute_normal();
309 jab 173
#endif
305 jab 174
  return light_pow*dot(r.hit_normal, light_dir);
175
}
176
 
177
double (*shade_ray[2])(Ray&) = { lambertian_shade,
418 jrf 178
				                         shadow_shade      };
305 jab 179
 
180
//////////////////////////////////////////////////////////////
181
//      D R A W   F U N C T I O N S
182
//////////////////////////////////////////////////////////////
183
 
184
/*
185
void enable_textures(TriMesh& tm)
186
{
187
  for(unsigned int i=0;i<tm.materials.size(); ++i)
188
  {
189
    Material& mat = tm.materials[i];
190
    if(mat.tex_name != "")
191
    {
192
      string name = mat.tex_path + mat.tex_name;
193
 
194
      GLuint tex_id;
195
      if(load_image_into_texture(name, tex_id))
196
	mat.tex_id = tex_id;
197
    }
198
  }
199
}
200
*/
201
 
202
void set_perspective_proj()
203
{
204
  glMatrixMode(GL_PROJECTION);	 
205
  glLoadIdentity();            
206
 
207
  gluPerspective(64.0, 1.0, 0.1, 1000.0);
208
 
209
  glMatrixMode(GL_MODELVIEW);
210
}
211
 
212
void set_ortho_proj()
213
{
214
  glMatrixMode(GL_PROJECTION);	 
215
  glLoadIdentity();             
216
 
217
  glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
218
 
219
  glMatrixMode(GL_MODELVIEW);  
220
}
221
 
222
void draw_texture(unsigned int tex)
223
{
224
  static GLfloat verts[] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0 };
225
 
226
  glColor4f(1.0, 1.0, 1.0, 1.0);
227
 
228
  glBindTexture(GL_TEXTURE_2D, tex);
229
  glEnable(GL_TEXTURE_2D);
230
 
231
  glEnableClientState(GL_VERTEX_ARRAY);
232
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
233
 
234
  glVertexPointer(2, GL_FLOAT, 0, verts);
235
  glTexCoordPointer(2, GL_FLOAT, 0, verts);
236
 
237
  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
238
 
239
  glDisableClientState(GL_VERTEX_ARRAY);
240
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
241
 
242
  glDisable(GL_TEXTURE_2D);
243
}
244
 
245
void drawOBJ()
246
{
247
  static bool washere = false;
248
  static unsigned int disp_list;
249
 
250
  if(!washere)
251
  {
252
    disp_list = glGenLists(1);
253
    glNewList(disp_list, GL_COMPILE);
254
 
255
    glBegin(GL_TRIANGLES);
418 jrf 256
    for(int i = 0; i < mesh.geometry.no_faces(); ++i)
257
    {
258
      Vec3i n_face = mesh.normals.face(i);
259
      Vec3i g_face = mesh.geometry.face(i);
260
      for(int j=0;j<3;j++)
305 jab 261
      {
418 jrf 262
        double shade = 0.5;
305 jab 263
 
418 jrf 264
        if(n_face != Geometry::NULL_FACE)
265
        {
266
          Vec3f norm = normalize(mesh.normals.vertex(n_face[j]));
267
          glNormal3fv(norm.get());
268
          shade = light_pow*dot(norm, light_dir);
269
        }
305 jab 270
 
418 jrf 271
        glColor3d(shade, shade, shade);
272
        Vec3f vert = mesh.geometry.vertex(g_face[j]);	  
273
        glVertex3fv(vert.get());
305 jab 274
      }
418 jrf 275
    }
305 jab 276
    glEnd();
277
 
278
    glEndList();
279
    washere = true;
280
  }
281
  glCallList(disp_list);
282
}
283
 
284
 
285
//////////////////////////////////////////////////////////////
286
//      G L U T   C A L L B A C K   F U N C T I O N S                 
287
//////////////////////////////////////////////////////////////
288
 
289
void display()
290
{
291
  static bool first = true;
292
 
293
  if(first)
294
  {
295
    first = false;
296
    glutTimerFunc(spin_timer, spin, 0);
297
  }
298
 
299
  Vec3f eye, focus, up;
309 jab 300
	vctrl->get_view_param(eye, focus, up);
301
	cam->set(eye, focus, up, cam->get_focal_dist());
302
 
305 jab 303
  if(raytrace)
304
  {
305
    raytrace = false;
306
 
307
    cout << "Raytracing";
308
    float win_to_vp = 1.0f/static_cast<float>(TEX_SIZE);
309
    float lowerleft = 0.5 + win_to_vp*0.5;
310
    float step = win_to_vp/static_cast<float>(PIXEL_SUBDIVS);
311
 
312
    vector<Vec2f> jitter(PIXEL_SUBDIVS*PIXEL_SUBDIVS); 
313
    for(unsigned int i = 0; i < PIXEL_SUBDIVS; ++i)
314
      for(unsigned int j = 0; j < PIXEL_SUBDIVS; ++j)
315
      {
418 jrf 316
	      jitter[i*PIXEL_SUBDIVS + j][0] = (my_random() + (j%PIXEL_SUBDIVS))*step; 
317
	      jitter[i*PIXEL_SUBDIVS + j][1] = (my_random() + (i%PIXEL_SUBDIVS))*step; 
305 jab 318
      }
319
 
418 jrf 320
    Util::Timer tim;
321
    tim.start();
305 jab 322
    for(unsigned int i = 0; i < TEX_SIZE; ++i)
323
    {
418 jrf 324
	    for(unsigned int j = 0; j < TEX_SIZE; ++j)
325
	    {
326
		    Vec3d sum(0.0f);
327
		    Vec2f vp_pos(j*win_to_vp - lowerleft, i*win_to_vp - lowerleft);
328
 
329
		    for(unsigned int ky = 0; ky < PIXEL_SUBDIVS; ++ky)
330
		      for(unsigned int kx = 0; kx < PIXEL_SUBDIVS; ++kx)
331
		      {
332
			      Ray r = cam->get_ray(vp_pos + jitter[ky*PIXEL_SUBDIVS + kx]);
305 jab 333
 
312 jrf 334
#ifdef USE_BSP
418 jrf 335
			      if(tree.intersect(r))
336
			        sum += Vec3d(shade_ray[shadow](r));
337
			      else
338
			        sum += background;
309 jab 339
#else
418 jrf 340
			      float t = FLT_MAX;
341
			      bb_tree.intersect(r);
342
			      if(r.has_hit)
343
			        sum += Vec3d(shade_ray[0](r));
344
			      else 
345
			        sum += background;
309 jab 346
#endif		
418 jrf 347
		      }
348
	      image[i][j] = Vec3f(sum/static_cast<double>(PIXEL_SUBDIVS*PIXEL_SUBDIVS));
349
      }
350
      if(((i + 1) % 50) == 0) cerr << ".";
351
    }
352
	  cout << " - " << tim.get_secs() << " secs " << endl;
305 jab 353
    cout << endl;
354
 
355
    init_texture(image_tex);
356
 
357
    done = true;
358
  }
359
 
360
  if(done)
361
  {
362
    set_ortho_proj();
363
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
364
    glLoadIdentity();
365
 
366
    draw_texture(image_tex);
367
  }
368
  else
369
  {
370
    glEnable(GL_DEPTH_TEST);
371
 
372
    cam->glSetPerspective(winx, winy);
373
 
374
    glClearColor(background[0], background[1], background[2], 1.0);
375
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
376
    glLoadIdentity();
377
 
418 jrf 378
	  cam->glSetCamera();
305 jab 379
 
380
    glColor3f(0.5, 0.5, 0.5);
381
    drawOBJ();
382
 
383
    glDisable(GL_DEPTH_TEST);
384
  }
385
 
386
  glutSwapBuffers();  
387
}
388
 
389
void reshape(int w, int h)
390
{
391
  winx = w; winy = h;
392
 
309 jab 393
  vctrl->reshape(winx, winy);
305 jab 394
 
395
  glViewport(0, 0, winx, winy);
396
}
397
 
398
void keyboard(unsigned char key, int x, int y)
399
{
400
  switch(key)
401
  {
402
  case '+':
403
    ++PIXEL_SUBDIVS;
404
    cout << "Rays per pixel: " << PIXEL_SUBDIVS*PIXEL_SUBDIVS << endl;
405
    break;
406
  case '-':
407
    if(PIXEL_SUBDIVS > 1)
408
      --PIXEL_SUBDIVS;
409
    cout << "Rays per pixel: " << PIXEL_SUBDIVS*PIXEL_SUBDIVS << endl;
410
    break;
411
  case 'r':
412
    if(done) done = false;
413
    else raytrace = true;
414
    break;
415
  case 's':
416
    shadow = !shadow;
417
    cout << "Shadow " << (shadow ? "on." : "off.") << endl;
418
    break;
419
  case 27:
309 jab 420
    delete vctrl;
305 jab 421
    delete cam;
422
    exit(0);
423
  }
424
}
425
 
426
void mouse(int btn, int state, int x, int y)
427
{
428
  if(state == GLUT_DOWN) 
429
  {
430
    if(btn == GLUT_LEFT_BUTTON) 
309 jab 431
      vctrl->grab_ball(ROTATE_ACTION, Vec2i(x, y));
305 jab 432
    else if(btn == GLUT_MIDDLE_BUTTON) 
309 jab 433
      vctrl->grab_ball(ZOOM_ACTION, Vec2i(x, y));
305 jab 434
    else if(btn == GLUT_RIGHT_BUTTON) 
309 jab 435
      vctrl->grab_ball(PAN_ACTION, Vec2i(x, y));
305 jab 436
  }
437
  else if(state == GLUT_UP)
309 jab 438
			vctrl->release_ball();
305 jab 439
 
440
  mouse_state = state;
441
  mouse_button = btn;
442
 
443
  glutPostRedisplay();
444
}
445
 
446
void move(int x, int y)
447
{
309 jab 448
    vctrl->roll_ball(Vec2i(x, y));
305 jab 449
 
450
  glutPostRedisplay();
451
}
452
 
453
void spin(int x)
454
{
309 jab 455
  vctrl->try_spin();
305 jab 456
  glutTimerFunc(spin_timer, spin, 0);  
457
  glutPostRedisplay();
458
}
459
 
460
 
461
//////////////////////////////////////////////////////////////
462
//                        M A I N
463
//////////////////////////////////////////////////////////////
464
 
465
int main(int argc, char** argv)
466
{
467
#ifdef __BORLANDC__
468
  _control87(MCW_EM, MCW_EM);  // Borland C++ will crash OpenGL if this
469
                               // magic line is not inserted
470
#endif
471
 
472
  glutInit(&argc, argv);
473
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
474
  glutInitWindowSize(winx, winy);
475
  glutCreateWindow("Press 'r' to raytrace");
476
  glutDisplayFunc(display);
477
  glutReshapeFunc(reshape);
478
  glutKeyboardFunc(keyboard);
479
  glutMouseFunc(mouse);
480
  glutMotionFunc(move);
481
 
482
  // LOAD OBJ
483
  string filename;
484
  if(argc > 1)
485
  {
486
    filename = argv[1];
487
    cout << "Loading " << filename << endl;
488
 
489
    obj_load(filename, mesh);
490
    //if(!mesh.has_normals())
491
    //{
492
      cout << "Computing normals" << endl;
493
      mesh.compute_normals();
494
    //}
495
 
496
    cout << "No. of triangles: " << mesh.geometry.no_faces() << endl;
497
  }
498
  else
499
  {
500
    obj_load("../../data/dolphins.obj", mesh);
501
 
418 jrf 502
  	cout << "Computing normals" << endl;
305 jab 503
    mesh.compute_normals();
504
 
418 jrf 505
    //cout << "Usage: raytrace any_object.obj";
305 jab 506
    //exit(0);
507
  }
508
 
509
  initRaytracer();
510
  initGL();    
511
 
512
  glutMainLoop();
513
 
514
  return 0;
515
}
516