GEL  2
GEL is a library for Geometry and Linear Algebra
/Users/jab/Documents/Teaching/02585/GEL2_and_demos/GEL/src/Geometry/Ray.h
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations