Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
304 jab 1
#ifndef __RAY_H__
2
#define __RAY_H__
3
 
4
#include "../CGLA/Vec3i.h"
5
#include "../CGLA/Vec3f.h"
6
#include "TriMesh.h"
7
 
8
namespace Geometry 
9
{
10
  const double d_eps = 0.000001;
11
  const float f_eps = 0.01f;
12
 
13
  struct Ray 
14
  {
15
    // Constructor
16
    Ray() 
17
      : origin(0.0f), direction(0.0f), hit_pos(0.0f), hit_normal(0.0f), 
18
        has_hit(false), dist(CGLA::BIG), ior(1.0f), u(0.0f), v(0.0f), 
19
	hit_object(0)
20
    { }
21
 
22
    Ray(const CGLA::Vec3f& _origin, const CGLA::Vec3f& _direction) 
23
      : origin(_origin), direction(_direction), hit_pos(0.0f), hit_normal(0.0f), 
24
        has_hit(false), dist(CGLA::BIG), ior(1.0f), u(0.0f), v(0.0f), 
25
	hit_object(0)
26
    { }
27
 
28
    CGLA::Vec3f origin;
29
    CGLA::Vec3f direction;
30
    CGLA::Vec3f hit_pos;
31
    CGLA::Vec3f hit_normal;
32
 
33
    bool has_hit; // Did the ray hit an object
34
 
35
    double dist;  // Distance from origin to current intersection
36
    float ior;    // Current index of refraction for media
37
    float u, v;   // uv-coordinates on current surface
38
    float ran;
39
 
40
    int trace_depth;  // Current recursion number
41
    size_t hit_face_id;
42
    int id;
43
 
44
    Geometry::TriMesh* hit_object;
45
 
46
    void reset()
47
    {
48
      dist = CGLA::BIG; 
49
      hit_object = 0;
50
      u=0.0f;
51
      v=0.0f;
52
      has_hit=false;      
53
    }
54
 
55
    void compute_position()
56
    {
57
      hit_pos = origin + dist*direction;      
58
    }
59
 
60
    void compute_normal()
61
    {
62
      CGLA::Vec3i face = hit_object->normals.face(hit_face_id);
63
      CGLA::Vec3f normal0 = hit_object->normals.vertex(face[0]);
64
      CGLA::Vec3f normal1 = hit_object->normals.vertex(face[1]);
65
      CGLA::Vec3f normal2 = hit_object->normals.vertex(face[2]);
66
      hit_normal = normalize(normal0*(1 - u - v) + normal1*u + normal2*v);      
67
    }
68
 
69
    void reflect(const CGLA::Vec3f &normal)
70
    {
71
      assert(dot(direction, normal) < 0.0f);
72
      direction = normal*2.0f*dot(-direction,normal) + direction;      
73
    }
74
 
75
    void refract(const CGLA::Vec3f& normal, float new_ior)
76
    {
77
      float ref_ratio = ior/new_ior;
78
      float cos_N_I = dot(normal, direction);
79
      CGLA::Vec3f norm(normal);
80
 
81
      if(cos_N_I > 0.0f)
82
      {
83
	norm = -norm;
84
	cos_N_I = dot(norm, direction);
85
      }
86
 
87
      float selector = 1 + (ref_ratio*ref_ratio)*(cos_N_I*cos_N_I - 1);
88
 
89
      if(selector > 0.0f) 
90
      {
91
	direction = norm*(ref_ratio*(-cos_N_I) - sqrt(selector)) 
92
	            + direction*ref_ratio;
93
	ior = new_ior;
94
      } 
95
      else 
96
	// Total internal reflection.
97
	reflect(normal);
98
    }
99
 
100
    bool cond_set_parameter(float t, float _u, float _v, 
101
			    Geometry::TriMesh* mesh, size_t idx)
102
    {
103
      if(t < dist)
104
      {
105
	dist = t;
106
	u = _u;
107
	v = _v;
108
	hit_object = mesh;
109
	hit_face_id = idx;
110
	has_hit = true;
111
      }
112
    }
113
  };
114
}
115
#endif
116