Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/cvtt/ConvectionKernels_EndpointSelector.h
9896 views
1
#pragma once
2
#ifndef __CVTT_ENDPOINTSELECTOR_H__
3
#define __CVTT_ENDPOINTSELECTOR_H__
4
5
#include "ConvectionKernels_ParallelMath.h"
6
#include "ConvectionKernels_UnfinishedEndpoints.h"
7
#include "ConvectionKernels_PackedCovarianceMatrix.h"
8
9
namespace cvtt
10
{
11
namespace Internal
12
{
13
static const int NumEndpointSelectorPasses = 3;
14
15
template<int TVectorSize, int TIterationCount>
16
class EndpointSelector
17
{
18
public:
19
typedef ParallelMath::Float MFloat;
20
21
EndpointSelector()
22
{
23
for (int ch = 0; ch < TVectorSize; ch++)
24
{
25
m_centroid[ch] = ParallelMath::MakeFloatZero();
26
m_direction[ch] = ParallelMath::MakeFloatZero();
27
}
28
m_weightTotal = ParallelMath::MakeFloatZero();
29
m_minDist = ParallelMath::MakeFloat(FLT_MAX);
30
m_maxDist = ParallelMath::MakeFloat(-FLT_MAX);
31
}
32
33
void ContributePass(const MFloat *value, int pass, const MFloat &weight)
34
{
35
if (pass == 0)
36
ContributeCentroid(value, weight);
37
else if (pass == 1)
38
ContributeDirection(value, weight);
39
else if (pass == 2)
40
ContributeMinMax(value);
41
}
42
43
void FinishPass(int pass)
44
{
45
if (pass == 0)
46
FinishCentroid();
47
else if (pass == 1)
48
FinishDirection();
49
}
50
51
UnfinishedEndpoints<TVectorSize> GetEndpoints(const float channelWeights[TVectorSize]) const
52
{
53
MFloat unweightedBase[TVectorSize];
54
MFloat unweightedOffset[TVectorSize];
55
56
for (int ch = 0; ch < TVectorSize; ch++)
57
{
58
MFloat min = m_centroid[ch] + m_direction[ch] * m_minDist;
59
MFloat max = m_centroid[ch] + m_direction[ch] * m_maxDist;
60
61
float safeWeight = channelWeights[ch];
62
if (safeWeight == 0.f)
63
safeWeight = 1.0f;
64
65
unweightedBase[ch] = min / channelWeights[ch];
66
unweightedOffset[ch] = (max - min) / channelWeights[ch];
67
}
68
69
return UnfinishedEndpoints<TVectorSize>(unweightedBase, unweightedOffset);
70
}
71
72
private:
73
void ContributeCentroid(const MFloat *value, const MFloat &weight)
74
{
75
for (int ch = 0; ch < TVectorSize; ch++)
76
m_centroid[ch] = m_centroid[ch] + value[ch] * weight;
77
m_weightTotal = m_weightTotal + weight;
78
}
79
80
void FinishCentroid()
81
{
82
MFloat denom = m_weightTotal;
83
ParallelMath::MakeSafeDenominator(denom);
84
85
for (int ch = 0; ch < TVectorSize; ch++)
86
m_centroid[ch] = m_centroid[ch] / denom;
87
}
88
89
void ContributeDirection(const MFloat *value, const MFloat &weight)
90
{
91
MFloat diff[TVectorSize];
92
for (int ch = 0; ch < TVectorSize; ch++)
93
diff[ch] = value[ch] - m_centroid[ch];
94
95
m_covarianceMatrix.Add(diff, weight);
96
}
97
98
void FinishDirection()
99
{
100
MFloat approx[TVectorSize];
101
for (int ch = 0; ch < TVectorSize; ch++)
102
approx[ch] = ParallelMath::MakeFloat(1.0f);
103
104
for (int i = 0; i < TIterationCount; i++)
105
{
106
MFloat product[TVectorSize];
107
m_covarianceMatrix.Product(product, approx);
108
109
MFloat largestComponent = product[0];
110
for (int ch = 1; ch < TVectorSize; ch++)
111
largestComponent = ParallelMath::Max(largestComponent, product[ch]);
112
113
// product = largestComponent*newApprox
114
ParallelMath::MakeSafeDenominator(largestComponent);
115
for (int ch = 0; ch < TVectorSize; ch++)
116
approx[ch] = product[ch] / largestComponent;
117
}
118
119
// Normalize
120
MFloat approxLen = ParallelMath::MakeFloatZero();
121
for (int ch = 0; ch < TVectorSize; ch++)
122
approxLen = approxLen + approx[ch] * approx[ch];
123
124
approxLen = ParallelMath::Sqrt(approxLen);
125
126
ParallelMath::MakeSafeDenominator(approxLen);
127
128
for (int ch = 0; ch < TVectorSize; ch++)
129
m_direction[ch] = approx[ch] / approxLen;
130
}
131
132
void ContributeMinMax(const MFloat *value)
133
{
134
MFloat dist = ParallelMath::MakeFloatZero();
135
for (int ch = 0; ch < TVectorSize; ch++)
136
dist = dist + m_direction[ch] * (value[ch] - m_centroid[ch]);
137
138
m_minDist = ParallelMath::Min(m_minDist, dist);
139
m_maxDist = ParallelMath::Max(m_maxDist, dist);
140
}
141
142
ParallelMath::Float m_centroid[TVectorSize];
143
ParallelMath::Float m_direction[TVectorSize];
144
PackedCovarianceMatrix<TVectorSize> m_covarianceMatrix;
145
ParallelMath::Float m_weightTotal;
146
147
ParallelMath::Float m_minDist;
148
ParallelMath::Float m_maxDist;
149
};
150
}
151
}
152
153
#endif
154
155