Subversion Repositories gelsvn

Rev

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

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