Fix errors in new cluster fit compressor.

This commit is contained in:
castano
2012-01-02 08:49:13 +00:00
parent 23bfc1b514
commit f2d90ee844
16 changed files with 677 additions and 632 deletions

View File

@ -461,15 +461,30 @@ float ColorBlock::volume() const
}*/
void ColorSet::allocate(uint w, uint h)
{
nvDebugCheck(w <= 4 && h <= 4);
this->colorCount = w * h;
this->indexCount = 16;
this->w = 4;
this->h = 4;
//colors = new Vector4[colorCount];
//weights = new float[colorCount];
//indices = new int[indexCount];
}
// Allocate 4x4 block and fill with
void ColorSet::setColors(const float * data, uint img_w, uint img_h, uint img_x, uint img_y)
{
nvDebugCheck(img_x < img_w && img_y < img_h);
w = min(4U, img_w - img_x);
h = min(4U, img_h - img_y);
nvDebugCheck(w != 0 && h != 0);
const uint block_w = min(4U, img_w - img_x);
const uint block_h = min(4U, img_h - img_y);
nvDebugCheck(block_w != 0 && block_h != 0);
count = w * h;
allocate(block_w, block_h);
const float * r = data + img_w * img_h * 0;
const float * g = data + img_w * img_h * 1;
@ -477,9 +492,9 @@ void ColorSet::setColors(const float * data, uint img_w, uint img_h, uint img_x,
const float * a = data + img_w * img_h * 3;
// Set colors.
for (uint y = 0, i = 0; y < h; y++)
for (uint y = 0, i = 0; y < block_h; y++)
{
for (uint x = 0; x < w; x++, i++)
for (uint x = 0; x < block_w; x++, i++)
{
uint idx = x + img_x + (y + img_y) * img_w;
colors[i].x = r[idx];
@ -488,11 +503,25 @@ void ColorSet::setColors(const float * data, uint img_w, uint img_h, uint img_x,
colors[i].w = a[idx];
}
}
// Set default indices.
for (uint y = 0, i = 0; y < 4; y++)
{
for (uint x = 0; x < 4; x++)
{
if (x < block_w && y < block_h) {
indices[y*4+x] = i++;
}
else {
indices[y*4+x] = -1;
}
}
}
}
void ColorSet::setAlphaWeights()
{
for (uint i = 0; i < count; i++)
for (uint i = 0; i < colorCount; i++)
{
weights[i] = max(colors[i].w, 0.001f); // Avoid division by zero.
}
@ -500,72 +529,71 @@ void ColorSet::setAlphaWeights()
void ColorSet::setUniformWeights()
{
for (uint i = 0; i < count; i++)
for (uint i = 0; i < colorCount; i++)
{
weights[i] = 1.0f;
}
}
// @@ Handle complex blocks (not 4x4).
void ColorSet::createMinimalSet(bool ignoreTransparent)
{
nvDebugCheck(count == w*h); // Do not call this method multiple times.
nvDebugCheck(colorCount <= 16);
Vector4 C[16];
float W[16];
memcpy(C, colors, sizeof(Vector4)*count);
memcpy(W, weights, sizeof(float)*count);
memcpy(C, colors, sizeof(Vector4)*colorCount);
memcpy(W, weights, sizeof(float)*colorCount);
uint n = 0;
for (uint y = 0, i = 0; y < h; y++)
for (uint i = 0; i < indexCount; i++)
{
for (uint x = 0; x < w; x++, i++)
{
if (ignoreTransparent && C[i].w == 0) {
continue;
}
if (indices[i] < 0) {
continue;
}
uint idx = y * 4 + x;
Vector4 ci = C[indices[i]];
float wi = W[indices[i]];
// loop over previous points for a match
for (int j = 0; ; j++)
{
// allocate a new point
if (j == i)
{
colors[n] = C[i];
weights[n] = W[i];
remap[idx] = n;
n++;
break;
}
if (ignoreTransparent && ci.w == 0) {
indices[i] = -1;
continue;
}
// check for a match
bool colorMatch = (C[i].x == C[j].x) && (C[i].w == C[j].w) && (C[i].z == C[j].z);
//bool alphaMatch = (C[i].w == C[j].w);
// Find matching color.
uint j;
for (j = 0; j < n; j++) {
bool colorMatch = equal(colors[j].x, ci.x) && equal(colors[j].y, ci.y) && equal(colors[j].z, ci.z);
//bool alphaMatch = equal(colors[j].w, ci.w);
if (colorMatch)
{
// get the index of the match
int index = remap[j];
// map to this point and increase the weight
weights[index] += W[i];
remap[idx] = index;
break;
}
if (colorMatch) {
weights[j] += wi;
indices[i] = j;
break;
}
}
// No match found. Add new color.
if (j == n) {
colors[n] = ci;
weights[n] = wi;
indices[i] = n;
n++;
}
}
nvDebugCheck(n != 0);
for (uint i = n; i < colorCount; i++) {
weights[i] = 0;
}
count = n;
colorCount = n;
// Avoid empty blocks.
if (count == 0) {
count = 1;
//colors[0] = C[0];
//weights[0] = W[0];
memset(remap, 0, sizeof(int)*16);
if (colorCount == 0) {
colorCount = 1;
indices[0] = 0;
}
}
@ -578,7 +606,7 @@ void ColorSet::wrapIndices()
uint base = (y % h) * w;
for (uint x = w; x < 4; x++)
{
remap[y*4+3] = remap[base + (x % w)];
indices[y*4+3] = indices[base + (x % w)];
}
}
}
@ -588,7 +616,7 @@ bool ColorSet::isSingleColor(bool ignoreAlpha) const
Vector4 v = colors[0];
if (ignoreAlpha) v.w = 1.0f;
for (uint i = 1; i < count; i++)
for (uint i = 1; i < colorCount; i++)
{
Vector4 c = colors[i];
if (ignoreAlpha) c.w = 1.0f;
@ -615,7 +643,7 @@ static inline float component(Vector4::Arg c, uint i)
void ColorSet::swizzle(uint x, uint y, uint z, uint w)
{
for (uint i = 0; i < count; i++)
for (uint i = 0; i < colorCount; i++)
{
Vector4 c = colors[i];
colors[i].x = component(c, x);
@ -627,7 +655,7 @@ void ColorSet::swizzle(uint x, uint y, uint z, uint w)
bool ColorSet::hasAlpha() const
{
for (uint i = 0; i < count; i++)
for (uint i = 0; i < colorCount; i++)
{
if (colors[i].w != 0.0f) return true;
}

View File

@ -83,6 +83,11 @@ namespace nv
struct ColorSet
{
ColorSet() : colorCount(0), indexCount(0), w(0), h(0) {}
//~ColorSet() {}
void allocate(uint w, uint h);
void setColors(const float * data, uint img_w, uint img_h, uint img_x, uint img_y);
void setAlphaWeights();
@ -97,19 +102,22 @@ namespace nv
bool hasAlpha() const;
// These methods require indices to be set:
Vector4 color(uint x, uint y) const { nvDebugCheck(x < w && y < h); return colors[remap[y * 4 + x]]; }
Vector4 & color(uint x, uint y) { nvDebugCheck(x < w && y < h); return colors[remap[y * 4 + x]]; }
Vector4 color(uint x, uint y) const { nvDebugCheck(x < w && y < h); return colors[indices[y * 4 + x]]; }
Vector4 & color(uint x, uint y) { nvDebugCheck(x < w && y < h); return colors[indices[y * 4 + x]]; }
Vector4 color(uint i) const { nvDebugCheck(i < 16); return colors[remap[i]]; }
Vector4 & color(uint i) { nvDebugCheck(i < 16); return colors[remap[i]]; }
Vector4 color(uint i) const { nvDebugCheck(i < indexCount); return colors[indices[i]]; }
Vector4 & color(uint i) { nvDebugCheck(i < indexCount); return colors[indices[i]]; }
bool isValidIndex(uint i) const { return i < indexCount && indices[i] >= 0; }
uint count;
uint w, h;
uint colorCount;
uint indexCount; // Fixed to 16
uint w, h; // Fixed to 4x4
// Allocate color set dynamically and add support for sets larger than 4x4.
Vector4 colors[16];
float weights[16];
int remap[16];
int indices[16];
};
} // nv namespace