Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
TOrthonormalBasis3.ipp
Go to the documentation of this file.
1#pragma once
2
4#include "Math/math.h"
5
6#include <Common/assertion.h>
7
8#include <algorithm>
9#include <cmath>
10#include <limits>
11
12namespace ph::math
13{
14
15template<typename T>
17{
18 PH_ASSERT_IN_RANGE(unitYAxis.lengthSquared(), static_cast<T>(0.9), static_cast<T>(1.1));
20 // choose an axis deviate enough to specified y-axis to perform cross product in order to avoid some
21 // numerical errors
22 TVector3<T> unitXAxis;
23 if(std::abs(unitYAxis.y()) < constant::rcp_sqrt_2<real>)
24 {
25 unitXAxis.set({-unitYAxis.z(), T(0), unitYAxis.x()});// yAxis cross (0, 1, 0)
26 unitXAxis.mulLocal(T(1) / std::sqrt(unitXAxis.x() * unitXAxis.x() + unitXAxis.z() * unitXAxis.z()));
27 }
28 else
29 {
30 unitXAxis.set({unitYAxis.y(), -unitYAxis.x(), T(0)});// yAxis cross (0, 0, 1)
31 unitXAxis.mulLocal(T(1) / std::sqrt(unitXAxis.x() * unitXAxis.x() + unitXAxis.y() * unitXAxis.y()));
32 }
33
34 const TVector3<T> unitZAxis = unitXAxis.cross(unitYAxis);
35
36 PH_ASSERT_IN_RANGE(unitXAxis.lengthSquared(), static_cast<T>(0.9), static_cast<T>(1.1));
37 PH_ASSERT_IN_RANGE(unitZAxis.lengthSquared(), static_cast<T>(0.9), static_cast<T>(1.1));
39 return TOrthonormalBasis3(unitXAxis, unitYAxis, unitZAxis);
40
41 // TEST
42 /*std::cerr << std::setprecision(20);
43 if(std::abs(out_unitXaxis->length() - 1.0_r) > 0.000001_r)
44 std::cerr << out_unitXaxis->length() << std::endl;
45 if(std::abs(out_unitZaxis->length() - 1.0_r) > 0.000001_r)
46 std::cerr << out_unitZaxis->length() << std::endl;
47 if(out_unitXaxis->dot(*out_unitZaxis) > 0.000001_r)
48 std::cerr << out_unitXaxis->dot(*out_unitZaxis) << std::endl;
49 if(out_unitZaxis->dot(unitYaxis) > 0.000001_r)
50 std::cerr << out_unitZaxis->dot(unitYaxis) << std::endl;
51 if(unitYaxis.dot(*out_unitXaxis) > 0.000001_r)
52 std::cerr << unitYaxis.dot(*out_unitXaxis) << std::endl;*/
54
55template<typename T>
57 m_xAxis(1, 0, 0),
58 m_yAxis(0, 1, 0),
59 m_zAxis(0, 0, 1)
60{}
61
62template<typename T>
64 const TVector3<T>& xAxis,
65 const TVector3<T>& yAxis,
66 const TVector3<T>& zAxis)
68 : m_xAxis(xAxis)
69 , m_yAxis(yAxis)
70 , m_zAxis(zAxis)
72 PH_ASSERT_IN_RANGE(xAxis.lengthSquared(), static_cast<T>(0.9), static_cast<T>(1.1));
73 PH_ASSERT_IN_RANGE(yAxis.lengthSquared(), static_cast<T>(0.9), static_cast<T>(1.1));
74 PH_ASSERT_IN_RANGE(zAxis.lengthSquared(), static_cast<T>(0.9), static_cast<T>(1.1));
75}
77template<typename T>
79{
80 return TVector3<T>(m_xAxis.dot(worldVec),
81 m_yAxis.dot(worldVec),
82 m_zAxis.dot(worldVec));
83}
84
85template<typename T>
87{
88 return m_xAxis.mul(localVec.x()).add(
89 m_yAxis.mul(localVec.y())).add(
90 m_zAxis.mul(localVec.z()));
91}
92
93template<typename T>
94inline T TOrthonormalBasis3<T>::cosPhi(const TVector3<T>& unitVec) const
95{
96 const T zProjection = unitVec.dot(m_zAxis);
97 const T rProjection = sinTheta(unitVec);
98 return math::safe_clamp(zProjection / rProjection, static_cast<T>(-1), static_cast<T>(1));
99}
100
101template<typename T>
102inline T TOrthonormalBasis3<T>::sinPhi(const TVector3<T>& unitVec) const
103{
104 const T xProjection = unitVec.dot(m_xAxis);
105 const T rProjection = sinTheta(unitVec);
106 return math::safe_clamp(xProjection / rProjection, static_cast<T>(-1), static_cast<T>(1));
107}
108
109template<typename T>
110inline T TOrthonormalBasis3<T>::tanPhi(const TVector3<T>& unitVec) const
111{
112 const T zProjection = unitVec.dot(m_zAxis);
113 const T xProjection = unitVec.dot(m_xAxis);
114 const T tanP = xProjection / zProjection;
115 return std::isfinite(tanP) ? tanP : static_cast<T>(0);
116}
117
118template<typename T>
119inline T TOrthonormalBasis3<T>::cos2Phi(const TVector3<T>& unitVec) const
120{
121 return math::squared(cosPhi(unitVec));
122}
123
124template<typename T>
125inline T TOrthonormalBasis3<T>::sin2Phi(const TVector3<T>& unitVec) const
126{
127 return math::squared(sinPhi(unitVec));
128}
129
130template<typename T>
131inline T TOrthonormalBasis3<T>::tan2Phi(const TVector3<T>& unitVec) const
132{
133 const T cos2P = cos2Phi(unitVec);
134 const T sin2P = 1 - cos2P;
135 const T tan2P = sin2P / cos2P;
136 PH_ASSERT(tan2P >= static_cast<T>(0) || !std::isfinite(tan2P));
137 return std::isfinite(tan2P) ? tan2P : static_cast<T>(0);
138}
139
140template<typename T>
141inline T TOrthonormalBasis3<T>::cosTheta(const TVector3<T>& unitVec) const
142{
143 return math::clamp(m_yAxis.dot(unitVec), static_cast<T>(-1), static_cast<T>(1));
144}
145
146template<typename T>
147inline T TOrthonormalBasis3<T>::sinTheta(const TVector3<T>& unitVec) const
148{
149 return std::sqrt(sin2Theta(unitVec));
150}
151
152template<typename T>
153inline T TOrthonormalBasis3<T>::tanTheta(const TVector3<T>& unitVec) const
154{
155 const T cosT = cosTheta(unitVec);
156 const T tanT = sinTheta(unitVec) / cosT;
157 return std::isfinite(tanT) ? tanT : static_cast<T>(0);
158}
159
160template<typename T>
162{
163 return std::abs(cosTheta(unitVec));
164}
165
166template<typename T>
168{
169 return std::abs(sinTheta(unitVec));
170}
171
172template<typename T>
173inline T TOrthonormalBasis3<T>::cos2Theta(const TVector3<T>& unitVec) const
174{
175 return math::squared(cosTheta(unitVec));
176}
177
178template<typename T>
179inline T TOrthonormalBasis3<T>::sin2Theta(const TVector3<T>& unitVec) const
180{
181 return 1 - cos2Theta(unitVec);
182}
183
184template<typename T>
185inline T TOrthonormalBasis3<T>::tan2Theta(const TVector3<T>& unitVec) const
186{
187 const T cos2T = cos2Theta(unitVec);
188 const T sin2T = 1 - cos2T;
189 const T tan2T = sin2T / cos2T;
190 PH_ASSERT(tan2T >= static_cast<T>(0) || !std::isfinite(tan2T));
191 return std::isfinite(tan2T) ? tan2T : static_cast<T>(0);
192}
193
194template<typename T>
196{
197 renormalizeXAxis();
198 renormalizeYAxis();
199 renormalizeZAxis();
200
201 return *this;
202}
203
204template<typename T>
206{
207 m_xAxis.normalizeLocal();
208
209 return *this;
210}
211
212template<typename T>
214{
215 m_yAxis.normalizeLocal();
216
217 return *this;
218}
219
220template<typename T>
222{
223 m_zAxis.normalizeLocal();
224
225 return *this;
226}
227
228template<typename T>
230{
231 m_xAxis = axis;
232
233 return *this;
234}
235
236template<typename T>
238{
239 m_yAxis = axis;
240
241 return *this;
242}
243
244template<typename T>
246{
247 m_zAxis = axis;
248
249 return *this;
250}
251
252template<typename T>
254 const TVector3<T>& xAxis,
255 const TVector3<T>& yAxis,
256 const TVector3<T>& zAxis)
257{
258 m_xAxis = xAxis;
259 m_yAxis = yAxis;
260 m_zAxis = zAxis;
261
262 return *this;
263}
264
265template<typename T>
267{
268 return m_xAxis;
269}
270
271template<typename T>
273{
274 return m_yAxis;
275}
276
277template<typename T>
279{
280 return m_zAxis;
281}
282
283}// end namespace ph::math
Represents a set of orthonormal basis vectors in 3-D space.
Definition TOrthonormalBasis3.h:13
T absCosTheta(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:161
TVector3< T > worldToLocal(const TVector3< T > &worldVec) const
Definition TOrthonormalBasis3.ipp:78
TVector3< T > getYAxis() const
Definition TOrthonormalBasis3.ipp:272
TVector3< T > getZAxis() const
Definition TOrthonormalBasis3.ipp:278
TOrthonormalBasis3 & set(const TVector3< T > &xAxis, const TVector3< T > &yAxis, const TVector3< T > &zAxis)
Definition TOrthonormalBasis3.ipp:253
static TOrthonormalBasis3 makeFromUnitY(const TVector3< T > &unitYAxis)
Definition TOrthonormalBasis3.ipp:16
TOrthonormalBasis3 & renormalize()
Definition TOrthonormalBasis3.ipp:195
TVector3< T > getXAxis() const
Definition TOrthonormalBasis3.ipp:266
T tanTheta(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:153
T tanPhi(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:110
TOrthonormalBasis3 & setXAxis(const TVector3< T > &axis)
Definition TOrthonormalBasis3.ipp:229
T sin2Theta(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:179
T tan2Theta(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:185
T sinTheta(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:147
T absSinTheta(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:167
T sinPhi(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:102
TOrthonormalBasis3 & setZAxis(const TVector3< T > &axis)
Definition TOrthonormalBasis3.ipp:245
TOrthonormalBasis3 & renormalizeZAxis()
Definition TOrthonormalBasis3.ipp:221
TOrthonormalBasis3 & renormalizeXAxis()
Definition TOrthonormalBasis3.ipp:205
T cosTheta(const TVector3< T > &unitVec) const
Calculates trigonometries for the angle in spherical coordinates.
Definition TOrthonormalBasis3.ipp:141
T sin2Phi(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:125
T cos2Phi(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:119
TOrthonormalBasis3 & renormalizeYAxis()
Definition TOrthonormalBasis3.ipp:213
T tan2Phi(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:131
T cos2Theta(const TVector3< T > &unitVec) const
Definition TOrthonormalBasis3.ipp:173
T cosPhi(const TVector3< T > &unitVec) const
Calculates trigonometries for the angle in spherical coordinates.
Definition TOrthonormalBasis3.ipp:94
TOrthonormalBasis3 & setYAxis(const TVector3< T > &axis)
Definition TOrthonormalBasis3.ipp:237
TOrthonormalBasis3()
Creates basis with unit x, y and z axes.
Definition TOrthonormalBasis3.ipp:56
TVector3< T > localToWorld(const TVector3< T > &localVec) const
Definition TOrthonormalBasis3.ipp:86
Represents a 3-D vector.
Definition TVector3.h:17
T & y()
Definition TVector3.ipp:189
T & z()
Definition TVector3.ipp:195
T & x()
Definition TVector3.ipp:183
TVector3 cross(const TVector3 &rhs) const
Definition TVector3.ipp:75
Derived mul(const Derived &rhs) const
Definition TArithmeticArrayBase.ipp:98
Derived & set(T value)
Definition TArithmeticArrayBase.ipp:604
T dot(const Derived &rhs) const
Definition TVectorNBase.ipp:14
Derived & mulLocal(const Derived &rhs)
Definition TArithmeticArrayBase.ipp:112
T lengthSquared() const
Definition TVectorNBase.ipp:44
Miscellaneous math utilities.
constexpr T rcp_sqrt_2
Value of .
Definition constant.h:63
Math functions and utilities.
Definition TransformInfo.h:10
T safe_clamp(const T value, const T lowerBound, const T upperBound)
Clamps a value to [lowerBound, upperBound], fallback to lowerBound. If a floating-point value is non-...
Definition math.h:98
T squared(const T value)
Definition math.h:59
T clamp(const T value, const T lowerBound, const T upperBound)
Clamps a value to [lowerBound, upperBound]. None of value, lowerBound and upperBound can be NaN,...
Definition math.h:77