public ClusterFit(ColourSet colours, SquishFlags flags) : base(colours, flags) { // set the iteration count m_iterationCount = ((m_flags & SquishFlags.ColourIterativeClusterFit) != 0) ? kMaxIterations : 1; // initialise the best error m_besterror = new Vec4(float.MaxValue); // initialise the metric bool perceptual = ((m_flags & SquishFlags.ColourMetricPerceptual) != 0); if (perceptual) m_metric = new Vec4(0.2126f, 0.7152f, 0.0722f, 0.0f); else m_metric = new Vec4(1.0f); // cache some values int count = m_colours.GetCount(); Vec3[] values = m_colours.GetPoints(); // get the covariance matrix Sym3x3 covariance = Sym3x3.ComputeWeightedCovariance(count, values, m_colours.GetWeights()); // compute the principle component m_principle = Sym3x3.ComputePrincipleComponent(covariance); }
public RangeFit(ColourSet colours, SquishFlags flags) : base(colours, flags) { // initialise the metric bool perceptual = ((m_flags & SquishFlags.ColourMetricPerceptual) != 0); if (perceptual) m_metric = new Vec3(0.2126f, 0.7152f, 0.0722f); else m_metric = new Vec3(1.0f); // initialise the best error m_besterror = float.MaxValue; // cache some values int count = m_colours.GetCount(); Vec3[] values = m_colours.GetPoints(); float[] weights = m_colours.GetWeights(); // get the covariance matrix Sym3x3 covariance = Sym3x3.ComputeWeightedCovariance(count, values, weights); // compute the principle component Vec3 principle = Sym3x3.ComputePrincipleComponent(covariance); // get the min and max range as the codebook endpoints Vec3 start = new Vec3(0.0f); Vec3 end = new Vec3(0.0f); if (count > 0) { float min, max; // compute the range start = end = values[0]; min = max = Vec3.Dot(values[0], principle); for (int i = 1; i < count; ++i) { float val = Vec3.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 one = new Vec3(1.0f); Vec3 zero = new Vec3(0.0f); start = Vec3.Min(one, Vec3.Max(zero, start)); end = Vec3.Min(one, Vec3.Max(zero, end)); // clamp to the grid and save Vec3 grid = new Vec3(31.0f, 63.0f, 31.0f); Vec3 gridrcp = new Vec3(1.0f / 31.0f, 1.0f / 63.0f, 1.0f / 31.0f); Vec3 half = new Vec3(0.5f); m_start = Vec3.Truncate(grid * start + half) * gridrcp; m_end = Vec3.Truncate(grid * end + half) * gridrcp; }
public SingleColourFit(ColourSet colours, SquishFlags flags) : base(colours, flags) { Vec3[] values = m_colours.GetPoints(); m_colour[0] = (byte)CMath.FloatToInt(255.0f * values[0].X(), 255); m_colour[1] = (byte)CMath.FloatToInt(255.0f * values[0].Y(), 255); m_colour[2] = (byte)CMath.FloatToInt(255.0f * values[0].Z(), 255); // initialise the best error m_besterror = int.MaxValue; }
/// <summary> /// Compresses a 4x4 block of pixels. /// </summary> /// <param name="rgba">The rgba values of the 16 source pixels.</param> /// <param name="mask">The valid pixel mask.</param> /// <param name="block">Storage for the compressed DXT block.</param> /// <param name="flags">Compression flags.</param> public static unsafe void CompressMasked(byte* rgba, int mask, byte* block, SquishFlags flags) { // fix any bad flags flags = FixFlags(flags); if ((flags & (SquishFlags.BC1 | SquishFlags.BC2 | SquishFlags.BC3 | SquishFlags.BC4 | SquishFlags.BC5)) != 0) { CompressMaskedBC(rgba, mask, block, flags); return; } // get the block locations byte* colourBlock = block; byte* alphaBock = block; if ((flags & (SquishFlags.Dxt3 | SquishFlags.Dxt5)) != 0) colourBlock = block + 8; // create the minimal point set ColourSet colours = new ColourSet(rgba, mask, flags); // check the compression type and compress colour if (colours.GetCount() == 1) { // always do a single colour fit SingleColourFit fit = new SingleColourFit(colours, flags); fit.Compress(colourBlock); } else if ((flags & SquishFlags.ColourRangeFit) != 0 || colours.GetCount() == 0) { // do a range fit RangeFit fit = new RangeFit(colours, flags); fit.Compress(colourBlock); } else { // default to a cluster fit (could be iterative or not) ClusterFit fit = new ClusterFit(colours, flags); fit.Compress(colourBlock); } // compress alpha separately if necessary if ((flags & SquishFlags.Dxt3) != 0) AlphaBlock.CompressAlphaDxt3(rgba, mask, alphaBock); else if ((flags & SquishFlags.Dxt5) != 0) AlphaBlock.CompressAlphaDxt5(rgba, mask, alphaBock); }
public ColourFit(ColourSet colours, SquishFlags flags) { m_colours = colours; m_flags = flags; }