GEL
2
GEL is a library for Geometry and Linear Algebra
|
00001 #ifndef __GEOMETRY_RAY_H__ 00002 #define __GEOMETRY_RAY_H__ 00003 00004 #include "../CGLA/Vec3i.h" 00005 #include "../CGLA/Vec3f.h" 00006 #include "TriMesh.h" 00007 #include "Material.h" 00008 00009 namespace Geometry 00010 { 00011 const double d_eps = 1.0e-12; 00012 const float f_eps = 1.0e-6f; 00013 00014 struct Ray 00015 { 00016 // Constructor 00017 Ray() 00018 : origin(0.0f), direction(0.0f), hit_pos(0.0f), hit_normal(0.0f), 00019 has_hit(false), dist(CGLA::BIG), ior(1.0f), u(0.0f), v(0.0f), 00020 hit_object(0), trace_depth(0), inside(false), did_hit_diffuse(false) 00021 { } 00022 00023 Ray(const CGLA::Vec3f& _origin, const CGLA::Vec3f& _direction) 00024 : origin(_origin), direction(_direction), hit_pos(0.0f), hit_normal(0.0f), 00025 has_hit(false), dist(CGLA::BIG), ior(1.0f), u(0.0f), v(0.0f), 00026 hit_object(0), trace_depth(0), inside(false), did_hit_diffuse(false) 00027 { } 00028 00029 CGLA::Vec3f origin; 00030 CGLA::Vec3f direction; 00031 CGLA::Vec3f hit_pos; 00032 CGLA::Vec3f hit_normal; 00033 00034 bool has_hit; // Did the ray hit an object 00035 bool inside; // Is the ray inside an object 00036 bool did_hit_diffuse; 00037 00038 double dist; // Distance from origin to current intersection 00039 float ior; // Current index of refraction for media 00040 float u, v; // uv-coordinates on current surface 00041 00042 int trace_depth; // Current recursion number 00043 size_t hit_face_id; 00044 int id; 00045 00046 const TriMesh* hit_object; 00047 00048 const Material* get_hit_material() const 00049 { 00050 if(!hit_object) 00051 return 0; 00052 return &hit_object->materials[hit_object->mat_idx[hit_face_id]]; 00053 } 00054 00055 void reset() 00056 { 00057 dist = CGLA::BIG; 00058 hit_object = 0; 00059 u=0.0f; 00060 v=0.0f; 00061 has_hit=false; 00062 } 00063 00064 void compute_position() 00065 { 00066 hit_pos = origin + dist*direction; 00067 } 00068 00069 void compute_normal() 00070 { 00071 CGLA::Vec3i face = hit_object->normals.face(hit_face_id); 00072 CGLA::Vec3f normal0 = hit_object->normals.vertex(face[0]); 00073 CGLA::Vec3f normal1 = hit_object->normals.vertex(face[1]); 00074 CGLA::Vec3f normal2 = hit_object->normals.vertex(face[2]); 00075 hit_normal = normalize(normal0*(1 - u - v) + normal1*u + normal2*v); 00076 } 00077 00078 void reflect(const CGLA::Vec3f &normal) 00079 { 00080 assert(dot(direction, normal) < 0.0f); 00081 direction = normal*2.0f*dot(-direction,normal) + direction; 00082 } 00083 00084 void refract(const CGLA::Vec3f& normal, float new_ior) 00085 { 00086 float ref_ratio = ior/new_ior; 00087 float cos_N_I = dot(normal, direction); 00088 CGLA::Vec3f norm(normal); 00089 00090 if(cos_N_I > 0.0f) 00091 { 00092 norm = -norm; 00093 cos_N_I = dot(norm, direction); 00094 } 00095 00096 float selector = 1+(ref_ratio*ref_ratio)*(cos_N_I*cos_N_I - 1); 00097 00098 if(selector > 0.0f) 00099 { 00100 direction = norm*(ref_ratio*(-cos_N_I) - sqrt(selector)) 00101 + direction*ref_ratio; 00102 ior = new_ior; 00103 } 00104 else 00105 // Total internal reflection. 00106 reflect(normal); 00107 } 00108 00109 bool cond_set_parameter(float t, float _u, float _v, Geometry::TriMesh* mesh, size_t idx) 00110 { 00111 if(t < dist) 00112 { 00113 dist = t; 00114 u = _u; 00115 v = _v; 00116 hit_object = mesh; 00117 hit_face_id = idx; 00118 has_hit = true; 00119 return true; 00120 } 00121 return false; 00122 } 00123 }; 00124 } 00125 #endif 00126