Subversion Repositories gelsvn

Rev

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

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