5 #ifndef _SPICA_VECT_MATH_H_
6 #define _SPICA_VECT_MATH_H_
10 #include "core/core.hpp"
11 #include "core/vector3d.h"
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();
24 template <
class Vec1,
class Vec2>
25 double absDot(
const Vec1& v1,
const Vec2& v2) {
26 return std::abs(dot(v1, v2));
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();
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 };
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;
52 double sphericalTheta(
const Vec& dir) {
53 return std::acos(clamp(dir.z(), -1.0, 1.0));
57 double cosTheta(
const Vec& w) {
62 double cos2Theta(
const Vec& w) {
67 double sin2Theta(
const Vec& w) {
68 return std::max(0.0, 1.0 - cos2Theta(w));
72 double sinTheta(
const Vec& w) {
73 return std::sqrt(sin2Theta(w));
77 double tanTheta(
const Vec& w) {
78 return sinTheta(w) / (cosTheta(w) + EPS);
82 double tan2Theta(
const Vec& w) {
83 return sin2Theta(w) / (cos2Theta(w) + EPS);
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);
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);
99 double cos2Phi(
const Vec& w) {
100 const double c = vect::cosPhi(w);
105 double sin2Phi(
const Vec& w) {
106 const double s = vect::sinPhi(w);
111 bool sameHemisphere(
const Vec& w1,
const Vec& w2) {
112 return w1.z() * w2.z() > 0.0;
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()));
120 *u = vect::normalize(Vec(0, w.z(), -w.y()));
122 *v = vect::normalize(vect::cross(w, *u));
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));
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;
149 if (sin2ThetaT >= 1.0)
return false;
150 double cosThetaT = std::sqrt(1.0 - sin2ThetaT);
151 *wt = eta * (-wi) + (eta * cosThetaI - cosThetaT) * Vec1(n);
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;
164 #endif // _SPICA_VECT_MATH_H_