The spica renderer
vect_math.h
1 #ifdef _MSC_VER
2 #pragma once
3 #endif
4 
5 #ifndef _SPICA_VECT_MATH_H_
6 #define _SPICA_VECT_MATH_H_
7 
8 #include <type_traits>
9 
10 #include "core/core.hpp"
11 #include "core/vector3d.h"
12 
13 namespace spica {
14 
15 namespace vect {
16 
17 template <class Vec1, class Vec2>
18 typename Vec1::type dot(const Vec1& v1, const Vec2& v2) {
19  static_assert(std::is_same<typename Vec1::type, typename Vec2::type>::value,
20  "Base types of two vectors must be the same!!");
21  return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z();
22 }
23 
24 template <class Vec1, class Vec2>
25 double absDot(const Vec1& v1, const Vec2& v2) {
26  return std::abs(dot(v1, v2));
27 }
28 
29 template <class Vec>
30 Vec cross(const Vec& v1, const Vec& v2) {
31  using Type = typename Vec::type;
32  Type x = v1.y() * v2.z() - v1.z() * v2.y();
33  Type y = v1.z() * v2.x() - v1.x() * v2.z();
34  Type z = v1.x() * v2.y() - v1.y() * v2.x();
35  return { x, y, z };
36 }
37 
38 template <class Vec>
39 Vec normalize(const Vec& v) {
40  const double nrm = std::sqrt(v.x() * v.x() + v.y() * v.y() + v.z() * v.z());
41  Assertion(nrm != 0.0, "Zero division!!");
42  return { v.x() / nrm, v.y() / nrm, v.z() / nrm };
43 }
44 
45 template <class Vec>
46 double sphericalPhi(const Vec& dir) {
47  double p = std::atan2(dir.y(), dir.x());
48  return p < 0.0 ? p + 2.0 * PI : p;
49 }
50 
51 template <class Vec>
52 double sphericalTheta(const Vec& dir) {
53  return std::acos(clamp(dir.z(), -1.0, 1.0));
54 }
55 
56 template <class Vec>
57 double cosTheta(const Vec& w) {
58  return w.z();
59 }
60 
61 template <class Vec>
62 double cos2Theta(const Vec& w) {
63  return w.z() * w.z();
64 }
65 
66 template <class Vec>
67 double sin2Theta(const Vec& w) {
68  return std::max(0.0, 1.0 - cos2Theta(w));
69 }
70 
71 template <class Vec>
72 double sinTheta(const Vec& w) {
73  return std::sqrt(sin2Theta(w));
74 }
75 
76 template <class Vec>
77 double tanTheta(const Vec& w) {
78  return sinTheta(w) / (cosTheta(w) + EPS);
79 }
80 
81 template <class Vec>
82 double tan2Theta(const Vec& w) {
83  return sin2Theta(w) / (cos2Theta(w) + EPS);
84 }
85 
86 template <class Vec>
87 double cosPhi(const Vec& w) {
88  double sinTheta = vect::sinTheta(w);
89  return (sinTheta == 0.0) ? 1.0 : clamp(w.x() / sinTheta, -1.0, 1.0);
90 }
91 
92 template <class Vec>
93 double sinPhi(const Vec& w) {
94  double sinTheta = vect::sinTheta(w);
95  return (sinTheta == 0.0) ? 0.0 : clamp(w.y() / sinTheta, -1.0, 1.0);
96 }
97 
98 template <class Vec>
99 double cos2Phi(const Vec& w) {
100  const double c = vect::cosPhi(w);
101  return c * c;
102 }
103 
104 template <class Vec>
105 double sin2Phi(const Vec& w) {
106  const double s = vect::sinPhi(w);
107  return s * s;
108 }
109 
110 template <class Vec>
111 bool sameHemisphere(const Vec& w1, const Vec& w2) {
112  return w1.z() * w2.z() > 0.0;
113 }
114 
115 template <class Vec>
116 void coordinateSystem(const Vec& w, Vec* u, Vec* v) {
117  if (std::abs(w.x()) > std::abs(w.y())) {
118  *u = vect::normalize(Vec(-w.z(), 0, w.x()));
119  } else {
120  *u = vect::normalize(Vec(0, w.z(), -w.y()));
121  }
122  *v = vect::normalize(vect::cross(w, *u));
123 }
124 
131 template <class Vec1, class Vec2>
132 Vector3_<typename Vec1::type> reflect(const Vec1& wo, const Vec2& n) {
133  using Type = typename Vec1::type;
134  return Vector3_<Type>(- wo + Vector3_<Type>(n) * Type(2) * vect::dot(n, wo));
135 }
136 
143 template <class Vec1, class Vec2>
144 bool refract(const Vec1& wi, const Vec2& n, double eta, Vec1* wt) {
145  double cosThetaI = vect::dot(n, wi);
146  double sin2ThetaI = std::max(0.0, 1.0 - cosThetaI * cosThetaI);
147  double sin2ThetaT = eta * eta * sin2ThetaI;
148 
149  if (sin2ThetaT >= 1.0) return false;
150  double cosThetaT = std::sqrt(1.0 - sin2ThetaT);
151  *wt = eta * (-wi) + (eta * cosThetaI - cosThetaT) * Vec1(n);
152  return true;
153 }
154 
155 template <class Vec1, class Vec2>
156 inline Vec1 faceforward(const Vec1& n, const Vec2& v) {
157  return vect::dot(n, v) < 0.0 ? -n : n;
158 }
159 
160 } // namespace vect
161 
162 } // namespace spica
163 
164 #endif // _SPICA_VECT_MATH_H_