Subversion Repositories gelsvn

Rev

Rev 324 | Rev 420 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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