Exemple #1
0
    private const float FLT_EPSILON = 1.192092896e-07F; // This is not the same value as Single.Epsilon

    #endregion Private Fields

    #region Public Methods

    public static Sym3x3 ComputeWeightedCovariance(int n, Vec3[] points, float[] weights) {
      //
      // compute the centroid
      //
      float total = 0.0f;

      Vec3 centroid = new Vec3(0.0f);

      for(int i = 0; i < n; ++i) {
        total += weights[i];

        centroid += weights[i] * points[i];
      }

      centroid /= total;
      //
      // accumulate the covariance matrix
      //
      Sym3x3 covariance = new Sym3x3(0.0f);

      for(int i = 0; i < n; ++i) {
        Vec3 a = points[i] - centroid;

        Vec3 b = weights[i] * a;

        covariance[0] += a.X * b.X;
        covariance[1] += a.X * b.Y;
        covariance[2] += a.X * b.Z;
        covariance[3] += a.Y * b.Y;
        covariance[4] += a.Y * b.Z;
        covariance[5] += a.Z * b.Z;
      }
      //
      // return it
      //
      return covariance;
    }
Exemple #2
0
        protected override unsafe void Compress4(byte *block)
        {
            //
            // cache some values
            //
            int count = colours.Count;

            Vec3[] values = colours.Points;
            //
            // create a codebook
            //
            Vec3[] codes = new Vec3[4];

            codes[0] = start;
            codes[1] = end;
            codes[2] = 2.0f / 3.0f * start + 1.0f / 3.0f * end;
            codes[3] = 1.0f / 3.0f * start + 2.0f / 3.0f * end;
            //
            // match each point to the closest code
            //
            byte[] closest = new byte[16];

            float error = 0.0f;

            for (int i = 0; i < count; ++i)
            {
                //
                // find the closest code
                //
                float dist = Single.MaxValue;

                int idx = 0;

                for (int j = 0; j < 4; ++j)
                {
                    float d = Vec3.LengthSquared(metric * (values[i] - codes[j]));

                    if (d < dist)
                    {
                        dist = d;

                        idx = j;
                    }
                }
                //
                // save the index
                //
                closest[i] = (byte)idx;
                //
                // accumulate the error
                //
                error += dist;
            }
            //
            // save this scheme if it wins
            //
            if (error < bestError)
            {
                //
                // remap the indices
                //
                byte[] indices = new byte[16];

                colours.RemapIndices(closest, indices);
                //
                // save the block
                //
                ColourBlock.WriteColourBlock4(start, end, indices, block);
                //
                // save the error
                //
                bestError = error;
            }
        }
Exemple #3
0
 public static float LengthSquared(Vec3 v) {
   return Dot(v, v);
 }
Exemple #4
0
 public static Vec3 Truncate(Vec3 v) {
   return new Vec3((float)(v.x > 0.0f ? Math.Floor(v.x ) : Math.Ceiling(v.x)), (float)(v.y > 0.0f ? Math.Floor(v.y) : Math.Ceiling(v.y)), (float)(v.z > 0.0f ? Math.Floor(v.z ) : Math.Ceiling(v.z)));
 }
Exemple #5
0
 public static Vec3 Max(Vec3 left, Vec3 right) {
   return new Vec3(Math.Max(left.x, right.x), Math.Max(left.y, right.y), Math.Max(left.z, right.z));
 }
Exemple #6
0
    private static Vec3 subtract(Vec3 left, Vec3 right) {
      left.x -= right.x;
      left.y -= right.y;
      left.z -= right.z;

      return left;
    }
Exemple #7
0
    public ClusterFit(ColourSet Colours, SquishFlags Flags) : base(Colours, Flags) {
      //
      // initialise the metric
      //
      bool isPerceptual = (flags & SquishFlags.ColourMetricPerceptual) != 0;

      metric = isPerceptual ? new Vec3(0.2126f, 0.7152f, 0.0722f) : new Vec3(1.0f);
      //
      // initialise the best error
      //
      bestError = Single.MaxValue;
      //
      // cache some values
      //
      int count = colours.Count;

      Vec3[] values = colours.Points;

      float[] weights = colours.Weights;
      //
      // get the covariance matrix
      //
      Sym3x3 covariance = Maths.ComputeWeightedCovariance(count, values, weights);
      //
      // compute the principle component
      //
      Vec3 principle = Maths.ComputePrincipleComponent(covariance);
      //
      // get the min and max range as the codebook endpoints
      //
      Vec3 startTemp = new Vec3(0.0f);
      Vec3   endTemp = new Vec3(0.0f);

      if (count > 0) {
        //
        // compute the range
        //
        startTemp = endTemp = values[0];

        float min = Vec3.Dot(values[0], principle);

        float max = min;

        for(int i = 1; i < count; ++i) {
          float val = Vec3.Dot(values[i], principle);

          if (val < min) {
            startTemp = values[i];

            min = val;
          }
          else {
            if (val > max) {
              endTemp = values[i];

              max = val;
            }
          }
        }
      }
      //
      // clamp the output to [0, 1]
      //
      Vec3 one  = new Vec3(1.0f);
      Vec3 zero = new Vec3(0.0f);

      startTemp = Vec3.Min(one, Vec3.Max(zero, startTemp));
      endTemp   = Vec3.Min(one, Vec3.Max(zero, endTemp));
      //
      // 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);

      start = Vec3.Truncate(grid * startTemp + half) * gridrcp;
      end   = Vec3.Truncate(grid * endTemp   + half) * gridrcp;
    }
