Subversion Repositories gelsvn

Rev

Rev 609 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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