void ClusterFit::SetColourSet( ColourSet const* colours, int flags ) { ColourFit::SetColourSet( colours, flags ); // initialise the best error #if SQUISH_USE_SIMD m_besterror = VEC4_CONST( FLT_MAX ); Vec3 metric = m_metric.GetVec3(); #else m_besterror = FLT_MAX; Vec3 metric = m_metric; #endif // cache some values int const count = m_colours->GetCount(); Vec3 const* values = m_colours->GetPoints(); // get the covariance matrix Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights(), metric ); // compute the principle component Vec3 principle = ComputePrincipleComponent( covariance ); // build the list of values float dps[16]; for( int i = 0; i < count; ++i ) { dps[i] = Dot( values[i], principle ); m_order[i] = i; } // stable sort for( int i = 0; i < count; ++i ) { for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j ) { std::swap( dps[j], dps[j - 1] ); std::swap( m_order[j], m_order[j - 1] ); } } // weight all the points #if SQUISH_USE_SIMD Vec4 const* unweighted = m_colours->GetPointsSimd(); Vec4 const* weights = m_colours->GetWeightsSimd(); m_xxsum = VEC4_CONST( 0.0f ); #else Vec3 const* unweighted = m_colours->GetPoints(); float const* weights = m_colours->GetWeights(); m_xxsum = Vec3( 0.0f ); #endif for( int i = 0; i < count; ++i ) { int p = m_order[i]; m_unweighted[i] = unweighted[p]; m_weights[i] = weights[p]; m_weighted[i] = weights[p]*unweighted[p]; m_xxsum += m_weighted[i]*m_weighted[i]; } }
RangeFit::RangeFit( ColourSet const* colours, int flags, float* metric ) : ColourFit( colours, flags ) { // initialise the metric (old perceptual = 0.2126f, 0.7152f, 0.0722f) if( metric ) m_metric = Vec3( metric[0], metric[1], metric[2] ); else m_metric = Vec3( 1.0f ); // initialise the best error m_besterror = FLT_MAX; // cache some values int const count = m_colours->GetCount(); Vec3 const* values = m_colours->GetPoints(); float const* weights = m_colours->GetWeights(); // get the covariance matrix Sym3x3 covariance = ComputeWeightedCovariance( count, values, weights ); // compute the principle component Vec3 principle = ComputePrincipleComponent( covariance ); // get the min and max range as the codebook endpoints Vec3 start( 0.0f ); Vec3 end( 0.0f ); if( count > 0 ) { float min, max; // compute the range start = end = values[0]; min = max = Dot( values[0], principle ); for( int i = 1; i < count; ++i ) { float val = Dot( values[i], principle ); if( val < min ) { start = values[i]; min = val; } else if( val > max ) { end = values[i]; max = val; } } } // clamp the output to [0, 1] Vec3 const one( 1.0f ); Vec3 const zero( 0.0f ); start = Min( one, Max( zero, start ) ); end = Min( one, Max( zero, end ) ); // clamp to the grid and save Vec3 const grid( 31.0f, 63.0f, 31.0f ); Vec3 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f ); Vec3 const half( 0.5f ); m_start = Truncate( grid*start + half )*gridrcp; m_end = Truncate( grid*end + half )*gridrcp; }