Exemple #8
0
    public unsafe ColourSet(byte *rgba, int mask, SquishFlags flags) {
      Count = 0;

      IsTransparent = false;
      //
      // check the compression mode for dxt1
      //
      bool isDxt1        = (flags & SquishFlags.Dxt1) != 0;
      bool weightByAlpha = (flags & SquishFlags.WeightColourByAlpha) != 0;
      //
      // create the minimal set
      //
      for (int i = 0; i < 16; ++i) {
        //
        // check this pixel is enabled
        //
        int bit = 1 << i;

        if ((mask & bit) == 0) {
          remap[i] = -1;

          continue;
        }
        //
        // check for transparent pixels when using dxt1
        //
        if (isDxt1 && rgba[4 * i + 3] < 128) {
          remap[i] = -1;

          IsTransparent = true;

          continue;
        }
        //
        // loop over previous points for a match
        //
        for(int j = 0; ; ++j) {
          //
          // allocate a new point
          //
          if (j == i) {
            //
            // normalise coordinates to [0,1]
            //
            float x = rgba[4 * i + 0] / 255.0f;
            float y = rgba[4 * i + 1] / 255.0f;
            float z = rgba[4 * i + 2] / 255.0f;
            //
            // ensure there is always non-zero weight even for zero alpha
            //
            float w = (rgba[4 * i + 3] + 1) / 256.0f;
            //
            // add the point
            //
            Points[Count]  = new Vec3(x, y, z);

            Weights[Count] = weightByAlpha ? w : 1.0f;

            remap[i] = Count;
            //
            // advance
            //
            ++Count;

            break;
          }
          //
          // check for a match
          //
          int oldbit = 1 << j;

          bool match = ((mask & oldbit) != 0) && (rgba[4 * i + 0] == rgba[4 * j])
                                              && (rgba[4 * i + 1] == rgba[4 * j + 1])
                                              && (rgba[4 * i + 2] == rgba[4 * j + 2])
                                              && (rgba[4 * j + 3] >= 128 || !isDxt1);

          if (match) {
            //
            // get the index of the match
            //
            int index = remap[j];
            //
            // ensure there is always non-zero weight even for zero alpha
            //
            float w = (rgba[4 * i + 3] + 1) / 256.0f;
            //
            // map to this point and increase the weight
            //
            Weights[index] += weightByAlpha ? w : 1.0f;

            remap[i] = index;

            break;
          }
        }
      }
      //
      // square root the weights
      //
      for (int i = 0; i < Count; ++i) Weights[i] = (float)Math.Sqrt(Weights[i]);
    }
Exemple #9
0
    public static Vec3 operator*(Vec3 left, Vec3 right) {
      Vec3 copy = new Vec3(left);

      return multiply(copy, right);
    }
Exemple #10
0
    public static Vec3 operator-(Vec3 left, Vec3 right) {
      Vec3 copy = new Vec3(left);

      return subtract(copy, right);
    }
Exemple #11
0
    public static Vec3 operator+(Vec3 left, Vec3 right) {
      Vec3 copy = new Vec3(left);

      return add(copy, right);
    }
Exemple #12
0
 public Vec3(Vec3 copy) {
   x = copy.x;
   y = copy.y;
   z = copy.z;
 }
Exemple #13
0
 private static Vec3 divide(Vec3 left, float right) {
   return multiply(left, 1.0f / right);
 }
Exemple #14
0
    private static Vec3 multiply(Vec3 left, float right) {
      left.x *= right;
      left.y *= right;
      left.z *= right;

      return left;
    }
Exemple #15
0
    private static Vec3 multiply(Vec3 left, Vec3 right) {
      left.x *= right.x;
      left.y *= right.y;
      left.z *= right.z;

      return left;
    }
