Subversion Repositories gelsvn

Rev

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