Lightmetrica  0.0.1.50dbee3 (yosakoi)
 All Classes Functions Variables Typedefs Enumerations Enumerator
triaccel.h
1 /*
2  Lightmetrica : A research-oriented renderer
3 
4  Copyright (c) 2014 Hisanari Otsu
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #pragma once
21 #ifndef LIB_LIGHTMETRICA_TRIACCEL_H
22 #define LIB_LIGHTMETRICA_TRIACCEL_H
23 
24 #include "math.functions.h"
25 #include "ray.h"
26 
27 LM_NAMESPACE_BEGIN
28 
29 // TriAccel by Ingo Wald
30 // We used the implementation in mitsuba with a slight modification
31 struct TriAccel
32 {
33 
34  uint32_t k;
35  Math::Float n_u;
36  Math::Float n_v;
37  Math::Float n_d;
38 
39  Math::Float a_u;
40  Math::Float a_v;
41  Math::Float b_nu;
42  Math::Float b_nv;
43 
44  Math::Float c_nu;
45  Math::Float c_nv;
46  uint32_t shapeIndex;
47  uint32_t primIndex;
48 
49  // Construct from vertex data. Returns '1' if there was a failure
50  LM_FORCE_INLINE int Load(const Math::Vec3& A, const Math::Vec3& B, const Math::Vec3& C);
51 
52  // Fast ray-triangle intersection test
53  LM_FORCE_INLINE bool Intersect(const Ray& ray, Math::Float mint, Math::Float maxt, Math::Float& u, Math::Float& v, Math::Float& t) const;
54 
55 };
56 
57 LM_FORCE_INLINE int TriAccel::Load(const Math::Vec3& A, const Math::Vec3& B, const Math::Vec3& C)
58 {
59  static const int waldModulo[4] = { 1, 2, 0, 1 };
60 
61  Math::Vec3 b = C - A;
62  Math::Vec3 c = B - A;
63  Math::Vec3 N = Math::Cross(c, b);
64 
65  k = 0;
66  // Determine the largest projection axis
67  for (int j = 0; j < 3; j++)
68  {
69  if (Math::Abs(N[j]) > Math::Abs(N[k]))
70  {
71  k = j;
72  }
73  }
74 
75  uint32_t u = waldModulo[k];
76  uint32_t v = waldModulo[k+1];
77  const Math::Float n_k = N[k];
78  const Math::Float denom = b[u]*c[v] - b[v]*c[u];
79 
80  if (denom == 0)
81  {
82  k = 3;
83  return 1;
84  }
85 
86  // Pre-compute intersection calculation constants
87  n_u = N[u] / n_k;
88  n_v = N[v] / n_k;
89  n_d = Math::Dot(Math::Vec3(A), N) / n_k;
90  b_nu = b[u] / denom;
91  b_nv = -b[v] / denom;
92  a_u = A[u];
93  a_v = A[v];
94  c_nu = c[v] / denom;
95  c_nv = -c[u] / denom;
96 
97  return 0;
98 }
99 
100 LM_FORCE_INLINE bool TriAccel::Intersect(const Ray& ray, Math::Float mint, Math::Float maxt, Math::Float& u, Math::Float& v, Math::Float& t) const
101 {
102  Math::Float o_u, o_v, o_k, d_u, d_v, d_k;
103  switch (k)
104  {
105  case 0:
106  o_u = ray.o[1];
107  o_v = ray.o[2];
108  o_k = ray.o[0];
109  d_u = ray.d[1];
110  d_v = ray.d[2];
111  d_k = ray.d[0];
112  break;
113 
114  case 1:
115  o_u = ray.o[2];
116  o_v = ray.o[0];
117  o_k = ray.o[1];
118  d_u = ray.d[2];
119  d_v = ray.d[0];
120  d_k = ray.d[1];
121  break;
122 
123  case 2:
124  o_u = ray.o[0];
125  o_v = ray.o[1];
126  o_k = ray.o[2];
127  d_u = ray.d[0];
128  d_v = ray.d[1];
129  d_k = ray.d[2];
130  break;
131 
132  default:
133  return false;
134  }
135 
136 
137 #if LM_DEBUG_MODE
138  if (d_u * n_u + d_v * n_v + d_k == 0)
139  {
140  return false;
141  }
142 #endif
143 
144  // Calculate the plane intersection (Typo in the thesis?)
145  t = (n_d - o_u*n_u - o_v*n_v - o_k) / (d_u * n_u + d_v * n_v + d_k);
146  if (t < mint || t > maxt)
147  {
148  return false;
149  }
150 
151  // Calculate the projected plane intersection point
152  const Math::Float hu = o_u + t * d_u - a_u;
153  const Math::Float hv = o_v + t * d_v - a_v;
154 
155  // In barycentric coordinates
156  u = hv * b_nu + hu * b_nv;
157  v = hu * c_nu + hv * c_nv;
158 
159  return u >= 0 && v >= 0 && u+v <= 1;
160 }
161 
162 LM_NAMESPACE_END
163 
164 #endif // LIB_LIGHTMETRICA_TRIACCEL_H
Definition: triaccel.h:31
Definition: ray.h:33