Path: blob/master/thirdparty/cvtt/ConvectionKernels_EndpointSelector.h
9896 views
#pragma once1#ifndef __CVTT_ENDPOINTSELECTOR_H__2#define __CVTT_ENDPOINTSELECTOR_H__34#include "ConvectionKernels_ParallelMath.h"5#include "ConvectionKernels_UnfinishedEndpoints.h"6#include "ConvectionKernels_PackedCovarianceMatrix.h"78namespace cvtt9{10namespace Internal11{12static const int NumEndpointSelectorPasses = 3;1314template<int TVectorSize, int TIterationCount>15class EndpointSelector16{17public:18typedef ParallelMath::Float MFloat;1920EndpointSelector()21{22for (int ch = 0; ch < TVectorSize; ch++)23{24m_centroid[ch] = ParallelMath::MakeFloatZero();25m_direction[ch] = ParallelMath::MakeFloatZero();26}27m_weightTotal = ParallelMath::MakeFloatZero();28m_minDist = ParallelMath::MakeFloat(FLT_MAX);29m_maxDist = ParallelMath::MakeFloat(-FLT_MAX);30}3132void ContributePass(const MFloat *value, int pass, const MFloat &weight)33{34if (pass == 0)35ContributeCentroid(value, weight);36else if (pass == 1)37ContributeDirection(value, weight);38else if (pass == 2)39ContributeMinMax(value);40}4142void FinishPass(int pass)43{44if (pass == 0)45FinishCentroid();46else if (pass == 1)47FinishDirection();48}4950UnfinishedEndpoints<TVectorSize> GetEndpoints(const float channelWeights[TVectorSize]) const51{52MFloat unweightedBase[TVectorSize];53MFloat unweightedOffset[TVectorSize];5455for (int ch = 0; ch < TVectorSize; ch++)56{57MFloat min = m_centroid[ch] + m_direction[ch] * m_minDist;58MFloat max = m_centroid[ch] + m_direction[ch] * m_maxDist;5960float safeWeight = channelWeights[ch];61if (safeWeight == 0.f)62safeWeight = 1.0f;6364unweightedBase[ch] = min / channelWeights[ch];65unweightedOffset[ch] = (max - min) / channelWeights[ch];66}6768return UnfinishedEndpoints<TVectorSize>(unweightedBase, unweightedOffset);69}7071private:72void ContributeCentroid(const MFloat *value, const MFloat &weight)73{74for (int ch = 0; ch < TVectorSize; ch++)75m_centroid[ch] = m_centroid[ch] + value[ch] * weight;76m_weightTotal = m_weightTotal + weight;77}7879void FinishCentroid()80{81MFloat denom = m_weightTotal;82ParallelMath::MakeSafeDenominator(denom);8384for (int ch = 0; ch < TVectorSize; ch++)85m_centroid[ch] = m_centroid[ch] / denom;86}8788void ContributeDirection(const MFloat *value, const MFloat &weight)89{90MFloat diff[TVectorSize];91for (int ch = 0; ch < TVectorSize; ch++)92diff[ch] = value[ch] - m_centroid[ch];9394m_covarianceMatrix.Add(diff, weight);95}9697void FinishDirection()98{99MFloat approx[TVectorSize];100for (int ch = 0; ch < TVectorSize; ch++)101approx[ch] = ParallelMath::MakeFloat(1.0f);102103for (int i = 0; i < TIterationCount; i++)104{105MFloat product[TVectorSize];106m_covarianceMatrix.Product(product, approx);107108MFloat largestComponent = product[0];109for (int ch = 1; ch < TVectorSize; ch++)110largestComponent = ParallelMath::Max(largestComponent, product[ch]);111112// product = largestComponent*newApprox113ParallelMath::MakeSafeDenominator(largestComponent);114for (int ch = 0; ch < TVectorSize; ch++)115approx[ch] = product[ch] / largestComponent;116}117118// Normalize119MFloat approxLen = ParallelMath::MakeFloatZero();120for (int ch = 0; ch < TVectorSize; ch++)121approxLen = approxLen + approx[ch] * approx[ch];122123approxLen = ParallelMath::Sqrt(approxLen);124125ParallelMath::MakeSafeDenominator(approxLen);126127for (int ch = 0; ch < TVectorSize; ch++)128m_direction[ch] = approx[ch] / approxLen;129}130131void ContributeMinMax(const MFloat *value)132{133MFloat dist = ParallelMath::MakeFloatZero();134for (int ch = 0; ch < TVectorSize; ch++)135dist = dist + m_direction[ch] * (value[ch] - m_centroid[ch]);136137m_minDist = ParallelMath::Min(m_minDist, dist);138m_maxDist = ParallelMath::Max(m_maxDist, dist);139}140141ParallelMath::Float m_centroid[TVectorSize];142ParallelMath::Float m_direction[TVectorSize];143PackedCovarianceMatrix<TVectorSize> m_covarianceMatrix;144ParallelMath::Float m_weightTotal;145146ParallelMath::Float m_minDist;147ParallelMath::Float m_maxDist;148};149}150}151152#endif153154155