Exemple #16
0
        public ClusterFit(ColourSet Colours, SquishFlags Flags) : base(Colours, Flags)
        {
            //
            // initialise the metric
            //
            bool isPerceptual = (flags & SquishFlags.ColourMetricPerceptual) != 0;

            metric = isPerceptual ? new Vec3(0.2126f, 0.7152f, 0.0722f) : new Vec3(1.0f);
            //
            // initialise the best error
            //
            bestError = Single.MaxValue;
            //
            // cache some values
            //
            int count = colours.Count;

            Vec3[] values = colours.Points;

            float[] weights = colours.Weights;
            //
            // get the covariance matrix
            //
            Sym3x3 covariance = Maths.ComputeWeightedCovariance(count, values, weights);
            //
            // compute the principle component
            //
            Vec3 principle = Maths.ComputePrincipleComponent(covariance);
            //
            // get the min and max range as the codebook endpoints
            //
            Vec3 startTemp = new Vec3(0.0f);
            Vec3 endTemp   = new Vec3(0.0f);

            if (count > 0)
            {
                //
                // compute the range
                //
                startTemp = endTemp = values[0];

                float min = Vec3.Dot(values[0], principle);

                float max = min;

                for (int i = 1; i < count; ++i)
                {
                    float val = Vec3.Dot(values[i], principle);

                    if (val < min)
                    {
                        startTemp = values[i];

                        min = val;
                    }
                    else
                    {
                        if (val > max)
                        {
                            endTemp = values[i];

                            max = val;
                        }
                    }
                }
            }
            //
            // clamp the output to [0, 1]
            //
            Vec3 one  = new Vec3(1.0f);
            Vec3 zero = new Vec3(0.0f);

            startTemp = Vec3.Min(one, Vec3.Max(zero, startTemp));
            endTemp   = Vec3.Min(one, Vec3.Max(zero, endTemp));
            //
            // 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);

            start = Vec3.Truncate(grid * startTemp + half) * gridrcp;
            end   = Vec3.Truncate(grid * endTemp + half) * gridrcp;
        }
Exemple #17
0
    public static Vec3 operator*(float left, Vec3 right) {
      Vec3 copy = new Vec3(right);

      return multiply(copy, left);
    }
Exemple #18
0
    public static Vec3 operator/(Vec3 left, float right) {
      Vec3 copy = new Vec3(left);

      return divide(copy, right);
    }
Exemple #19
0
    protected override unsafe void Compress4(byte *block) {
      //
      // cache some values
      //
      int count = colours.Count;

      Vec3[] values = colours.Points;
      //
      // create a codebook
      //
      Vec3[] codes = new Vec3[4];

      codes[0] = start;
      codes[1] = end;
      codes[2] = 2.0f / 3.0f * start + 1.0f / 3.0f * end;
      codes[3] = 1.0f / 3.0f * start + 2.0f / 3.0f * end;
      //
      // match each point to the closest code
      //
      byte[] closest = new byte[16];

      float error = 0.0f;

      for(int i = 0; i < count; ++i) {
        //
        // find the closest code
        //
        float dist = Single.MaxValue;

        int idx = 0;

        for(int j = 0; j < 4; ++j) {
          float d = Vec3.LengthSquared(metric * (values[i] - codes[j]));

          if (d < dist) {
            dist = d;

            idx = j;
          }
        }
        //
        // save the index
        //
        closest[i] = (byte)idx;
        //
        // accumulate the error
        //
        error += dist;
      }
      //
      // save this scheme if it wins
      //
      if (error < bestError) {
        //
        // remap the indices
        //
        byte[] indices = new byte[16];

        colours.RemapIndices(closest, indices);
        //
        // save the block
        //
        ColourBlock.WriteColourBlock4(start, end, indices, block);
        //
        // save the error
        //
        bestError = error;
      }
    }
Exemple #20
0
 public static float Dot(Vec3 left, Vec3 right) {
   return left.x * right.x + left.y * right.y + left.z * right.z;
 }
Exemple #21
0
    private void computeEndPoints(SingleColourLookup[][] lookups) {
      //
      // check each index combination (endpoint or intermediate)
      //
      error = Int32.MaxValue;

      for(int i = 0; i < 2; ++i) {
        //
        // check the error for this codebook index
        //
        SourceBlock[] sources = new SourceBlock[3];

        int err = 0;

        for(int channel = 0; channel < 3; ++channel) {
          //
          // grab the lookup table and index for this channel
          //
          SingleColourLookup[] lookup = lookups[channel];

          int target = colour[channel];
          //
          // store a pointer to the source for this channel
          //
          sources[channel] = lookup[target].sources[i];
          //
          // accumulate the error
          //
          int diff = sources[channel].error;

          err += diff * diff;
        }
        //
        // keep it if the error is lower
        //
        if (err < error) {
          start = new Vec3(sources[0].start / 31.0f, sources[1].start / 63.0f, sources[2].start / 31.0f);

          end = new Vec3(sources[0].end / 31.0f, sources[1].end / 63.0f, sources[2].end / 31.0f);

          index = (byte)(2 * i);

          error = err;
        }
      }
    }
Exemple #22
0
    private static Vec3 add(Vec3 left, Vec3 right) {
      left.x += right.x;
      left.y += right.y;
      left.z += right.z;

      return left;
    }