Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
geometry.h
Go to the documentation of this file.
1#pragma once
2
3#include "Math/TVector2.h"
4#include "Math/TVector3.h"
5
6#include <Common/assertion.h>
7
8namespace ph::math
9{
10
11namespace detail
12{
13
24template<typename T>
26{
27 const TVector2<T> diagonallyMirroredPoint(point.y(), point.x());
28
29 /*
30 Note that in [1], it is calculated as
31
32 return (1.0 - abs(v.yx)) * (v.xy >= 0.0 ? 1.0 : -1.0);
33
34 which translate to the following:
35 */
36 // Basically mirror and flip along various axes
37 return diagonallyMirroredPoint.abs().complement() *
38 TVector2<T>(point.x() >= 0.0f ? 1.0f : -1.0f, point.y() >= 0.0f ? 1.0f : -1.0f);
39
40 /*
41 However, that seems overly complexed. Here I derived a simpler equivalent. It is worth noting that
42 my variant is likely inferior as the paper [2] uses the same formulation as in [1]. They use only
43 sign changes and complements to achieve the mirror, and should be robust (no seams due to quantization
44 errors; mine's uses arithmetic on the coordinates which can cause problems I guess).
45 */
46 /*return diagonallyMirroredPoint +
47 TVector2<T>(point.x() >= 0 ? 1 : -1, point.y() >= 0 ? 1 : -1);*/
48}
49
50}// end namespace detail
51
52// TODO: precise version of the encoding (see [2])
53
58template<typename T>
60{
61 TVector3<T> octahedronProj = unitVec / unitVec.abs().sum();
62 if(octahedronProj.z() < 0)
63 {
64 const TVector2<T> mirroredXYProj = detail::octahedron_diamond_mirror(TVector2<T>(octahedronProj.x(), octahedronProj.y()));
65 octahedronProj.x() = mirroredXYProj.x();
66 octahedronProj.y() = mirroredXYProj.y();
67 }
68
69 return TVector2<T>(octahedronProj.x(), octahedronProj.y()) * static_cast<T>(0.5) + static_cast<T>(0.5);
70}
71
76template<typename T>
78{
79 PH_ASSERT_IN_RANGE_INCLUSIVE(encodedVal.x(), 0, 1);
80 PH_ASSERT_IN_RANGE_INCLUSIVE(encodedVal.y(), 0, 1);
81
82 // Note that https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/
83 // provides an alternative approach that is faster on GPU.
84
85 const TVector2<T> expandedEncodedVal = encodedVal * static_cast<T>(2) - static_cast<T>(1);
86
87 TVector3<T> octahedronProj(
88 expandedEncodedVal.x(),
89 expandedEncodedVal.y(),
90 static_cast<T>(1) - expandedEncodedVal.abs().sum());
91 if(octahedronProj.z() < 0)
92 {
93 const TVector2<T> mirroredXYProj = detail::octahedron_diamond_mirror(TVector2<T>(octahedronProj.x(), octahedronProj.y()));
94 octahedronProj.x() = mirroredXYProj.x();
95 octahedronProj.y() = mirroredXYProj.y();
96 }
97
98 return octahedronProj.normalize();
99}
100
101}// end namespace ph::math
Represents a 2-D vector.
Definition TVector2.h:19
T & x()
Definition TVector2.ipp:38
T & y()
Definition TVector2.ipp:44
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
Derived normalize() const
Normalize the vector. Notice that normalizing a integer typed vector will result in 0-vector most of ...
Definition TVectorNBase.ipp:50
Derived abs() const
Definition TArithmeticArrayBase.ipp:466
TVector2< T > octahedron_diamond_mirror(const TVector2< T > &point)
Definition geometry.h:25
Math functions and utilities.
Definition TransformInfo.h:10
TVector2< T > octahedron_unit_vector_encode(const TVector3< T > &unitVec)
Encode a unit vector using octahedron projection.
Definition geometry.h:59
TVector3< T > octahedron_unit_vector_decode(const TVector2< T > &encodedVal)
Decode and get a unit vector using octahedron projection.
Definition geometry.h:77