squish: Update to upstream 1.14
Sources are untouched, tarball from https://sourceforge.net/projects/libsquish
(cherry picked from commit 249836e530
)
This commit is contained in:
parent
1022705707
commit
8263fca121
5
thirdparty/README.md
vendored
5
thirdparty/README.md
vendored
@ -150,9 +150,8 @@ Files extracted from upstream source:
|
|||||||
|
|
||||||
## squish
|
## squish
|
||||||
|
|
||||||
- Upstream: https://code.google.com/archive/p/libsquish
|
- Upstream: https://sourceforge.net/projects/libsquish
|
||||||
and patches from https://github.com/Cavewhere/squish
|
- Version: 1.14
|
||||||
- Version: 1.11
|
|
||||||
- License: MIT
|
- License: MIT
|
||||||
|
|
||||||
Files extracted from upstream source:
|
Files extracted from upstream source:
|
||||||
|
583
thirdparty/squish/alpha.cpp
vendored
583
thirdparty/squish/alpha.cpp
vendored
@ -1,29 +1,30 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "alpha.h"
|
#include "alpha.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -31,319 +32,319 @@ namespace squish {
|
|||||||
|
|
||||||
static int FloatToInt( float a, int limit )
|
static int FloatToInt( float a, int limit )
|
||||||
{
|
{
|
||||||
// use ANSI round-to-zero behaviour to get round-to-nearest
|
// use ANSI round-to-zero behaviour to get round-to-nearest
|
||||||
int i = ( int )( a + 0.5f );
|
int i = ( int )( a + 0.5f );
|
||||||
|
|
||||||
// clamp to the limit
|
// clamp to the limit
|
||||||
if( i < 0 )
|
if( i < 0 )
|
||||||
i = 0;
|
i = 0;
|
||||||
else if( i > limit )
|
else if( i > limit )
|
||||||
i = limit;
|
i = limit;
|
||||||
|
|
||||||
// done
|
// done
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressAlphaDxt3( u8 const* rgba, int mask, void* block )
|
void CompressAlphaDxt3( u8 const* rgba, int mask, void* block )
|
||||||
{
|
{
|
||||||
u8* bytes = reinterpret_cast< u8* >( block );
|
u8* bytes = reinterpret_cast< u8* >( block );
|
||||||
|
|
||||||
// quantise and pack the alpha values pairwise
|
|
||||||
for( int i = 0; i < 8; ++i )
|
|
||||||
{
|
|
||||||
// quantise down to 4 bits
|
|
||||||
float alpha1 = ( float )rgba[8*i + 3] * ( 15.0f/255.0f );
|
|
||||||
float alpha2 = ( float )rgba[8*i + 7] * ( 15.0f/255.0f );
|
|
||||||
int quant1 = FloatToInt( alpha1, 15 );
|
|
||||||
int quant2 = FloatToInt( alpha2, 15 );
|
|
||||||
|
|
||||||
// set alpha to zero where masked
|
|
||||||
int bit1 = 1 << ( 2*i );
|
|
||||||
int bit2 = 1 << ( 2*i + 1 );
|
|
||||||
if( ( mask & bit1 ) == 0 )
|
|
||||||
quant1 = 0;
|
|
||||||
if( ( mask & bit2 ) == 0 )
|
|
||||||
quant2 = 0;
|
|
||||||
|
|
||||||
// pack into the byte
|
// quantise and pack the alpha values pairwise
|
||||||
bytes[i] = ( u8 )( quant1 | ( quant2 << 4 ) );
|
for( int i = 0; i < 8; ++i )
|
||||||
}
|
{
|
||||||
|
// quantise down to 4 bits
|
||||||
|
float alpha1 = ( float )rgba[8*i + 3] * ( 15.0f/255.0f );
|
||||||
|
float alpha2 = ( float )rgba[8*i + 7] * ( 15.0f/255.0f );
|
||||||
|
int quant1 = FloatToInt( alpha1, 15 );
|
||||||
|
int quant2 = FloatToInt( alpha2, 15 );
|
||||||
|
|
||||||
|
// set alpha to zero where masked
|
||||||
|
int bit1 = 1 << ( 2*i );
|
||||||
|
int bit2 = 1 << ( 2*i + 1 );
|
||||||
|
if( ( mask & bit1 ) == 0 )
|
||||||
|
quant1 = 0;
|
||||||
|
if( ( mask & bit2 ) == 0 )
|
||||||
|
quant2 = 0;
|
||||||
|
|
||||||
|
// pack into the byte
|
||||||
|
bytes[i] = ( u8 )( quant1 | ( quant2 << 4 ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompressAlphaDxt3( u8* rgba, void const* block )
|
void DecompressAlphaDxt3( u8* rgba, void const* block )
|
||||||
{
|
{
|
||||||
u8 const* bytes = reinterpret_cast< u8 const* >( block );
|
u8 const* bytes = reinterpret_cast< u8 const* >( block );
|
||||||
|
|
||||||
// unpack the alpha values pairwise
|
|
||||||
for( int i = 0; i < 8; ++i )
|
|
||||||
{
|
|
||||||
// quantise down to 4 bits
|
|
||||||
u8 quant = bytes[i];
|
|
||||||
|
|
||||||
// unpack the values
|
|
||||||
u8 lo = quant & 0x0f;
|
|
||||||
u8 hi = quant & 0xf0;
|
|
||||||
|
|
||||||
// convert back up to bytes
|
// unpack the alpha values pairwise
|
||||||
rgba[8*i + 3] = lo | ( lo << 4 );
|
for( int i = 0; i < 8; ++i )
|
||||||
rgba[8*i + 7] = hi | ( hi >> 4 );
|
{
|
||||||
}
|
// quantise down to 4 bits
|
||||||
|
u8 quant = bytes[i];
|
||||||
|
|
||||||
|
// unpack the values
|
||||||
|
u8 lo = quant & 0x0f;
|
||||||
|
u8 hi = quant & 0xf0;
|
||||||
|
|
||||||
|
// convert back up to bytes
|
||||||
|
rgba[8*i + 3] = lo | ( lo << 4 );
|
||||||
|
rgba[8*i + 7] = hi | ( hi >> 4 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FixRange( int& min, int& max, int steps )
|
static void FixRange( int& min, int& max, int steps )
|
||||||
{
|
{
|
||||||
if( max - min < steps )
|
if( max - min < steps )
|
||||||
max = std::min( min + steps, 255 );
|
max = std::min( min + steps, 255 );
|
||||||
if( max - min < steps )
|
if( max - min < steps )
|
||||||
min = std::max( 0, max - steps );
|
min = std::max( 0, max - steps );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FitCodes( u8 const* rgba, int mask, u8 const* codes, u8* indices )
|
static int FitCodes( u8 const* rgba, int mask, u8 const* codes, u8* indices )
|
||||||
{
|
{
|
||||||
// fit each alpha value to the codebook
|
// fit each alpha value to the codebook
|
||||||
int err = 0;
|
int err = 0;
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
// check this pixel is valid
|
// check this pixel is valid
|
||||||
int bit = 1 << i;
|
int bit = 1 << i;
|
||||||
if( ( mask & bit ) == 0 )
|
if( ( mask & bit ) == 0 )
|
||||||
{
|
{
|
||||||
// use the first code
|
// use the first code
|
||||||
indices[i] = 0;
|
indices[i] = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the least error and corresponding index
|
// find the least error and corresponding index
|
||||||
int value = rgba[4*i + 3];
|
int value = rgba[4*i + 3];
|
||||||
int least = INT_MAX;
|
int least = INT_MAX;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for( int j = 0; j < 8; ++j )
|
for( int j = 0; j < 8; ++j )
|
||||||
{
|
{
|
||||||
// get the squared error from this code
|
// get the squared error from this code
|
||||||
int dist = ( int )value - ( int )codes[j];
|
int dist = ( int )value - ( int )codes[j];
|
||||||
dist *= dist;
|
dist *= dist;
|
||||||
|
|
||||||
// compare with the best so far
|
// compare with the best so far
|
||||||
if( dist < least )
|
if( dist < least )
|
||||||
{
|
{
|
||||||
least = dist;
|
least = dist;
|
||||||
index = j;
|
index = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// save this index and accumulate the error
|
// save this index and accumulate the error
|
||||||
indices[i] = ( u8 )index;
|
indices[i] = ( u8 )index;
|
||||||
err += least;
|
err += least;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the total error
|
// return the total error
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteAlphaBlock( int alpha0, int alpha1, u8 const* indices, void* block )
|
static void WriteAlphaBlock( int alpha0, int alpha1, u8 const* indices, void* block )
|
||||||
{
|
{
|
||||||
u8* bytes = reinterpret_cast< u8* >( block );
|
u8* bytes = reinterpret_cast< u8* >( block );
|
||||||
|
|
||||||
// write the first two bytes
|
// write the first two bytes
|
||||||
bytes[0] = ( u8 )alpha0;
|
bytes[0] = ( u8 )alpha0;
|
||||||
bytes[1] = ( u8 )alpha1;
|
bytes[1] = ( u8 )alpha1;
|
||||||
|
|
||||||
// pack the indices with 3 bits each
|
// pack the indices with 3 bits each
|
||||||
u8* dest = bytes + 2;
|
u8* dest = bytes + 2;
|
||||||
u8 const* src = indices;
|
u8 const* src = indices;
|
||||||
for( int i = 0; i < 2; ++i )
|
for( int i = 0; i < 2; ++i )
|
||||||
{
|
{
|
||||||
// pack 8 3-bit values
|
// pack 8 3-bit values
|
||||||
int value = 0;
|
int value = 0;
|
||||||
for( int j = 0; j < 8; ++j )
|
for( int j = 0; j < 8; ++j )
|
||||||
{
|
{
|
||||||
int index = *src++;
|
int index = *src++;
|
||||||
value |= ( index << 3*j );
|
value |= ( index << 3*j );
|
||||||
}
|
}
|
||||||
|
|
||||||
// store in 3 bytes
|
// store in 3 bytes
|
||||||
for( int j = 0; j < 3; ++j )
|
for( int j = 0; j < 3; ++j )
|
||||||
{
|
{
|
||||||
int byte = ( value >> 8*j ) & 0xff;
|
int byte = ( value >> 8*j ) & 0xff;
|
||||||
*dest++ = ( u8 )byte;
|
*dest++ = ( u8 )byte;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteAlphaBlock5( int alpha0, int alpha1, u8 const* indices, void* block )
|
static void WriteAlphaBlock5( int alpha0, int alpha1, u8 const* indices, void* block )
|
||||||
{
|
{
|
||||||
// check the relative values of the endpoints
|
// check the relative values of the endpoints
|
||||||
if( alpha0 > alpha1 )
|
if( alpha0 > alpha1 )
|
||||||
{
|
{
|
||||||
// swap the indices
|
// swap the indices
|
||||||
u8 swapped[16];
|
u8 swapped[16];
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
u8 index = indices[i];
|
u8 index = indices[i];
|
||||||
if( index == 0 )
|
if( index == 0 )
|
||||||
swapped[i] = 1;
|
swapped[i] = 1;
|
||||||
else if( index == 1 )
|
else if( index == 1 )
|
||||||
swapped[i] = 0;
|
swapped[i] = 0;
|
||||||
else if( index <= 5 )
|
else if( index <= 5 )
|
||||||
swapped[i] = 7 - index;
|
swapped[i] = 7 - index;
|
||||||
else
|
else
|
||||||
swapped[i] = index;
|
swapped[i] = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the block
|
// write the block
|
||||||
WriteAlphaBlock( alpha1, alpha0, swapped, block );
|
WriteAlphaBlock( alpha1, alpha0, swapped, block );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// write the block
|
// write the block
|
||||||
WriteAlphaBlock( alpha0, alpha1, indices, block );
|
WriteAlphaBlock( alpha0, alpha1, indices, block );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteAlphaBlock7( int alpha0, int alpha1, u8 const* indices, void* block )
|
static void WriteAlphaBlock7( int alpha0, int alpha1, u8 const* indices, void* block )
|
||||||
{
|
{
|
||||||
// check the relative values of the endpoints
|
// check the relative values of the endpoints
|
||||||
if( alpha0 < alpha1 )
|
if( alpha0 < alpha1 )
|
||||||
{
|
{
|
||||||
// swap the indices
|
// swap the indices
|
||||||
u8 swapped[16];
|
u8 swapped[16];
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
u8 index = indices[i];
|
u8 index = indices[i];
|
||||||
if( index == 0 )
|
if( index == 0 )
|
||||||
swapped[i] = 1;
|
swapped[i] = 1;
|
||||||
else if( index == 1 )
|
else if( index == 1 )
|
||||||
swapped[i] = 0;
|
swapped[i] = 0;
|
||||||
else
|
else
|
||||||
swapped[i] = 9 - index;
|
swapped[i] = 9 - index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the block
|
// write the block
|
||||||
WriteAlphaBlock( alpha1, alpha0, swapped, block );
|
WriteAlphaBlock( alpha1, alpha0, swapped, block );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// write the block
|
// write the block
|
||||||
WriteAlphaBlock( alpha0, alpha1, indices, block );
|
WriteAlphaBlock( alpha0, alpha1, indices, block );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressAlphaDxt5( u8 const* rgba, int mask, void* block )
|
void CompressAlphaDxt5( u8 const* rgba, int mask, void* block )
|
||||||
{
|
{
|
||||||
// get the range for 5-alpha and 7-alpha interpolation
|
// get the range for 5-alpha and 7-alpha interpolation
|
||||||
int min5 = 255;
|
int min5 = 255;
|
||||||
int max5 = 0;
|
int max5 = 0;
|
||||||
int min7 = 255;
|
int min7 = 255;
|
||||||
int max7 = 0;
|
int max7 = 0;
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
// check this pixel is valid
|
// check this pixel is valid
|
||||||
int bit = 1 << i;
|
int bit = 1 << i;
|
||||||
if( ( mask & bit ) == 0 )
|
if( ( mask & bit ) == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// incorporate into the min/max
|
// incorporate into the min/max
|
||||||
int value = rgba[4*i + 3];
|
int value = rgba[4*i + 3];
|
||||||
if( value < min7 )
|
if( value < min7 )
|
||||||
min7 = value;
|
min7 = value;
|
||||||
if( value > max7 )
|
if( value > max7 )
|
||||||
max7 = value;
|
max7 = value;
|
||||||
if( value != 0 && value < min5 )
|
if( value != 0 && value < min5 )
|
||||||
min5 = value;
|
min5 = value;
|
||||||
if( value != 255 && value > max5 )
|
if( value != 255 && value > max5 )
|
||||||
max5 = value;
|
max5 = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle the case that no valid range was found
|
// handle the case that no valid range was found
|
||||||
if( min5 > max5 )
|
if( min5 > max5 )
|
||||||
min5 = max5;
|
min5 = max5;
|
||||||
if( min7 > max7 )
|
if( min7 > max7 )
|
||||||
min7 = max7;
|
min7 = max7;
|
||||||
|
|
||||||
// fix the range to be the minimum in each case
|
// fix the range to be the minimum in each case
|
||||||
FixRange( min5, max5, 5 );
|
FixRange( min5, max5, 5 );
|
||||||
FixRange( min7, max7, 7 );
|
FixRange( min7, max7, 7 );
|
||||||
|
|
||||||
// set up the 5-alpha code book
|
// set up the 5-alpha code book
|
||||||
u8 codes5[8];
|
u8 codes5[8];
|
||||||
codes5[0] = ( u8 )min5;
|
codes5[0] = ( u8 )min5;
|
||||||
codes5[1] = ( u8 )max5;
|
codes5[1] = ( u8 )max5;
|
||||||
for( int i = 1; i < 5; ++i )
|
for( int i = 1; i < 5; ++i )
|
||||||
codes5[1 + i] = ( u8 )( ( ( 5 - i )*min5 + i*max5 )/5 );
|
codes5[1 + i] = ( u8 )( ( ( 5 - i )*min5 + i*max5 )/5 );
|
||||||
codes5[6] = 0;
|
codes5[6] = 0;
|
||||||
codes5[7] = 255;
|
codes5[7] = 255;
|
||||||
|
|
||||||
// set up the 7-alpha code book
|
// set up the 7-alpha code book
|
||||||
u8 codes7[8];
|
u8 codes7[8];
|
||||||
codes7[0] = ( u8 )min7;
|
codes7[0] = ( u8 )min7;
|
||||||
codes7[1] = ( u8 )max7;
|
codes7[1] = ( u8 )max7;
|
||||||
for( int i = 1; i < 7; ++i )
|
for( int i = 1; i < 7; ++i )
|
||||||
codes7[1 + i] = ( u8 )( ( ( 7 - i )*min7 + i*max7 )/7 );
|
codes7[1 + i] = ( u8 )( ( ( 7 - i )*min7 + i*max7 )/7 );
|
||||||
|
|
||||||
// fit the data to both code books
|
// fit the data to both code books
|
||||||
u8 indices5[16];
|
u8 indices5[16];
|
||||||
u8 indices7[16];
|
u8 indices7[16];
|
||||||
int err5 = FitCodes( rgba, mask, codes5, indices5 );
|
int err5 = FitCodes( rgba, mask, codes5, indices5 );
|
||||||
int err7 = FitCodes( rgba, mask, codes7, indices7 );
|
int err7 = FitCodes( rgba, mask, codes7, indices7 );
|
||||||
|
|
||||||
// save the block with least error
|
// save the block with least error
|
||||||
if( err5 <= err7 )
|
if( err5 <= err7 )
|
||||||
WriteAlphaBlock5( min5, max5, indices5, block );
|
WriteAlphaBlock5( min5, max5, indices5, block );
|
||||||
else
|
else
|
||||||
WriteAlphaBlock7( min7, max7, indices7, block );
|
WriteAlphaBlock7( min7, max7, indices7, block );
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompressAlphaDxt5( u8* rgba, void const* block )
|
void DecompressAlphaDxt5( u8* rgba, void const* block )
|
||||||
{
|
{
|
||||||
// get the two alpha values
|
// get the two alpha values
|
||||||
u8 const* bytes = reinterpret_cast< u8 const* >( block );
|
u8 const* bytes = reinterpret_cast< u8 const* >( block );
|
||||||
int alpha0 = bytes[0];
|
int alpha0 = bytes[0];
|
||||||
int alpha1 = bytes[1];
|
int alpha1 = bytes[1];
|
||||||
|
|
||||||
// compare the values to build the codebook
|
// compare the values to build the codebook
|
||||||
u8 codes[8];
|
u8 codes[8];
|
||||||
codes[0] = ( u8 )alpha0;
|
codes[0] = ( u8 )alpha0;
|
||||||
codes[1] = ( u8 )alpha1;
|
codes[1] = ( u8 )alpha1;
|
||||||
if( alpha0 <= alpha1 )
|
if( alpha0 <= alpha1 )
|
||||||
{
|
{
|
||||||
// use 5-alpha codebook
|
// use 5-alpha codebook
|
||||||
for( int i = 1; i < 5; ++i )
|
for( int i = 1; i < 5; ++i )
|
||||||
codes[1 + i] = ( u8 )( ( ( 5 - i )*alpha0 + i*alpha1 )/5 );
|
codes[1 + i] = ( u8 )( ( ( 5 - i )*alpha0 + i*alpha1 )/5 );
|
||||||
codes[6] = 0;
|
codes[6] = 0;
|
||||||
codes[7] = 255;
|
codes[7] = 255;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// use 7-alpha codebook
|
// use 7-alpha codebook
|
||||||
for( int i = 1; i < 7; ++i )
|
for( int i = 1; i < 7; ++i )
|
||||||
codes[1 + i] = ( u8 )( ( ( 7 - i )*alpha0 + i*alpha1 )/7 );
|
codes[1 + i] = ( u8 )( ( ( 7 - i )*alpha0 + i*alpha1 )/7 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode the indices
|
// decode the indices
|
||||||
u8 indices[16];
|
u8 indices[16];
|
||||||
u8 const* src = bytes + 2;
|
u8 const* src = bytes + 2;
|
||||||
u8* dest = indices;
|
u8* dest = indices;
|
||||||
for( int i = 0; i < 2; ++i )
|
for( int i = 0; i < 2; ++i )
|
||||||
{
|
{
|
||||||
// grab 3 bytes
|
// grab 3 bytes
|
||||||
int value = 0;
|
int value = 0;
|
||||||
for( int j = 0; j < 3; ++j )
|
for( int j = 0; j < 3; ++j )
|
||||||
{
|
{
|
||||||
int byte = *src++;
|
int byte = *src++;
|
||||||
value |= ( byte << 8*j );
|
value |= ( byte << 8*j );
|
||||||
}
|
}
|
||||||
|
|
||||||
// unpack 8 3-bit values from it
|
// unpack 8 3-bit values from it
|
||||||
for( int j = 0; j < 8; ++j )
|
for( int j = 0; j < 8; ++j )
|
||||||
{
|
{
|
||||||
int index = ( value >> 3*j ) & 0x7;
|
int index = ( value >> 3*j ) & 0x7;
|
||||||
*dest++ = ( u8 )index;
|
*dest++ = ( u8 )index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write out the indexed codebook values
|
// write out the indexed codebook values
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
rgba[4*i + 3] = codes[indices[i]];
|
rgba[4*i + 3] = codes[indices[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
40
thirdparty/squish/alpha.h
vendored
40
thirdparty/squish/alpha.h
vendored
@ -1,32 +1,32 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_ALPHA_H
|
#ifndef SQUISH_ALPHA_H
|
||||||
#define SQUISH_ALPHA_H
|
#define SQUISH_ALPHA_H
|
||||||
|
|
||||||
#include <squish.h>
|
#include "squish.h"
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
|
667
thirdparty/squish/clusterfit.cpp
vendored
667
thirdparty/squish/clusterfit.cpp
vendored
@ -1,29 +1,29 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
Copyright (c) 2007 Ignacio Castano icastano@nvidia.com
|
Copyright (c) 2007 Ignacio Castano icastano@nvidia.com
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "clusterfit.h"
|
#include "clusterfit.h"
|
||||||
#include "colourset.h"
|
#include "colourset.h"
|
||||||
#include "colourblock.h"
|
#include "colourblock.h"
|
||||||
@ -31,363 +31,362 @@
|
|||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
ClusterFit::ClusterFit( ColourSet const* colours, int flags )
|
ClusterFit::ClusterFit( ColourSet const* colours, int flags, float* metric )
|
||||||
: ColourFit( colours, flags )
|
: ColourFit( colours, flags )
|
||||||
{
|
{
|
||||||
// set the iteration count
|
// set the iteration count
|
||||||
m_iterationCount = ( m_flags & kColourIterativeClusterFit ) ? kMaxIterations : 1;
|
m_iterationCount = ( m_flags & kColourIterativeClusterFit ) ? kMaxIterations : 1;
|
||||||
|
|
||||||
// initialise the best error
|
// initialise the metric (old perceptual = 0.2126f, 0.7152f, 0.0722f)
|
||||||
m_besterror = VEC4_CONST( FLT_MAX );
|
if( metric )
|
||||||
|
m_metric = Vec4( metric[0], metric[1], metric[2], 1.0f );
|
||||||
|
else
|
||||||
|
m_metric = VEC4_CONST( 1.0f );
|
||||||
|
|
||||||
// initialise the metric
|
// initialise the best error
|
||||||
bool perceptual = ( ( m_flags & kColourMetricPerceptual ) != 0 );
|
m_besterror = VEC4_CONST( FLT_MAX );
|
||||||
if( perceptual )
|
|
||||||
m_metric = Vec4( 0.2126f, 0.7152f, 0.0722f, 0.0f );
|
|
||||||
else
|
|
||||||
m_metric = VEC4_CONST( 1.0f );
|
|
||||||
|
|
||||||
// cache some values
|
// cache some values
|
||||||
int const count = m_colours->GetCount();
|
int const count = m_colours->GetCount();
|
||||||
Vec3 const* values = m_colours->GetPoints();
|
Vec3 const* values = m_colours->GetPoints();
|
||||||
|
|
||||||
// get the covariance matrix
|
// get the covariance matrix
|
||||||
Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() );
|
Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() );
|
||||||
|
|
||||||
// compute the principle component
|
// compute the principle component
|
||||||
m_principle = ComputePrincipleComponent( covariance );
|
m_principle = ComputePrincipleComponent( covariance );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClusterFit::ConstructOrdering( Vec3 const& axis, int iteration )
|
bool ClusterFit::ConstructOrdering( Vec3 const& axis, int iteration )
|
||||||
{
|
{
|
||||||
// cache some values
|
// cache some values
|
||||||
int const count = m_colours->GetCount();
|
int const count = m_colours->GetCount();
|
||||||
Vec3 const* values = m_colours->GetPoints();
|
Vec3 const* values = m_colours->GetPoints();
|
||||||
|
|
||||||
// build the list of dot products
|
// build the list of dot products
|
||||||
float dps[16];
|
float dps[16];
|
||||||
u8* order = ( u8* )m_order + 16*iteration;
|
u8* order = ( u8* )m_order + 16*iteration;
|
||||||
for( int i = 0; i < count; ++i )
|
for( int i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
dps[i] = Dot( values[i], axis );
|
dps[i] = Dot( values[i], axis );
|
||||||
order[i] = ( u8 )i;
|
order[i] = ( u8 )i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stable sort using them
|
// stable sort using them
|
||||||
for( int i = 0; i < count; ++i )
|
for( int i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j )
|
for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j )
|
||||||
{
|
{
|
||||||
std::swap( dps[j], dps[j - 1] );
|
std::swap( dps[j], dps[j - 1] );
|
||||||
std::swap( order[j], order[j - 1] );
|
std::swap( order[j], order[j - 1] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check this ordering is unique
|
// check this ordering is unique
|
||||||
for( int it = 0; it < iteration; ++it )
|
for( int it = 0; it < iteration; ++it )
|
||||||
{
|
{
|
||||||
u8 const* prev = ( u8* )m_order + 16*it;
|
u8 const* prev = ( u8* )m_order + 16*it;
|
||||||
bool same = true;
|
bool same = true;
|
||||||
for( int i = 0; i < count; ++i )
|
for( int i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
if( order[i] != prev[i] )
|
if( order[i] != prev[i] )
|
||||||
{
|
{
|
||||||
same = false;
|
same = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( same )
|
if( same )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the ordering and weight all the points
|
// copy the ordering and weight all the points
|
||||||
Vec3 const* unweighted = m_colours->GetPoints();
|
Vec3 const* unweighted = m_colours->GetPoints();
|
||||||
float const* weights = m_colours->GetWeights();
|
float const* weights = m_colours->GetWeights();
|
||||||
m_xsum_wsum = VEC4_CONST( 0.0f );
|
m_xsum_wsum = VEC4_CONST( 0.0f );
|
||||||
for( int i = 0; i < count; ++i )
|
for( int i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
int j = order[i];
|
int j = order[i];
|
||||||
Vec4 p( unweighted[j].X(), unweighted[j].Y(), unweighted[j].Z(), 1.0f );
|
Vec4 p( unweighted[j].X(), unweighted[j].Y(), unweighted[j].Z(), 1.0f );
|
||||||
Vec4 w( weights[j] );
|
Vec4 w( weights[j] );
|
||||||
Vec4 x = p*w;
|
Vec4 x = p*w;
|
||||||
m_points_weights[i] = x;
|
m_points_weights[i] = x;
|
||||||
m_xsum_wsum += x;
|
m_xsum_wsum += x;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterFit::Compress3( void* block )
|
void ClusterFit::Compress3( void* block )
|
||||||
{
|
{
|
||||||
// declare variables
|
// declare variables
|
||||||
int const count = m_colours->GetCount();
|
int const count = m_colours->GetCount();
|
||||||
Vec4 const two = VEC4_CONST( 2.0 );
|
Vec4 const two = VEC4_CONST( 2.0 );
|
||||||
Vec4 const one = VEC4_CONST( 1.0f );
|
Vec4 const one = VEC4_CONST( 1.0f );
|
||||||
Vec4 const half_half2( 0.5f, 0.5f, 0.5f, 0.25f );
|
Vec4 const half_half2( 0.5f, 0.5f, 0.5f, 0.25f );
|
||||||
Vec4 const zero = VEC4_CONST( 0.0f );
|
Vec4 const zero = VEC4_CONST( 0.0f );
|
||||||
Vec4 const half = VEC4_CONST( 0.5f );
|
Vec4 const half = VEC4_CONST( 0.5f );
|
||||||
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
|
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
|
||||||
Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f );
|
Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f );
|
||||||
|
|
||||||
// prepare an ordering using the principle axis
|
// prepare an ordering using the principle axis
|
||||||
ConstructOrdering( m_principle, 0 );
|
ConstructOrdering( m_principle, 0 );
|
||||||
|
|
||||||
// check all possible clusters and iterate on the total order
|
|
||||||
Vec4 beststart = VEC4_CONST( 0.0f );
|
|
||||||
Vec4 bestend = VEC4_CONST( 0.0f );
|
|
||||||
Vec4 besterror = m_besterror;
|
|
||||||
u8 bestindices[16];
|
|
||||||
int bestiteration = 0;
|
|
||||||
int besti = 0, bestj = 0;
|
|
||||||
|
|
||||||
// loop over iterations (we avoid the case that all points in first or last cluster)
|
|
||||||
for( int iterationIndex = 0;; )
|
|
||||||
{
|
|
||||||
// first cluster [0,i) is at the start
|
|
||||||
Vec4 part0 = VEC4_CONST( 0.0f );
|
|
||||||
for( int i = 0; i < count; ++i )
|
|
||||||
{
|
|
||||||
// second cluster [i,j) is half along
|
|
||||||
Vec4 part1 = ( i == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f );
|
|
||||||
int jmin = ( i == 0 ) ? 1 : i;
|
|
||||||
for( int j = jmin;; )
|
|
||||||
{
|
|
||||||
// last cluster [j,count) is at the end
|
|
||||||
Vec4 part2 = m_xsum_wsum - part1 - part0;
|
|
||||||
|
|
||||||
// compute least squares terms directly
|
|
||||||
Vec4 alphax_sum = MultiplyAdd( part1, half_half2, part0 );
|
|
||||||
Vec4 alpha2_sum = alphax_sum.SplatW();
|
|
||||||
|
|
||||||
Vec4 betax_sum = MultiplyAdd( part1, half_half2, part2 );
|
// check all possible clusters and iterate on the total order
|
||||||
Vec4 beta2_sum = betax_sum.SplatW();
|
Vec4 beststart = VEC4_CONST( 0.0f );
|
||||||
|
Vec4 bestend = VEC4_CONST( 0.0f );
|
||||||
|
Vec4 besterror = m_besterror;
|
||||||
|
u8 bestindices[16];
|
||||||
|
int bestiteration = 0;
|
||||||
|
int besti = 0, bestj = 0;
|
||||||
|
|
||||||
Vec4 alphabeta_sum = ( part1*half_half2 ).SplatW();
|
// loop over iterations (we avoid the case that all points in first or last cluster)
|
||||||
|
for( int iterationIndex = 0;; )
|
||||||
|
{
|
||||||
|
// first cluster [0,i) is at the start
|
||||||
|
Vec4 part0 = VEC4_CONST( 0.0f );
|
||||||
|
for( int i = 0; i < count; ++i )
|
||||||
|
{
|
||||||
|
// second cluster [i,j) is half along
|
||||||
|
Vec4 part1 = ( i == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f );
|
||||||
|
int jmin = ( i == 0 ) ? 1 : i;
|
||||||
|
for( int j = jmin;; )
|
||||||
|
{
|
||||||
|
// last cluster [j,count) is at the end
|
||||||
|
Vec4 part2 = m_xsum_wsum - part1 - part0;
|
||||||
|
|
||||||
// compute the least-squares optimal points
|
// compute least squares terms directly
|
||||||
Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) );
|
Vec4 alphax_sum = MultiplyAdd( part1, half_half2, part0 );
|
||||||
Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor;
|
Vec4 alpha2_sum = alphax_sum.SplatW();
|
||||||
Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor;
|
|
||||||
|
|
||||||
// clamp to the grid
|
Vec4 betax_sum = MultiplyAdd( part1, half_half2, part2 );
|
||||||
a = Min( one, Max( zero, a ) );
|
Vec4 beta2_sum = betax_sum.SplatW();
|
||||||
b = Min( one, Max( zero, b ) );
|
|
||||||
a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp;
|
|
||||||
b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp;
|
|
||||||
|
|
||||||
// compute the error (we skip the constant xxsum)
|
|
||||||
Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
|
|
||||||
Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum );
|
|
||||||
Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 );
|
|
||||||
Vec4 e4 = MultiplyAdd( two, e3, e1 );
|
|
||||||
|
|
||||||
// apply the metric to the error term
|
Vec4 alphabeta_sum = ( part1*half_half2 ).SplatW();
|
||||||
Vec4 e5 = e4*m_metric;
|
|
||||||
Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ();
|
|
||||||
|
|
||||||
// keep the solution if it wins
|
|
||||||
if( CompareAnyLessThan( error, besterror ) )
|
|
||||||
{
|
|
||||||
beststart = a;
|
|
||||||
bestend = b;
|
|
||||||
besti = i;
|
|
||||||
bestj = j;
|
|
||||||
besterror = error;
|
|
||||||
bestiteration = iterationIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// advance
|
// compute the least-squares optimal points
|
||||||
if( j == count )
|
Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) );
|
||||||
break;
|
Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor;
|
||||||
part1 += m_points_weights[j];
|
Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor;
|
||||||
++j;
|
|
||||||
}
|
|
||||||
|
|
||||||
// advance
|
// clamp to the grid
|
||||||
part0 += m_points_weights[i];
|
a = Min( one, Max( zero, a ) );
|
||||||
}
|
b = Min( one, Max( zero, b ) );
|
||||||
|
a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp;
|
||||||
// stop if we didn't improve in this iteration
|
b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp;
|
||||||
if( bestiteration != iterationIndex )
|
|
||||||
break;
|
|
||||||
|
|
||||||
// advance if possible
|
|
||||||
++iterationIndex;
|
|
||||||
if( iterationIndex == m_iterationCount )
|
|
||||||
break;
|
|
||||||
|
|
||||||
// stop if a new iteration is an ordering that has already been tried
|
|
||||||
Vec3 axis = ( bestend - beststart ).GetVec3();
|
|
||||||
if( !ConstructOrdering( axis, iterationIndex ) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the block if necessary
|
|
||||||
if( CompareAnyLessThan( besterror, m_besterror ) )
|
|
||||||
{
|
|
||||||
// remap the indices
|
|
||||||
u8 const* order = ( u8* )m_order + 16*bestiteration;
|
|
||||||
|
|
||||||
u8 unordered[16];
|
// compute the error (we skip the constant xxsum)
|
||||||
for( int m = 0; m < besti; ++m )
|
Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
|
||||||
unordered[order[m]] = 0;
|
Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum );
|
||||||
for( int m = besti; m < bestj; ++m )
|
Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 );
|
||||||
unordered[order[m]] = 2;
|
Vec4 e4 = MultiplyAdd( two, e3, e1 );
|
||||||
for( int m = bestj; m < count; ++m )
|
|
||||||
unordered[order[m]] = 1;
|
|
||||||
|
|
||||||
m_colours->RemapIndices( unordered, bestindices );
|
// apply the metric to the error term
|
||||||
|
Vec4 e5 = e4*m_metric;
|
||||||
// save the block
|
Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ();
|
||||||
WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
|
|
||||||
|
|
||||||
// save the error
|
// keep the solution if it wins
|
||||||
m_besterror = besterror;
|
if( CompareAnyLessThan( error, besterror ) )
|
||||||
}
|
{
|
||||||
|
beststart = a;
|
||||||
|
bestend = b;
|
||||||
|
besti = i;
|
||||||
|
bestj = j;
|
||||||
|
besterror = error;
|
||||||
|
bestiteration = iterationIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance
|
||||||
|
if( j == count )
|
||||||
|
break;
|
||||||
|
part1 += m_points_weights[j];
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance
|
||||||
|
part0 += m_points_weights[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop if we didn't improve in this iteration
|
||||||
|
if( bestiteration != iterationIndex )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// advance if possible
|
||||||
|
++iterationIndex;
|
||||||
|
if( iterationIndex == m_iterationCount )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// stop if a new iteration is an ordering that has already been tried
|
||||||
|
Vec3 axis = ( bestend - beststart ).GetVec3();
|
||||||
|
if( !ConstructOrdering( axis, iterationIndex ) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the block if necessary
|
||||||
|
if( CompareAnyLessThan( besterror, m_besterror ) )
|
||||||
|
{
|
||||||
|
// remap the indices
|
||||||
|
u8 const* order = ( u8* )m_order + 16*bestiteration;
|
||||||
|
|
||||||
|
u8 unordered[16];
|
||||||
|
for( int m = 0; m < besti; ++m )
|
||||||
|
unordered[order[m]] = 0;
|
||||||
|
for( int m = besti; m < bestj; ++m )
|
||||||
|
unordered[order[m]] = 2;
|
||||||
|
for( int m = bestj; m < count; ++m )
|
||||||
|
unordered[order[m]] = 1;
|
||||||
|
|
||||||
|
m_colours->RemapIndices( unordered, bestindices );
|
||||||
|
|
||||||
|
// save the block
|
||||||
|
WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
|
||||||
|
|
||||||
|
// save the error
|
||||||
|
m_besterror = besterror;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClusterFit::Compress4( void* block )
|
void ClusterFit::Compress4( void* block )
|
||||||
{
|
{
|
||||||
// declare variables
|
// declare variables
|
||||||
int const count = m_colours->GetCount();
|
int const count = m_colours->GetCount();
|
||||||
Vec4 const two = VEC4_CONST( 2.0f );
|
Vec4 const two = VEC4_CONST( 2.0f );
|
||||||
Vec4 const one = VEC4_CONST( 1.0f );
|
Vec4 const one = VEC4_CONST( 1.0f );
|
||||||
Vec4 const onethird_onethird2( 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/9.0f );
|
Vec4 const onethird_onethird2( 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/9.0f );
|
||||||
Vec4 const twothirds_twothirds2( 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, 4.0f/9.0f );
|
Vec4 const twothirds_twothirds2( 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, 4.0f/9.0f );
|
||||||
Vec4 const twonineths = VEC4_CONST( 2.0f/9.0f );
|
Vec4 const twonineths = VEC4_CONST( 2.0f/9.0f );
|
||||||
Vec4 const zero = VEC4_CONST( 0.0f );
|
Vec4 const zero = VEC4_CONST( 0.0f );
|
||||||
Vec4 const half = VEC4_CONST( 0.5f );
|
Vec4 const half = VEC4_CONST( 0.5f );
|
||||||
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
|
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
|
||||||
Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f );
|
Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f );
|
||||||
|
|
||||||
// prepare an ordering using the principle axis
|
// prepare an ordering using the principle axis
|
||||||
ConstructOrdering( m_principle, 0 );
|
ConstructOrdering( m_principle, 0 );
|
||||||
|
|
||||||
// check all possible clusters and iterate on the total order
|
|
||||||
Vec4 beststart = VEC4_CONST( 0.0f );
|
|
||||||
Vec4 bestend = VEC4_CONST( 0.0f );
|
|
||||||
Vec4 besterror = m_besterror;
|
|
||||||
u8 bestindices[16];
|
|
||||||
int bestiteration = 0;
|
|
||||||
int besti = 0, bestj = 0, bestk = 0;
|
|
||||||
|
|
||||||
// loop over iterations (we avoid the case that all points in first or last cluster)
|
|
||||||
for( int iterationIndex = 0;; )
|
|
||||||
{
|
|
||||||
// first cluster [0,i) is at the start
|
|
||||||
Vec4 part0 = VEC4_CONST( 0.0f );
|
|
||||||
for( int i = 0; i < count; ++i )
|
|
||||||
{
|
|
||||||
// second cluster [i,j) is one third along
|
|
||||||
Vec4 part1 = VEC4_CONST( 0.0f );
|
|
||||||
for( int j = i;; )
|
|
||||||
{
|
|
||||||
// third cluster [j,k) is two thirds along
|
|
||||||
Vec4 part2 = ( j == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f );
|
|
||||||
int kmin = ( j == 0 ) ? 1 : j;
|
|
||||||
for( int k = kmin;; )
|
|
||||||
{
|
|
||||||
// last cluster [k,count) is at the end
|
|
||||||
Vec4 part3 = m_xsum_wsum - part2 - part1 - part0;
|
|
||||||
|
|
||||||
// compute least squares terms directly
|
// check all possible clusters and iterate on the total order
|
||||||
Vec4 const alphax_sum = MultiplyAdd( part2, onethird_onethird2, MultiplyAdd( part1, twothirds_twothirds2, part0 ) );
|
Vec4 beststart = VEC4_CONST( 0.0f );
|
||||||
Vec4 const alpha2_sum = alphax_sum.SplatW();
|
Vec4 bestend = VEC4_CONST( 0.0f );
|
||||||
|
Vec4 besterror = m_besterror;
|
||||||
Vec4 const betax_sum = MultiplyAdd( part1, onethird_onethird2, MultiplyAdd( part2, twothirds_twothirds2, part3 ) );
|
u8 bestindices[16];
|
||||||
Vec4 const beta2_sum = betax_sum.SplatW();
|
int bestiteration = 0;
|
||||||
|
int besti = 0, bestj = 0, bestk = 0;
|
||||||
Vec4 const alphabeta_sum = twonineths*( part1 + part2 ).SplatW();
|
|
||||||
|
|
||||||
// compute the least-squares optimal points
|
// loop over iterations (we avoid the case that all points in first or last cluster)
|
||||||
Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) );
|
for( int iterationIndex = 0;; )
|
||||||
Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor;
|
{
|
||||||
Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor;
|
// first cluster [0,i) is at the start
|
||||||
|
Vec4 part0 = VEC4_CONST( 0.0f );
|
||||||
|
for( int i = 0; i < count; ++i )
|
||||||
|
{
|
||||||
|
// second cluster [i,j) is one third along
|
||||||
|
Vec4 part1 = VEC4_CONST( 0.0f );
|
||||||
|
for( int j = i;; )
|
||||||
|
{
|
||||||
|
// third cluster [j,k) is two thirds along
|
||||||
|
Vec4 part2 = ( j == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f );
|
||||||
|
int kmin = ( j == 0 ) ? 1 : j;
|
||||||
|
for( int k = kmin;; )
|
||||||
|
{
|
||||||
|
// last cluster [k,count) is at the end
|
||||||
|
Vec4 part3 = m_xsum_wsum - part2 - part1 - part0;
|
||||||
|
|
||||||
// clamp to the grid
|
// compute least squares terms directly
|
||||||
a = Min( one, Max( zero, a ) );
|
Vec4 const alphax_sum = MultiplyAdd( part2, onethird_onethird2, MultiplyAdd( part1, twothirds_twothirds2, part0 ) );
|
||||||
b = Min( one, Max( zero, b ) );
|
Vec4 const alpha2_sum = alphax_sum.SplatW();
|
||||||
a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp;
|
|
||||||
b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp;
|
|
||||||
|
|
||||||
// compute the error (we skip the constant xxsum)
|
|
||||||
Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
|
|
||||||
Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum );
|
|
||||||
Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 );
|
|
||||||
Vec4 e4 = MultiplyAdd( two, e3, e1 );
|
|
||||||
|
|
||||||
// apply the metric to the error term
|
Vec4 const betax_sum = MultiplyAdd( part1, onethird_onethird2, MultiplyAdd( part2, twothirds_twothirds2, part3 ) );
|
||||||
Vec4 e5 = e4*m_metric;
|
Vec4 const beta2_sum = betax_sum.SplatW();
|
||||||
Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ();
|
|
||||||
|
|
||||||
// keep the solution if it wins
|
Vec4 const alphabeta_sum = twonineths*( part1 + part2 ).SplatW();
|
||||||
if( CompareAnyLessThan( error, besterror ) )
|
|
||||||
{
|
|
||||||
beststart = a;
|
|
||||||
bestend = b;
|
|
||||||
besterror = error;
|
|
||||||
besti = i;
|
|
||||||
bestj = j;
|
|
||||||
bestk = k;
|
|
||||||
bestiteration = iterationIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// advance
|
// compute the least-squares optimal points
|
||||||
if( k == count )
|
Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) );
|
||||||
break;
|
Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor;
|
||||||
part2 += m_points_weights[k];
|
Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor;
|
||||||
++k;
|
|
||||||
}
|
|
||||||
|
|
||||||
// advance
|
// clamp to the grid
|
||||||
if( j == count )
|
a = Min( one, Max( zero, a ) );
|
||||||
break;
|
b = Min( one, Max( zero, b ) );
|
||||||
part1 += m_points_weights[j];
|
a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp;
|
||||||
++j;
|
b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp;
|
||||||
}
|
|
||||||
|
|
||||||
// advance
|
// compute the error (we skip the constant xxsum)
|
||||||
part0 += m_points_weights[i];
|
Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
|
||||||
}
|
Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum );
|
||||||
|
Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 );
|
||||||
// stop if we didn't improve in this iteration
|
Vec4 e4 = MultiplyAdd( two, e3, e1 );
|
||||||
if( bestiteration != iterationIndex )
|
|
||||||
break;
|
|
||||||
|
|
||||||
// advance if possible
|
|
||||||
++iterationIndex;
|
|
||||||
if( iterationIndex == m_iterationCount )
|
|
||||||
break;
|
|
||||||
|
|
||||||
// stop if a new iteration is an ordering that has already been tried
|
|
||||||
Vec3 axis = ( bestend - beststart ).GetVec3();
|
|
||||||
if( !ConstructOrdering( axis, iterationIndex ) )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the block if necessary
|
// apply the metric to the error term
|
||||||
if( CompareAnyLessThan( besterror, m_besterror ) )
|
Vec4 e5 = e4*m_metric;
|
||||||
{
|
Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ();
|
||||||
// remap the indices
|
|
||||||
u8 const* order = ( u8* )m_order + 16*bestiteration;
|
|
||||||
|
|
||||||
u8 unordered[16];
|
// keep the solution if it wins
|
||||||
for( int m = 0; m < besti; ++m )
|
if( CompareAnyLessThan( error, besterror ) )
|
||||||
unordered[order[m]] = 0;
|
{
|
||||||
for( int m = besti; m < bestj; ++m )
|
beststart = a;
|
||||||
unordered[order[m]] = 2;
|
bestend = b;
|
||||||
for( int m = bestj; m < bestk; ++m )
|
besterror = error;
|
||||||
unordered[order[m]] = 3;
|
besti = i;
|
||||||
for( int m = bestk; m < count; ++m )
|
bestj = j;
|
||||||
unordered[order[m]] = 1;
|
bestk = k;
|
||||||
|
bestiteration = iterationIndex;
|
||||||
|
}
|
||||||
|
|
||||||
m_colours->RemapIndices( unordered, bestindices );
|
// advance
|
||||||
|
if( k == count )
|
||||||
// save the block
|
break;
|
||||||
WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
|
part2 += m_points_weights[k];
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
|
||||||
// save the error
|
// advance
|
||||||
m_besterror = besterror;
|
if( j == count )
|
||||||
}
|
break;
|
||||||
|
part1 += m_points_weights[j];
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance
|
||||||
|
part0 += m_points_weights[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop if we didn't improve in this iteration
|
||||||
|
if( bestiteration != iterationIndex )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// advance if possible
|
||||||
|
++iterationIndex;
|
||||||
|
if( iterationIndex == m_iterationCount )
|
||||||
|
break;
|
||||||
|
|
||||||
|
// stop if a new iteration is an ordering that has already been tried
|
||||||
|
Vec3 axis = ( bestend - beststart ).GetVec3();
|
||||||
|
if( !ConstructOrdering( axis, iterationIndex ) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the block if necessary
|
||||||
|
if( CompareAnyLessThan( besterror, m_besterror ) )
|
||||||
|
{
|
||||||
|
// remap the indices
|
||||||
|
u8 const* order = ( u8* )m_order + 16*bestiteration;
|
||||||
|
|
||||||
|
u8 unordered[16];
|
||||||
|
for( int m = 0; m < besti; ++m )
|
||||||
|
unordered[order[m]] = 0;
|
||||||
|
for( int m = besti; m < bestj; ++m )
|
||||||
|
unordered[order[m]] = 2;
|
||||||
|
for( int m = bestj; m < bestk; ++m )
|
||||||
|
unordered[order[m]] = 3;
|
||||||
|
for( int m = bestk; m < count; ++m )
|
||||||
|
unordered[order[m]] = 1;
|
||||||
|
|
||||||
|
m_colours->RemapIndices( unordered, bestindices );
|
||||||
|
|
||||||
|
// save the block
|
||||||
|
WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
|
||||||
|
|
||||||
|
// save the error
|
||||||
|
m_besterror = besterror;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
68
thirdparty/squish/clusterfit.h
vendored
68
thirdparty/squish/clusterfit.h
vendored
@ -1,33 +1,33 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
Copyright (c) 2007 Ignacio Castano icastano@nvidia.com
|
Copyright (c) 2007 Ignacio Castano icastano@nvidia.com
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_CLUSTERFIT_H
|
#ifndef SQUISH_CLUSTERFIT_H
|
||||||
#define SQUISH_CLUSTERFIT_H
|
#define SQUISH_CLUSTERFIT_H
|
||||||
|
|
||||||
#include <squish.h>
|
#include "squish.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
#include "simd.h"
|
#include "simd.h"
|
||||||
#include "colourfit.h"
|
#include "colourfit.h"
|
||||||
@ -37,23 +37,23 @@ namespace squish {
|
|||||||
class ClusterFit : public ColourFit
|
class ClusterFit : public ColourFit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClusterFit( ColourSet const* colours, int flags );
|
ClusterFit( ColourSet const* colours, int flags, float* metric );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ConstructOrdering( Vec3 const& axis, int iteration );
|
bool ConstructOrdering( Vec3 const& axis, int iteration );
|
||||||
|
|
||||||
virtual void Compress3( void* block );
|
virtual void Compress3( void* block );
|
||||||
virtual void Compress4( void* block );
|
virtual void Compress4( void* block );
|
||||||
|
|
||||||
enum { kMaxIterations = 8 };
|
enum { kMaxIterations = 8 };
|
||||||
|
|
||||||
int m_iterationCount;
|
int m_iterationCount;
|
||||||
Vec3 m_principle;
|
Vec3 m_principle;
|
||||||
u8 m_order[16*kMaxIterations];
|
u8 m_order[16*kMaxIterations];
|
||||||
Vec4 m_points_weights[16];
|
Vec4 m_points_weights[16];
|
||||||
Vec4 m_xsum_wsum;
|
Vec4 m_xsum_wsum;
|
||||||
Vec4 m_metric;
|
Vec4 m_metric;
|
||||||
Vec4 m_besterror;
|
Vec4 m_besterror;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
334
thirdparty/squish/colourblock.cpp
vendored
334
thirdparty/squish/colourblock.cpp
vendored
@ -1,214 +1,214 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "colourblock.h"
|
#include "colourblock.h"
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
static int FloatToInt( float a, int limit )
|
static int FloatToInt( float a, int limit )
|
||||||
{
|
{
|
||||||
// use ANSI round-to-zero behaviour to get round-to-nearest
|
// use ANSI round-to-zero behaviour to get round-to-nearest
|
||||||
int i = ( int )( a + 0.5f );
|
int i = ( int )( a + 0.5f );
|
||||||
|
|
||||||
// clamp to the limit
|
// clamp to the limit
|
||||||
if( i < 0 )
|
if( i < 0 )
|
||||||
i = 0;
|
i = 0;
|
||||||
else if( i > limit )
|
else if( i > limit )
|
||||||
i = limit;
|
i = limit;
|
||||||
|
|
||||||
// done
|
// done
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FloatTo565( Vec3::Arg colour )
|
static int FloatTo565( Vec3::Arg colour )
|
||||||
{
|
{
|
||||||
// get the components in the correct range
|
// get the components in the correct range
|
||||||
int r = FloatToInt( 31.0f*colour.X(), 31 );
|
int r = FloatToInt( 31.0f*colour.X(), 31 );
|
||||||
int g = FloatToInt( 63.0f*colour.Y(), 63 );
|
int g = FloatToInt( 63.0f*colour.Y(), 63 );
|
||||||
int b = FloatToInt( 31.0f*colour.Z(), 31 );
|
int b = FloatToInt( 31.0f*colour.Z(), 31 );
|
||||||
|
|
||||||
// pack into a single value
|
// pack into a single value
|
||||||
return ( r << 11 ) | ( g << 5 ) | b;
|
return ( r << 11 ) | ( g << 5 ) | b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WriteColourBlock( int a, int b, u8* indices, void* block )
|
static void WriteColourBlock( int a, int b, u8* indices, void* block )
|
||||||
{
|
{
|
||||||
// get the block as bytes
|
// get the block as bytes
|
||||||
u8* bytes = ( u8* )block;
|
u8* bytes = ( u8* )block;
|
||||||
|
|
||||||
// write the endpoints
|
// write the endpoints
|
||||||
bytes[0] = ( u8 )( a & 0xff );
|
bytes[0] = ( u8 )( a & 0xff );
|
||||||
bytes[1] = ( u8 )( a >> 8 );
|
bytes[1] = ( u8 )( a >> 8 );
|
||||||
bytes[2] = ( u8 )( b & 0xff );
|
bytes[2] = ( u8 )( b & 0xff );
|
||||||
bytes[3] = ( u8 )( b >> 8 );
|
bytes[3] = ( u8 )( b >> 8 );
|
||||||
|
|
||||||
// write the indices
|
// write the indices
|
||||||
for( int i = 0; i < 4; ++i )
|
for( int i = 0; i < 4; ++i )
|
||||||
{
|
{
|
||||||
u8 const* ind = indices + 4*i;
|
u8 const* ind = indices + 4*i;
|
||||||
bytes[4 + i] = ind[0] | ( ind[1] << 2 ) | ( ind[2] << 4 ) | ( ind[3] << 6 );
|
bytes[4 + i] = ind[0] | ( ind[1] << 2 ) | ( ind[2] << 4 ) | ( ind[3] << 6 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block )
|
void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block )
|
||||||
{
|
{
|
||||||
// get the packed values
|
// get the packed values
|
||||||
int a = FloatTo565( start );
|
int a = FloatTo565( start );
|
||||||
int b = FloatTo565( end );
|
int b = FloatTo565( end );
|
||||||
|
|
||||||
// remap the indices
|
// remap the indices
|
||||||
u8 remapped[16];
|
u8 remapped[16];
|
||||||
if( a <= b )
|
if( a <= b )
|
||||||
{
|
{
|
||||||
// use the indices directly
|
// use the indices directly
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
remapped[i] = indices[i];
|
remapped[i] = indices[i];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// swap a and b
|
// swap a and b
|
||||||
std::swap( a, b );
|
std::swap( a, b );
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
if( indices[i] == 0 )
|
if( indices[i] == 0 )
|
||||||
remapped[i] = 1;
|
remapped[i] = 1;
|
||||||
else if( indices[i] == 1 )
|
else if( indices[i] == 1 )
|
||||||
remapped[i] = 0;
|
remapped[i] = 0;
|
||||||
else
|
else
|
||||||
remapped[i] = indices[i];
|
remapped[i] = indices[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the block
|
// write the block
|
||||||
WriteColourBlock( a, b, remapped, block );
|
WriteColourBlock( a, b, remapped, block );
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block )
|
void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block )
|
||||||
{
|
{
|
||||||
// get the packed values
|
// get the packed values
|
||||||
int a = FloatTo565( start );
|
int a = FloatTo565( start );
|
||||||
int b = FloatTo565( end );
|
int b = FloatTo565( end );
|
||||||
|
|
||||||
// remap the indices
|
// remap the indices
|
||||||
u8 remapped[16];
|
u8 remapped[16];
|
||||||
if( a < b )
|
if( a < b )
|
||||||
{
|
{
|
||||||
// swap a and b
|
// swap a and b
|
||||||
std::swap( a, b );
|
std::swap( a, b );
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
remapped[i] = ( indices[i] ^ 0x1 ) & 0x3;
|
remapped[i] = ( indices[i] ^ 0x1 ) & 0x3;
|
||||||
}
|
}
|
||||||
else if( a == b )
|
else if( a == b )
|
||||||
{
|
{
|
||||||
// use index 0
|
// use index 0
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
remapped[i] = 0;
|
remapped[i] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// use the indices directly
|
// use the indices directly
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
remapped[i] = indices[i];
|
remapped[i] = indices[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// write the block
|
// write the block
|
||||||
WriteColourBlock( a, b, remapped, block );
|
WriteColourBlock( a, b, remapped, block );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Unpack565( u8 const* packed, u8* colour )
|
static int Unpack565( u8 const* packed, u8* colour )
|
||||||
{
|
{
|
||||||
// build the packed value
|
// build the packed value
|
||||||
int value = ( int )packed[0] | ( ( int )packed[1] << 8 );
|
int value = ( int )packed[0] | ( ( int )packed[1] << 8 );
|
||||||
|
|
||||||
// get the components in the stored range
|
|
||||||
u8 red = ( u8 )( ( value >> 11 ) & 0x1f );
|
|
||||||
u8 green = ( u8 )( ( value >> 5 ) & 0x3f );
|
|
||||||
u8 blue = ( u8 )( value & 0x1f );
|
|
||||||
|
|
||||||
// scale up to 8 bits
|
// get the components in the stored range
|
||||||
colour[0] = ( red << 3 ) | ( red >> 2 );
|
u8 red = ( u8 )( ( value >> 11 ) & 0x1f );
|
||||||
colour[1] = ( green << 2 ) | ( green >> 4 );
|
u8 green = ( u8 )( ( value >> 5 ) & 0x3f );
|
||||||
colour[2] = ( blue << 3 ) | ( blue >> 2 );
|
u8 blue = ( u8 )( value & 0x1f );
|
||||||
colour[3] = 255;
|
|
||||||
|
// scale up to 8 bits
|
||||||
// return the value
|
colour[0] = ( red << 3 ) | ( red >> 2 );
|
||||||
return value;
|
colour[1] = ( green << 2 ) | ( green >> 4 );
|
||||||
|
colour[2] = ( blue << 3 ) | ( blue >> 2 );
|
||||||
|
colour[3] = 255;
|
||||||
|
|
||||||
|
// return the value
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompressColour( u8* rgba, void const* block, bool isDxt1 )
|
void DecompressColour( u8* rgba, void const* block, bool isDxt1 )
|
||||||
{
|
{
|
||||||
// get the block bytes
|
// get the block bytes
|
||||||
u8 const* bytes = reinterpret_cast< u8 const* >( block );
|
u8 const* bytes = reinterpret_cast< u8 const* >( block );
|
||||||
|
|
||||||
// unpack the endpoints
|
|
||||||
u8 codes[16];
|
|
||||||
int a = Unpack565( bytes, codes );
|
|
||||||
int b = Unpack565( bytes + 2, codes + 4 );
|
|
||||||
|
|
||||||
// generate the midpoints
|
|
||||||
for( int i = 0; i < 3; ++i )
|
|
||||||
{
|
|
||||||
int c = codes[i];
|
|
||||||
int d = codes[4 + i];
|
|
||||||
|
|
||||||
if( isDxt1 && a <= b )
|
// unpack the endpoints
|
||||||
{
|
u8 codes[16];
|
||||||
codes[8 + i] = ( u8 )( ( c + d )/2 );
|
int a = Unpack565( bytes, codes );
|
||||||
codes[12 + i] = 0;
|
int b = Unpack565( bytes + 2, codes + 4 );
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
codes[8 + i] = ( u8 )( ( 2*c + d )/3 );
|
|
||||||
codes[12 + i] = ( u8 )( ( c + 2*d )/3 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill in alpha for the intermediate values
|
|
||||||
codes[8 + 3] = 255;
|
|
||||||
codes[12 + 3] = ( isDxt1 && a <= b ) ? 0 : 255;
|
|
||||||
|
|
||||||
// unpack the indices
|
|
||||||
u8 indices[16];
|
|
||||||
for( int i = 0; i < 4; ++i )
|
|
||||||
{
|
|
||||||
u8* ind = indices + 4*i;
|
|
||||||
u8 packed = bytes[4 + i];
|
|
||||||
|
|
||||||
ind[0] = packed & 0x3;
|
|
||||||
ind[1] = ( packed >> 2 ) & 0x3;
|
|
||||||
ind[2] = ( packed >> 4 ) & 0x3;
|
|
||||||
ind[3] = ( packed >> 6 ) & 0x3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// store out the colours
|
// generate the midpoints
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 3; ++i )
|
||||||
{
|
{
|
||||||
u8 offset = 4*indices[i];
|
int c = codes[i];
|
||||||
for( int j = 0; j < 4; ++j )
|
int d = codes[4 + i];
|
||||||
rgba[4*i + j] = codes[offset + j];
|
|
||||||
}
|
if( isDxt1 && a <= b )
|
||||||
|
{
|
||||||
|
codes[8 + i] = ( u8 )( ( c + d )/2 );
|
||||||
|
codes[12 + i] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codes[8 + i] = ( u8 )( ( 2*c + d )/3 );
|
||||||
|
codes[12 + i] = ( u8 )( ( c + 2*d )/3 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill in alpha for the intermediate values
|
||||||
|
codes[8 + 3] = 255;
|
||||||
|
codes[12 + 3] = ( isDxt1 && a <= b ) ? 0 : 255;
|
||||||
|
|
||||||
|
// unpack the indices
|
||||||
|
u8 indices[16];
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
{
|
||||||
|
u8* ind = indices + 4*i;
|
||||||
|
u8 packed = bytes[4 + i];
|
||||||
|
|
||||||
|
ind[0] = packed & 0x3;
|
||||||
|
ind[1] = ( packed >> 2 ) & 0x3;
|
||||||
|
ind[2] = ( packed >> 4 ) & 0x3;
|
||||||
|
ind[3] = ( packed >> 6 ) & 0x3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store out the colours
|
||||||
|
for( int i = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
u8 offset = 4*indices[i];
|
||||||
|
for( int j = 0; j < 4; ++j )
|
||||||
|
rgba[4*i + j] = codes[offset + j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
40
thirdparty/squish/colourblock.h
vendored
40
thirdparty/squish/colourblock.h
vendored
@ -1,32 +1,32 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_COLOURBLOCK_H
|
#ifndef SQUISH_COLOURBLOCK_H
|
||||||
#define SQUISH_COLOURBLOCK_H
|
#define SQUISH_COLOURBLOCK_H
|
||||||
|
|
||||||
#include <squish.h>
|
#include "squish.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
66
thirdparty/squish/colourfit.cpp
vendored
66
thirdparty/squish/colourfit.cpp
vendored
@ -1,50 +1,54 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "colourfit.h"
|
#include "colourfit.h"
|
||||||
#include "colourset.h"
|
#include "colourset.h"
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
ColourFit::ColourFit( ColourSet const* colours, int flags )
|
ColourFit::ColourFit( ColourSet const* colours, int flags )
|
||||||
: m_colours( colours ),
|
: m_colours( colours ),
|
||||||
m_flags( flags )
|
m_flags( flags )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ColourFit::~ColourFit()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColourFit::Compress( void* block )
|
void ColourFit::Compress( void* block )
|
||||||
{
|
{
|
||||||
bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 );
|
bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 );
|
||||||
if( isDxt1 )
|
if( isDxt1 )
|
||||||
{
|
{
|
||||||
Compress3( block );
|
Compress3( block );
|
||||||
if( !m_colours->IsTransparent() )
|
if( !m_colours->IsTransparent() )
|
||||||
Compress4( block );
|
Compress4( block );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Compress4( block );
|
Compress4( block );
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
55
thirdparty/squish/colourfit.h
vendored
55
thirdparty/squish/colourfit.h
vendored
@ -1,34 +1,36 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_COLOURFIT_H
|
#ifndef SQUISH_COLOURFIT_H
|
||||||
#define SQUISH_COLOURFIT_H
|
#define SQUISH_COLOURFIT_H
|
||||||
|
|
||||||
#include <squish.h>
|
#include "squish.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
|
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
class ColourSet;
|
class ColourSet;
|
||||||
@ -36,16 +38,17 @@ class ColourSet;
|
|||||||
class ColourFit
|
class ColourFit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ColourFit( ColourSet const* colours, int flags );
|
ColourFit( ColourSet const* colours, int flags );
|
||||||
|
virtual ~ColourFit();
|
||||||
|
|
||||||
void Compress( void* block );
|
void Compress( void* block );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Compress3( void* block ) = 0;
|
virtual void Compress3( void* block ) = 0;
|
||||||
virtual void Compress4( void* block ) = 0;
|
virtual void Compress4( void* block ) = 0;
|
||||||
|
|
||||||
ColourSet const* m_colours;
|
ColourSet const* m_colours;
|
||||||
int m_flags;
|
int m_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
194
thirdparty/squish/colourset.cpp
vendored
194
thirdparty/squish/colourset.cpp
vendored
@ -1,121 +1,121 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "colourset.h"
|
#include "colourset.h"
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
ColourSet::ColourSet( u8 const* rgba, int mask, int flags )
|
ColourSet::ColourSet( u8 const* rgba, int mask, int flags )
|
||||||
: m_count( 0 ),
|
: m_count( 0 ),
|
||||||
m_transparent( false )
|
m_transparent( false )
|
||||||
{
|
{
|
||||||
// check the compression mode for dxt1
|
// check the compression mode for dxt1
|
||||||
bool isDxt1 = ( ( flags & kDxt1 ) != 0 );
|
bool isDxt1 = ( ( flags & kDxt1 ) != 0 );
|
||||||
bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 );
|
bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 );
|
||||||
|
|
||||||
// create the minimal set
|
// create the minimal set
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
// check this pixel is enabled
|
// check this pixel is enabled
|
||||||
int bit = 1 << i;
|
int bit = 1 << i;
|
||||||
if( ( mask & bit ) == 0 )
|
if( ( mask & bit ) == 0 )
|
||||||
{
|
{
|
||||||
m_remap[i] = -1;
|
m_remap[i] = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for transparent pixels when using dxt1
|
|
||||||
if( isDxt1 && rgba[4*i + 3] < 128 )
|
|
||||||
{
|
|
||||||
m_remap[i] = -1;
|
|
||||||
m_transparent = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop over previous points for a match
|
// check for transparent pixels when using dxt1
|
||||||
for( int j = 0;; ++j )
|
if( isDxt1 && rgba[4*i + 3] < 128 )
|
||||||
{
|
{
|
||||||
// allocate a new point
|
m_remap[i] = -1;
|
||||||
if( j == i )
|
m_transparent = true;
|
||||||
{
|
continue;
|
||||||
// normalise coordinates to [0,1]
|
}
|
||||||
float x = ( float )rgba[4*i] / 255.0f;
|
|
||||||
float y = ( float )rgba[4*i + 1] / 255.0f;
|
|
||||||
float z = ( float )rgba[4*i + 2] / 255.0f;
|
|
||||||
|
|
||||||
// ensure there is always non-zero weight even for zero alpha
|
|
||||||
float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f;
|
|
||||||
|
|
||||||
// add the point
|
// loop over previous points for a match
|
||||||
m_points[m_count] = Vec3( x, y, z );
|
for( int j = 0;; ++j )
|
||||||
m_weights[m_count] = ( weightByAlpha ? w : 1.0f );
|
{
|
||||||
m_remap[i] = m_count;
|
// allocate a new point
|
||||||
|
if( j == i )
|
||||||
// advance
|
{
|
||||||
++m_count;
|
// normalise coordinates to [0,1]
|
||||||
break;
|
float x = ( float )rgba[4*i] / 255.0f;
|
||||||
}
|
float y = ( float )rgba[4*i + 1] / 255.0f;
|
||||||
|
float z = ( float )rgba[4*i + 2] / 255.0f;
|
||||||
// check for a match
|
|
||||||
int oldbit = 1 << j;
|
|
||||||
bool match = ( ( mask & oldbit ) != 0 )
|
|
||||||
&& ( rgba[4*i] == 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 = m_remap[j];
|
|
||||||
|
|
||||||
// ensure there is always non-zero weight even for zero alpha
|
|
||||||
float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f;
|
|
||||||
|
|
||||||
// map to this point and increase the weight
|
// ensure there is always non-zero weight even for zero alpha
|
||||||
m_weights[index] += ( weightByAlpha ? w : 1.0f );
|
float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f;
|
||||||
m_remap[i] = index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// square root the weights
|
// add the point
|
||||||
for( int i = 0; i < m_count; ++i )
|
m_points[m_count] = Vec3( x, y, z );
|
||||||
m_weights[i] = std::sqrt( m_weights[i] );
|
m_weights[m_count] = ( weightByAlpha ? w : 1.0f );
|
||||||
|
m_remap[i] = m_count;
|
||||||
|
|
||||||
|
// advance
|
||||||
|
++m_count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for a match
|
||||||
|
int oldbit = 1 << j;
|
||||||
|
bool match = ( ( mask & oldbit ) != 0 )
|
||||||
|
&& ( rgba[4*i] == 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 = m_remap[j];
|
||||||
|
|
||||||
|
// ensure there is always non-zero weight even for zero alpha
|
||||||
|
float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f;
|
||||||
|
|
||||||
|
// map to this point and increase the weight
|
||||||
|
m_weights[index] += ( weightByAlpha ? w : 1.0f );
|
||||||
|
m_remap[i] = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// square root the weights
|
||||||
|
for( int i = 0; i < m_count; ++i )
|
||||||
|
m_weights[i] = std::sqrt( m_weights[i] );
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColourSet::RemapIndices( u8 const* source, u8* target ) const
|
void ColourSet::RemapIndices( u8 const* source, u8* target ) const
|
||||||
{
|
{
|
||||||
for( int i = 0; i < 16; ++i )
|
for( int i = 0; i < 16; ++i )
|
||||||
{
|
{
|
||||||
int j = m_remap[i];
|
int j = m_remap[i];
|
||||||
if( j == -1 )
|
if( j == -1 )
|
||||||
target[i] = 3;
|
target[i] = 3;
|
||||||
else
|
else
|
||||||
target[i] = source[j];
|
target[i] = source[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
62
thirdparty/squish/colourset.h
vendored
62
thirdparty/squish/colourset.h
vendored
@ -1,32 +1,32 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_COLOURSET_H
|
#ifndef SQUISH_COLOURSET_H
|
||||||
#define SQUISH_COLOURSET_H
|
#define SQUISH_COLOURSET_H
|
||||||
|
|
||||||
#include <squish.h>
|
#include "squish.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
@ -36,21 +36,21 @@ namespace squish {
|
|||||||
class ColourSet
|
class ColourSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ColourSet( u8 const* rgba, int mask, int flags );
|
ColourSet( u8 const* rgba, int mask, int flags );
|
||||||
|
|
||||||
int GetCount() const { return m_count; }
|
int GetCount() const { return m_count; }
|
||||||
Vec3 const* GetPoints() const { return m_points; }
|
Vec3 const* GetPoints() const { return m_points; }
|
||||||
float const* GetWeights() const { return m_weights; }
|
float const* GetWeights() const { return m_weights; }
|
||||||
bool IsTransparent() const { return m_transparent; }
|
bool IsTransparent() const { return m_transparent; }
|
||||||
|
|
||||||
void RemapIndices( u8 const* source, u8* target ) const;
|
void RemapIndices( u8 const* source, u8* target ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_count;
|
int m_count;
|
||||||
Vec3 m_points[16];
|
Vec3 m_points[16];
|
||||||
float m_weights[16];
|
float m_weights[16];
|
||||||
int m_remap[16];
|
int m_remap[16];
|
||||||
bool m_transparent;
|
bool m_transparent;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sqish
|
} // namespace sqish
|
||||||
|
40
thirdparty/squish/config.h
vendored
40
thirdparty/squish/config.h
vendored
@ -1,28 +1,28 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_CONFIG_H
|
#ifndef SQUISH_CONFIG_H
|
||||||
#define SQUISH_CONFIG_H
|
#define SQUISH_CONFIG_H
|
||||||
|
|
||||||
@ -36,7 +36,7 @@
|
|||||||
#define SQUISH_USE_SSE 0
|
#define SQUISH_USE_SSE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Internally et SQUISH_USE_SIMD when either Altivec or SSE is available.
|
// Internally set SQUISH_USE_SIMD when either Altivec or SSE is available.
|
||||||
#if SQUISH_USE_ALTIVEC && SQUISH_USE_SSE
|
#if SQUISH_USE_ALTIVEC && SQUISH_USE_SSE
|
||||||
#error "Cannot enable both Altivec and SSE!"
|
#error "Cannot enable both Altivec and SSE!"
|
||||||
#endif
|
#endif
|
||||||
|
384
thirdparty/squish/maths.cpp
vendored
384
thirdparty/squish/maths.cpp
vendored
@ -1,227 +1,259 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/*! @file
|
/*! @file
|
||||||
|
|
||||||
The symmetric eigensystem solver algorithm is from
|
The symmetric eigensystem solver algorithm is from
|
||||||
http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf
|
http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
|
#include "simd.h"
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights )
|
Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights )
|
||||||
{
|
{
|
||||||
// compute the centroid
|
// compute the centroid
|
||||||
float total = 0.0f;
|
float total = 0.0f;
|
||||||
Vec3 centroid( 0.0f );
|
Vec3 centroid( 0.0f );
|
||||||
for( int i = 0; i < n; ++i )
|
for( int i = 0; i < n; ++i )
|
||||||
{
|
{
|
||||||
total += weights[i];
|
total += weights[i];
|
||||||
centroid += weights[i]*points[i];
|
centroid += weights[i]*points[i];
|
||||||
}
|
}
|
||||||
centroid /= total;
|
if( total > FLT_EPSILON )
|
||||||
|
centroid /= total;
|
||||||
|
|
||||||
// accumulate the covariance matrix
|
// accumulate the covariance matrix
|
||||||
Sym3x3 covariance( 0.0f );
|
Sym3x3 covariance( 0.0f );
|
||||||
for( int i = 0; i < n; ++i )
|
for( int i = 0; i < n; ++i )
|
||||||
{
|
{
|
||||||
Vec3 a = points[i] - centroid;
|
Vec3 a = points[i] - centroid;
|
||||||
Vec3 b = weights[i]*a;
|
Vec3 b = weights[i]*a;
|
||||||
|
|
||||||
covariance[0] += a.X()*b.X();
|
covariance[0] += a.X()*b.X();
|
||||||
covariance[1] += a.X()*b.Y();
|
covariance[1] += a.X()*b.Y();
|
||||||
covariance[2] += a.X()*b.Z();
|
covariance[2] += a.X()*b.Z();
|
||||||
covariance[3] += a.Y()*b.Y();
|
covariance[3] += a.Y()*b.Y();
|
||||||
covariance[4] += a.Y()*b.Z();
|
covariance[4] += a.Y()*b.Z();
|
||||||
covariance[5] += a.Z()*b.Z();
|
covariance[5] += a.Z()*b.Z();
|
||||||
}
|
}
|
||||||
|
|
||||||
// return it
|
// return it
|
||||||
return covariance;
|
return covariance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
static Vec3 GetMultiplicity1Evector( Sym3x3 const& matrix, float evalue )
|
static Vec3 GetMultiplicity1Evector( Sym3x3 const& matrix, float evalue )
|
||||||
{
|
{
|
||||||
// compute M
|
// compute M
|
||||||
Sym3x3 m;
|
Sym3x3 m;
|
||||||
m[0] = matrix[0] - evalue;
|
m[0] = matrix[0] - evalue;
|
||||||
m[1] = matrix[1];
|
m[1] = matrix[1];
|
||||||
m[2] = matrix[2];
|
m[2] = matrix[2];
|
||||||
m[3] = matrix[3] - evalue;
|
m[3] = matrix[3] - evalue;
|
||||||
m[4] = matrix[4];
|
m[4] = matrix[4];
|
||||||
m[5] = matrix[5] - evalue;
|
m[5] = matrix[5] - evalue;
|
||||||
|
|
||||||
// compute U
|
// compute U
|
||||||
Sym3x3 u;
|
Sym3x3 u;
|
||||||
u[0] = m[3]*m[5] - m[4]*m[4];
|
u[0] = m[3]*m[5] - m[4]*m[4];
|
||||||
u[1] = m[2]*m[4] - m[1]*m[5];
|
u[1] = m[2]*m[4] - m[1]*m[5];
|
||||||
u[2] = m[1]*m[4] - m[2]*m[3];
|
u[2] = m[1]*m[4] - m[2]*m[3];
|
||||||
u[3] = m[0]*m[5] - m[2]*m[2];
|
u[3] = m[0]*m[5] - m[2]*m[2];
|
||||||
u[4] = m[1]*m[2] - m[4]*m[0];
|
u[4] = m[1]*m[2] - m[4]*m[0];
|
||||||
u[5] = m[0]*m[3] - m[1]*m[1];
|
u[5] = m[0]*m[3] - m[1]*m[1];
|
||||||
|
|
||||||
// find the largest component
|
// find the largest component
|
||||||
float mc = std::fabs( u[0] );
|
float mc = std::fabs( u[0] );
|
||||||
int mi = 0;
|
int mi = 0;
|
||||||
for( int i = 1; i < 6; ++i )
|
for( int i = 1; i < 6; ++i )
|
||||||
{
|
{
|
||||||
float c = std::fabs( u[i] );
|
float c = std::fabs( u[i] );
|
||||||
if( c > mc )
|
if( c > mc )
|
||||||
{
|
{
|
||||||
mc = c;
|
mc = c;
|
||||||
mi = i;
|
mi = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pick the column with this component
|
// pick the column with this component
|
||||||
switch( mi )
|
switch( mi )
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
return Vec3( u[0], u[1], u[2] );
|
return Vec3( u[0], u[1], u[2] );
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
case 3:
|
case 3:
|
||||||
return Vec3( u[1], u[3], u[4] );
|
return Vec3( u[1], u[3], u[4] );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Vec3( u[2], u[4], u[5] );
|
return Vec3( u[2], u[4], u[5] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vec3 GetMultiplicity2Evector( Sym3x3 const& matrix, float evalue )
|
static Vec3 GetMultiplicity2Evector( Sym3x3 const& matrix, float evalue )
|
||||||
{
|
{
|
||||||
// compute M
|
// compute M
|
||||||
Sym3x3 m;
|
Sym3x3 m;
|
||||||
m[0] = matrix[0] - evalue;
|
m[0] = matrix[0] - evalue;
|
||||||
m[1] = matrix[1];
|
m[1] = matrix[1];
|
||||||
m[2] = matrix[2];
|
m[2] = matrix[2];
|
||||||
m[3] = matrix[3] - evalue;
|
m[3] = matrix[3] - evalue;
|
||||||
m[4] = matrix[4];
|
m[4] = matrix[4];
|
||||||
m[5] = matrix[5] - evalue;
|
m[5] = matrix[5] - evalue;
|
||||||
|
|
||||||
// find the largest component
|
// find the largest component
|
||||||
float mc = std::fabs( m[0] );
|
float mc = std::fabs( m[0] );
|
||||||
int mi = 0;
|
int mi = 0;
|
||||||
for( int i = 1; i < 6; ++i )
|
for( int i = 1; i < 6; ++i )
|
||||||
{
|
{
|
||||||
float c = std::fabs( m[i] );
|
float c = std::fabs( m[i] );
|
||||||
if( c > mc )
|
if( c > mc )
|
||||||
{
|
{
|
||||||
mc = c;
|
mc = c;
|
||||||
mi = i;
|
mi = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pick the first eigenvector based on this index
|
// pick the first eigenvector based on this index
|
||||||
switch( mi )
|
switch( mi )
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
return Vec3( -m[1], m[0], 0.0f );
|
return Vec3( -m[1], m[0], 0.0f );
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
return Vec3( m[2], 0.0f, -m[0] );
|
return Vec3( m[2], 0.0f, -m[0] );
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
return Vec3( 0.0f, -m[4], m[3] );
|
return Vec3( 0.0f, -m[4], m[3] );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Vec3( 0.0f, -m[5], m[4] );
|
return Vec3( 0.0f, -m[5], m[4] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 ComputePrincipleComponent( Sym3x3 const& matrix )
|
Vec3 ComputePrincipleComponent( Sym3x3 const& matrix )
|
||||||
{
|
{
|
||||||
// compute the cubic coefficients
|
// compute the cubic coefficients
|
||||||
float c0 = matrix[0]*matrix[3]*matrix[5]
|
float c0 = matrix[0]*matrix[3]*matrix[5]
|
||||||
+ 2.0f*matrix[1]*matrix[2]*matrix[4]
|
+ 2.0f*matrix[1]*matrix[2]*matrix[4]
|
||||||
- matrix[0]*matrix[4]*matrix[4]
|
- matrix[0]*matrix[4]*matrix[4]
|
||||||
- matrix[3]*matrix[2]*matrix[2]
|
- matrix[3]*matrix[2]*matrix[2]
|
||||||
- matrix[5]*matrix[1]*matrix[1];
|
- matrix[5]*matrix[1]*matrix[1];
|
||||||
float c1 = matrix[0]*matrix[3] + matrix[0]*matrix[5] + matrix[3]*matrix[5]
|
float c1 = matrix[0]*matrix[3] + matrix[0]*matrix[5] + matrix[3]*matrix[5]
|
||||||
- matrix[1]*matrix[1] - matrix[2]*matrix[2] - matrix[4]*matrix[4];
|
- matrix[1]*matrix[1] - matrix[2]*matrix[2] - matrix[4]*matrix[4];
|
||||||
float c2 = matrix[0] + matrix[3] + matrix[5];
|
float c2 = matrix[0] + matrix[3] + matrix[5];
|
||||||
|
|
||||||
// compute the quadratic coefficients
|
// compute the quadratic coefficients
|
||||||
float a = c1 - ( 1.0f/3.0f )*c2*c2;
|
float a = c1 - ( 1.0f/3.0f )*c2*c2;
|
||||||
float b = ( -2.0f/27.0f )*c2*c2*c2 + ( 1.0f/3.0f )*c1*c2 - c0;
|
float b = ( -2.0f/27.0f )*c2*c2*c2 + ( 1.0f/3.0f )*c1*c2 - c0;
|
||||||
|
|
||||||
// compute the root count check
|
// compute the root count check
|
||||||
float Q = 0.25f*b*b + ( 1.0f/27.0f )*a*a*a;
|
float Q = 0.25f*b*b + ( 1.0f/27.0f )*a*a*a;
|
||||||
|
|
||||||
// test the multiplicity
|
// test the multiplicity
|
||||||
if( FLT_EPSILON < Q )
|
if( FLT_EPSILON < Q )
|
||||||
{
|
{
|
||||||
// only one root, which implies we have a multiple of the identity
|
// only one root, which implies we have a multiple of the identity
|
||||||
return Vec3( 1.0f );
|
return Vec3( 1.0f );
|
||||||
}
|
}
|
||||||
else if( Q < -FLT_EPSILON )
|
else if( Q < -FLT_EPSILON )
|
||||||
{
|
{
|
||||||
// three distinct roots
|
// three distinct roots
|
||||||
float theta = std::atan2( std::sqrt( -Q ), -0.5f*b );
|
float theta = std::atan2( std::sqrt( -Q ), -0.5f*b );
|
||||||
float rho = std::sqrt( 0.25f*b*b - Q );
|
float rho = std::sqrt( 0.25f*b*b - Q );
|
||||||
|
|
||||||
float rt = std::pow( rho, 1.0f/3.0f );
|
float rt = std::pow( rho, 1.0f/3.0f );
|
||||||
float ct = std::cos( theta/3.0f );
|
float ct = std::cos( theta/3.0f );
|
||||||
float st = std::sin( theta/3.0f );
|
float st = std::sin( theta/3.0f );
|
||||||
|
|
||||||
float l1 = ( 1.0f/3.0f )*c2 + 2.0f*rt*ct;
|
float l1 = ( 1.0f/3.0f )*c2 + 2.0f*rt*ct;
|
||||||
float l2 = ( 1.0f/3.0f )*c2 - rt*( ct + ( float )sqrt( 3.0f )*st );
|
float l2 = ( 1.0f/3.0f )*c2 - rt*( ct + ( float )sqrt( 3.0f )*st );
|
||||||
float l3 = ( 1.0f/3.0f )*c2 - rt*( ct - ( float )sqrt( 3.0f )*st );
|
float l3 = ( 1.0f/3.0f )*c2 - rt*( ct - ( float )sqrt( 3.0f )*st );
|
||||||
|
|
||||||
// pick the larger
|
// pick the larger
|
||||||
if( std::fabs( l2 ) > std::fabs( l1 ) )
|
if( std::fabs( l2 ) > std::fabs( l1 ) )
|
||||||
l1 = l2;
|
l1 = l2;
|
||||||
if( std::fabs( l3 ) > std::fabs( l1 ) )
|
if( std::fabs( l3 ) > std::fabs( l1 ) )
|
||||||
l1 = l3;
|
l1 = l3;
|
||||||
|
|
||||||
// get the eigenvector
|
// get the eigenvector
|
||||||
return GetMultiplicity1Evector( matrix, l1 );
|
return GetMultiplicity1Evector( matrix, l1 );
|
||||||
}
|
}
|
||||||
else // if( -FLT_EPSILON <= Q && Q <= FLT_EPSILON )
|
else // if( -FLT_EPSILON <= Q && Q <= FLT_EPSILON )
|
||||||
{
|
{
|
||||||
// two roots
|
// two roots
|
||||||
float rt;
|
float rt;
|
||||||
if( b < 0.0f )
|
if( b < 0.0f )
|
||||||
rt = -std::pow( -0.5f*b, 1.0f/3.0f );
|
rt = -std::pow( -0.5f*b, 1.0f/3.0f );
|
||||||
else
|
else
|
||||||
rt = std::pow( 0.5f*b, 1.0f/3.0f );
|
rt = std::pow( 0.5f*b, 1.0f/3.0f );
|
||||||
|
|
||||||
float l1 = ( 1.0f/3.0f )*c2 + rt; // repeated
|
float l1 = ( 1.0f/3.0f )*c2 + rt; // repeated
|
||||||
float l2 = ( 1.0f/3.0f )*c2 - 2.0f*rt;
|
float l2 = ( 1.0f/3.0f )*c2 - 2.0f*rt;
|
||||||
|
|
||||||
// get the eigenvector
|
// get the eigenvector
|
||||||
if( std::fabs( l1 ) > std::fabs( l2 ) )
|
if( std::fabs( l1 ) > std::fabs( l2 ) )
|
||||||
return GetMultiplicity2Evector( matrix, l1 );
|
return GetMultiplicity2Evector( matrix, l1 );
|
||||||
else
|
else
|
||||||
return GetMultiplicity1Evector( matrix, l2 );
|
return GetMultiplicity1Evector( matrix, l2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define POWER_ITERATION_COUNT 8
|
||||||
|
|
||||||
|
Vec3 ComputePrincipleComponent( Sym3x3 const& matrix )
|
||||||
|
{
|
||||||
|
Vec4 const row0( matrix[0], matrix[1], matrix[2], 0.0f );
|
||||||
|
Vec4 const row1( matrix[1], matrix[3], matrix[4], 0.0f );
|
||||||
|
Vec4 const row2( matrix[2], matrix[4], matrix[5], 0.0f );
|
||||||
|
Vec4 v = VEC4_CONST( 1.0f );
|
||||||
|
for( int i = 0; i < POWER_ITERATION_COUNT; ++i )
|
||||||
|
{
|
||||||
|
// matrix multiply
|
||||||
|
Vec4 w = row0*v.SplatX();
|
||||||
|
w = MultiplyAdd(row1, v.SplatY(), w);
|
||||||
|
w = MultiplyAdd(row2, v.SplatZ(), w);
|
||||||
|
|
||||||
|
// get max component from xyz in all channels
|
||||||
|
Vec4 a = Max(w.SplatX(), Max(w.SplatY(), w.SplatZ()));
|
||||||
|
|
||||||
|
// divide through and advance
|
||||||
|
v = w*Reciprocal(a);
|
||||||
|
}
|
||||||
|
return v.GetVec3();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
372
thirdparty/squish/maths.h
vendored
372
thirdparty/squish/maths.h
vendored
@ -1,28 +1,28 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_MATHS_H
|
#ifndef SQUISH_MATHS_H
|
||||||
#define SQUISH_MATHS_H
|
#define SQUISH_MATHS_H
|
||||||
|
|
||||||
@ -35,194 +35,194 @@ namespace squish {
|
|||||||
class Vec3
|
class Vec3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Vec3 const& Arg;
|
typedef Vec3 const& Arg;
|
||||||
|
|
||||||
Vec3()
|
Vec3()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Vec3( float s )
|
explicit Vec3( float s )
|
||||||
{
|
{
|
||||||
m_x = s;
|
m_x = s;
|
||||||
m_y = s;
|
m_y = s;
|
||||||
m_z = s;
|
m_z = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3( float x, float y, float z )
|
Vec3( float x, float y, float z )
|
||||||
{
|
{
|
||||||
m_x = x;
|
m_x = x;
|
||||||
m_y = y;
|
m_y = y;
|
||||||
m_z = z;
|
m_z = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
float X() const { return m_x; }
|
|
||||||
float Y() const { return m_y; }
|
|
||||||
float Z() const { return m_z; }
|
|
||||||
|
|
||||||
Vec3 operator-() const
|
|
||||||
{
|
|
||||||
return Vec3( -m_x, -m_y, -m_z );
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3& operator+=( Arg v )
|
|
||||||
{
|
|
||||||
m_x += v.m_x;
|
|
||||||
m_y += v.m_y;
|
|
||||||
m_z += v.m_z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3& operator-=( Arg v )
|
|
||||||
{
|
|
||||||
m_x -= v.m_x;
|
|
||||||
m_y -= v.m_y;
|
|
||||||
m_z -= v.m_z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3& operator*=( Arg v )
|
|
||||||
{
|
|
||||||
m_x *= v.m_x;
|
|
||||||
m_y *= v.m_y;
|
|
||||||
m_z *= v.m_z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3& operator*=( float s )
|
|
||||||
{
|
|
||||||
m_x *= s;
|
|
||||||
m_y *= s;
|
|
||||||
m_z *= s;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3& operator/=( Arg v )
|
|
||||||
{
|
|
||||||
m_x /= v.m_x;
|
|
||||||
m_y /= v.m_y;
|
|
||||||
m_z /= v.m_z;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3& operator/=( float s )
|
|
||||||
{
|
|
||||||
float t = 1.0f/s;
|
|
||||||
m_x *= t;
|
|
||||||
m_y *= t;
|
|
||||||
m_z *= t;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 operator+( Arg left, Arg right )
|
|
||||||
{
|
|
||||||
Vec3 copy( left );
|
|
||||||
return copy += right;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 operator-( Arg left, Arg right )
|
|
||||||
{
|
|
||||||
Vec3 copy( left );
|
|
||||||
return copy -= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 operator*( Arg left, Arg right )
|
|
||||||
{
|
|
||||||
Vec3 copy( left );
|
|
||||||
return copy *= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 operator*( Arg left, float right )
|
|
||||||
{
|
|
||||||
Vec3 copy( left );
|
|
||||||
return copy *= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 operator*( float left, Arg right )
|
|
||||||
{
|
|
||||||
Vec3 copy( right );
|
|
||||||
return copy *= left;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 operator/( Arg left, Arg right )
|
|
||||||
{
|
|
||||||
Vec3 copy( left );
|
|
||||||
return copy /= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 operator/( Arg left, float right )
|
|
||||||
{
|
|
||||||
Vec3 copy( left );
|
|
||||||
return copy /= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend float Dot( Arg left, Arg right )
|
|
||||||
{
|
|
||||||
return left.m_x*right.m_x + left.m_y*right.m_y + left.m_z*right.m_z;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 Min( Arg left, Arg right )
|
|
||||||
{
|
|
||||||
return Vec3(
|
|
||||||
std::min( left.m_x, right.m_x ),
|
|
||||||
std::min( left.m_y, right.m_y ),
|
|
||||||
std::min( left.m_z, right.m_z )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 Max( Arg left, Arg right )
|
float X() const { return m_x; }
|
||||||
{
|
float Y() const { return m_y; }
|
||||||
return Vec3(
|
float Z() const { return m_z; }
|
||||||
std::max( left.m_x, right.m_x ),
|
|
||||||
std::max( left.m_y, right.m_y ),
|
|
||||||
std::max( left.m_z, right.m_z )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec3 Truncate( Arg v )
|
Vec3 operator-() const
|
||||||
{
|
{
|
||||||
return Vec3(
|
return Vec3( -m_x, -m_y, -m_z );
|
||||||
v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ),
|
}
|
||||||
v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ),
|
|
||||||
v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z )
|
Vec3& operator+=( Arg v )
|
||||||
);
|
{
|
||||||
}
|
m_x += v.m_x;
|
||||||
|
m_y += v.m_y;
|
||||||
|
m_z += v.m_z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3& operator-=( Arg v )
|
||||||
|
{
|
||||||
|
m_x -= v.m_x;
|
||||||
|
m_y -= v.m_y;
|
||||||
|
m_z -= v.m_z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3& operator*=( Arg v )
|
||||||
|
{
|
||||||
|
m_x *= v.m_x;
|
||||||
|
m_y *= v.m_y;
|
||||||
|
m_z *= v.m_z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3& operator*=( float s )
|
||||||
|
{
|
||||||
|
m_x *= s;
|
||||||
|
m_y *= s;
|
||||||
|
m_z *= s;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3& operator/=( Arg v )
|
||||||
|
{
|
||||||
|
m_x /= v.m_x;
|
||||||
|
m_y /= v.m_y;
|
||||||
|
m_z /= v.m_z;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3& operator/=( float s )
|
||||||
|
{
|
||||||
|
float t = 1.0f/s;
|
||||||
|
m_x *= t;
|
||||||
|
m_y *= t;
|
||||||
|
m_z *= t;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 operator+( Arg left, Arg right )
|
||||||
|
{
|
||||||
|
Vec3 copy( left );
|
||||||
|
return copy += right;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 operator-( Arg left, Arg right )
|
||||||
|
{
|
||||||
|
Vec3 copy( left );
|
||||||
|
return copy -= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 operator*( Arg left, Arg right )
|
||||||
|
{
|
||||||
|
Vec3 copy( left );
|
||||||
|
return copy *= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 operator*( Arg left, float right )
|
||||||
|
{
|
||||||
|
Vec3 copy( left );
|
||||||
|
return copy *= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 operator*( float left, Arg right )
|
||||||
|
{
|
||||||
|
Vec3 copy( right );
|
||||||
|
return copy *= left;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 operator/( Arg left, Arg right )
|
||||||
|
{
|
||||||
|
Vec3 copy( left );
|
||||||
|
return copy /= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 operator/( Arg left, float right )
|
||||||
|
{
|
||||||
|
Vec3 copy( left );
|
||||||
|
return copy /= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend float Dot( Arg left, Arg right )
|
||||||
|
{
|
||||||
|
return left.m_x*right.m_x + left.m_y*right.m_y + left.m_z*right.m_z;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 Min( Arg left, Arg right )
|
||||||
|
{
|
||||||
|
return Vec3(
|
||||||
|
std::min( left.m_x, right.m_x ),
|
||||||
|
std::min( left.m_y, right.m_y ),
|
||||||
|
std::min( left.m_z, right.m_z )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 Max( Arg left, Arg right )
|
||||||
|
{
|
||||||
|
return Vec3(
|
||||||
|
std::max( left.m_x, right.m_x ),
|
||||||
|
std::max( left.m_y, right.m_y ),
|
||||||
|
std::max( left.m_z, right.m_z )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec3 Truncate( Arg v )
|
||||||
|
{
|
||||||
|
return Vec3(
|
||||||
|
v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ),
|
||||||
|
v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ),
|
||||||
|
v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_x;
|
float m_x;
|
||||||
float m_y;
|
float m_y;
|
||||||
float m_z;
|
float m_z;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline float LengthSquared( Vec3::Arg v )
|
inline float LengthSquared( Vec3::Arg v )
|
||||||
{
|
{
|
||||||
return Dot( v, v );
|
return Dot( v, v );
|
||||||
}
|
}
|
||||||
|
|
||||||
class Sym3x3
|
class Sym3x3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sym3x3()
|
Sym3x3()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Sym3x3( float s )
|
Sym3x3( float s )
|
||||||
{
|
{
|
||||||
for( int i = 0; i < 6; ++i )
|
for( int i = 0; i < 6; ++i )
|
||||||
m_x[i] = s;
|
m_x[i] = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
float operator[]( int index ) const
|
float operator[]( int index ) const
|
||||||
{
|
{
|
||||||
return m_x[index];
|
return m_x[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
float& operator[]( int index )
|
float& operator[]( int index )
|
||||||
{
|
{
|
||||||
return m_x[index];
|
return m_x[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_x[6];
|
float m_x[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights );
|
Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights );
|
||||||
|
337
thirdparty/squish/rangefit.cpp
vendored
337
thirdparty/squish/rangefit.cpp
vendored
@ -1,28 +1,28 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "rangefit.h"
|
#include "rangefit.h"
|
||||||
#include "colourset.h"
|
#include "colourset.h"
|
||||||
#include "colourblock.h"
|
#include "colourblock.h"
|
||||||
@ -30,173 +30,172 @@
|
|||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
RangeFit::RangeFit( ColourSet const* colours, int flags )
|
RangeFit::RangeFit( ColourSet const* colours, int flags, float* metric )
|
||||||
: ColourFit( colours, flags )
|
: ColourFit( colours, flags )
|
||||||
{
|
{
|
||||||
// initialise the metric
|
// initialise the metric (old perceptual = 0.2126f, 0.7152f, 0.0722f)
|
||||||
bool perceptual = ( ( m_flags & kColourMetricPerceptual ) != 0 );
|
if( metric )
|
||||||
if( perceptual )
|
m_metric = Vec3( metric[0], metric[1], metric[2] );
|
||||||
m_metric = Vec3( 0.2126f, 0.7152f, 0.0722f );
|
else
|
||||||
else
|
m_metric = Vec3( 1.0f );
|
||||||
m_metric = Vec3( 1.0f );
|
|
||||||
|
|
||||||
// initialise the best error
|
// initialise the best error
|
||||||
m_besterror = FLT_MAX;
|
m_besterror = FLT_MAX;
|
||||||
|
|
||||||
// cache some values
|
// cache some values
|
||||||
int const count = m_colours->GetCount();
|
int const count = m_colours->GetCount();
|
||||||
Vec3 const* values = m_colours->GetPoints();
|
Vec3 const* values = m_colours->GetPoints();
|
||||||
float const* weights = m_colours->GetWeights();
|
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
|
// get the covariance matrix
|
||||||
Vec3 start( 0.0f );
|
Sym3x3 covariance = ComputeWeightedCovariance( count, values, weights );
|
||||||
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
|
// compute the principle component
|
||||||
Vec3 const grid( 31.0f, 63.0f, 31.0f );
|
Vec3 principle = ComputePrincipleComponent( covariance );
|
||||||
Vec3 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f );
|
|
||||||
Vec3 const half( 0.5f );
|
// get the min and max range as the codebook endpoints
|
||||||
m_start = Truncate( grid*start + half )*gridrcp;
|
Vec3 start( 0.0f );
|
||||||
m_end = Truncate( grid*end + half )*gridrcp;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RangeFit::Compress3( void* block )
|
void RangeFit::Compress3( void* block )
|
||||||
{
|
{
|
||||||
// cache some values
|
// cache some values
|
||||||
int const count = m_colours->GetCount();
|
int const count = m_colours->GetCount();
|
||||||
Vec3 const* values = m_colours->GetPoints();
|
Vec3 const* values = m_colours->GetPoints();
|
||||||
|
|
||||||
// create a codebook
|
|
||||||
Vec3 codes[3];
|
|
||||||
codes[0] = m_start;
|
|
||||||
codes[1] = m_end;
|
|
||||||
codes[2] = 0.5f*m_start + 0.5f*m_end;
|
|
||||||
|
|
||||||
// match each point to the closest code
|
// create a codebook
|
||||||
u8 closest[16];
|
Vec3 codes[3];
|
||||||
float error = 0.0f;
|
codes[0] = m_start;
|
||||||
for( int i = 0; i < count; ++i )
|
codes[1] = m_end;
|
||||||
{
|
codes[2] = 0.5f*m_start + 0.5f*m_end;
|
||||||
// find the closest code
|
|
||||||
float dist = FLT_MAX;
|
// match each point to the closest code
|
||||||
int idx = 0;
|
u8 closest[16];
|
||||||
for( int j = 0; j < 3; ++j )
|
float error = 0.0f;
|
||||||
{
|
for( int i = 0; i < count; ++i )
|
||||||
float d = LengthSquared( m_metric*( values[i] - codes[j] ) );
|
{
|
||||||
if( d < dist )
|
// find the closest code
|
||||||
{
|
float dist = FLT_MAX;
|
||||||
dist = d;
|
int idx = 0;
|
||||||
idx = j;
|
for( int j = 0; j < 3; ++j )
|
||||||
}
|
{
|
||||||
}
|
float d = LengthSquared( m_metric*( values[i] - codes[j] ) );
|
||||||
|
if( d < dist )
|
||||||
// save the index
|
{
|
||||||
closest[i] = ( u8 )idx;
|
dist = d;
|
||||||
|
idx = j;
|
||||||
// accumulate the error
|
}
|
||||||
error += dist;
|
}
|
||||||
}
|
|
||||||
|
// save the index
|
||||||
// save this scheme if it wins
|
closest[i] = ( u8 )idx;
|
||||||
if( error < m_besterror )
|
|
||||||
{
|
// accumulate the error
|
||||||
// remap the indices
|
error += dist;
|
||||||
u8 indices[16];
|
}
|
||||||
m_colours->RemapIndices( closest, indices );
|
|
||||||
|
// save this scheme if it wins
|
||||||
// save the block
|
if( error < m_besterror )
|
||||||
WriteColourBlock3( m_start, m_end, indices, block );
|
{
|
||||||
|
// remap the indices
|
||||||
// save the error
|
u8 indices[16];
|
||||||
m_besterror = error;
|
m_colours->RemapIndices( closest, indices );
|
||||||
}
|
|
||||||
|
// save the block
|
||||||
|
WriteColourBlock3( m_start, m_end, indices, block );
|
||||||
|
|
||||||
|
// save the error
|
||||||
|
m_besterror = error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RangeFit::Compress4( void* block )
|
void RangeFit::Compress4( void* block )
|
||||||
{
|
{
|
||||||
// cache some values
|
// cache some values
|
||||||
int const count = m_colours->GetCount();
|
int const count = m_colours->GetCount();
|
||||||
Vec3 const* values = m_colours->GetPoints();
|
Vec3 const* values = m_colours->GetPoints();
|
||||||
|
|
||||||
// create a codebook
|
|
||||||
Vec3 codes[4];
|
|
||||||
codes[0] = m_start;
|
|
||||||
codes[1] = m_end;
|
|
||||||
codes[2] = ( 2.0f/3.0f )*m_start + ( 1.0f/3.0f )*m_end;
|
|
||||||
codes[3] = ( 1.0f/3.0f )*m_start + ( 2.0f/3.0f )*m_end;
|
|
||||||
|
|
||||||
// match each point to the closest code
|
// create a codebook
|
||||||
u8 closest[16];
|
Vec3 codes[4];
|
||||||
float error = 0.0f;
|
codes[0] = m_start;
|
||||||
for( int i = 0; i < count; ++i )
|
codes[1] = m_end;
|
||||||
{
|
codes[2] = ( 2.0f/3.0f )*m_start + ( 1.0f/3.0f )*m_end;
|
||||||
// find the closest code
|
codes[3] = ( 1.0f/3.0f )*m_start + ( 2.0f/3.0f )*m_end;
|
||||||
float dist = FLT_MAX;
|
|
||||||
int idx = 0;
|
|
||||||
for( int j = 0; j < 4; ++j )
|
|
||||||
{
|
|
||||||
float d = LengthSquared( m_metric*( values[i] - codes[j] ) );
|
|
||||||
if( d < dist )
|
|
||||||
{
|
|
||||||
dist = d;
|
|
||||||
idx = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the index
|
|
||||||
closest[i] = ( u8 )idx;
|
|
||||||
|
|
||||||
// accumulate the error
|
|
||||||
error += dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save this scheme if it wins
|
|
||||||
if( error < m_besterror )
|
|
||||||
{
|
|
||||||
// remap the indices
|
|
||||||
u8 indices[16];
|
|
||||||
m_colours->RemapIndices( closest, indices );
|
|
||||||
|
|
||||||
// save the block
|
|
||||||
WriteColourBlock4( m_start, m_end, indices, block );
|
|
||||||
|
|
||||||
// save the error
|
// match each point to the closest code
|
||||||
m_besterror = error;
|
u8 closest[16];
|
||||||
}
|
float error = 0.0f;
|
||||||
|
for( int i = 0; i < count; ++i )
|
||||||
|
{
|
||||||
|
// find the closest code
|
||||||
|
float dist = FLT_MAX;
|
||||||
|
int idx = 0;
|
||||||
|
for( int j = 0; j < 4; ++j )
|
||||||
|
{
|
||||||
|
float d = LengthSquared( m_metric*( values[i] - codes[j] ) );
|
||||||
|
if( d < dist )
|
||||||
|
{
|
||||||
|
dist = d;
|
||||||
|
idx = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the index
|
||||||
|
closest[i] = ( u8 )idx;
|
||||||
|
|
||||||
|
// accumulate the error
|
||||||
|
error += dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save this scheme if it wins
|
||||||
|
if( error < m_besterror )
|
||||||
|
{
|
||||||
|
// remap the indices
|
||||||
|
u8 indices[16];
|
||||||
|
m_colours->RemapIndices( closest, indices );
|
||||||
|
|
||||||
|
// save the block
|
||||||
|
WriteColourBlock4( m_start, m_end, indices, block );
|
||||||
|
|
||||||
|
// save the error
|
||||||
|
m_besterror = error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
58
thirdparty/squish/rangefit.h
vendored
58
thirdparty/squish/rangefit.h
vendored
@ -1,32 +1,32 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_RANGEFIT_H
|
#ifndef SQUISH_RANGEFIT_H
|
||||||
#define SQUISH_RANGEFIT_H
|
#define SQUISH_RANGEFIT_H
|
||||||
|
|
||||||
#include <squish.h>
|
#include "squish.h"
|
||||||
#include "colourfit.h"
|
#include "colourfit.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
|
|
||||||
@ -37,16 +37,16 @@ class ColourSet;
|
|||||||
class RangeFit : public ColourFit
|
class RangeFit : public ColourFit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RangeFit( ColourSet const* colours, int flags );
|
RangeFit( ColourSet const* colours, int flags, float* metric );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Compress3( void* block );
|
virtual void Compress3( void* block );
|
||||||
virtual void Compress4( void* block );
|
virtual void Compress4( void* block );
|
||||||
|
|
||||||
Vec3 m_metric;
|
Vec3 m_metric;
|
||||||
Vec3 m_start;
|
Vec3 m_start;
|
||||||
Vec3 m_end;
|
Vec3 m_end;
|
||||||
float m_besterror;
|
float m_besterror;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // squish
|
} // squish
|
||||||
|
38
thirdparty/squish/simd.h
vendored
38
thirdparty/squish/simd.h
vendored
@ -1,28 +1,28 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_SIMD_H
|
#ifndef SQUISH_SIMD_H
|
||||||
#define SQUISH_SIMD_H
|
#define SQUISH_SIMD_H
|
||||||
|
|
||||||
|
312
thirdparty/squish/simd_float.h
vendored
312
thirdparty/squish/simd_float.h
vendored
@ -1,28 +1,28 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_SIMD_FLOAT_H
|
#ifndef SQUISH_SIMD_FLOAT_H
|
||||||
#define SQUISH_SIMD_FLOAT_H
|
#define SQUISH_SIMD_FLOAT_H
|
||||||
|
|
||||||
@ -35,146 +35,146 @@ namespace squish {
|
|||||||
class Vec4
|
class Vec4
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Vec4 const& Arg;
|
typedef Vec4 const& Arg;
|
||||||
|
|
||||||
Vec4() {}
|
Vec4() {}
|
||||||
|
|
||||||
explicit Vec4( float s )
|
explicit Vec4( float s )
|
||||||
: m_x( s ),
|
: m_x( s ),
|
||||||
m_y( s ),
|
m_y( s ),
|
||||||
m_z( s ),
|
m_z( s ),
|
||||||
m_w( s )
|
m_w( s )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4( float x, float y, float z, float w )
|
Vec4( float x, float y, float z, float w )
|
||||||
: m_x( x ),
|
: m_x( x ),
|
||||||
m_y( y ),
|
m_y( y ),
|
||||||
m_z( z ),
|
m_z( z ),
|
||||||
m_w( w )
|
m_w( w )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 GetVec3() const
|
Vec3 GetVec3() const
|
||||||
{
|
{
|
||||||
return Vec3( m_x, m_y, m_z );
|
return Vec3( m_x, m_y, m_z );
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 SplatX() const { return Vec4( m_x ); }
|
Vec4 SplatX() const { return Vec4( m_x ); }
|
||||||
Vec4 SplatY() const { return Vec4( m_y ); }
|
Vec4 SplatY() const { return Vec4( m_y ); }
|
||||||
Vec4 SplatZ() const { return Vec4( m_z ); }
|
Vec4 SplatZ() const { return Vec4( m_z ); }
|
||||||
Vec4 SplatW() const { return Vec4( m_w ); }
|
Vec4 SplatW() const { return Vec4( m_w ); }
|
||||||
|
|
||||||
|
Vec4& operator+=( Arg v )
|
||||||
|
{
|
||||||
|
m_x += v.m_x;
|
||||||
|
m_y += v.m_y;
|
||||||
|
m_z += v.m_z;
|
||||||
|
m_w += v.m_w;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4& operator-=( Arg v )
|
||||||
|
{
|
||||||
|
m_x -= v.m_x;
|
||||||
|
m_y -= v.m_y;
|
||||||
|
m_z -= v.m_z;
|
||||||
|
m_w -= v.m_w;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4& operator*=( Arg v )
|
||||||
|
{
|
||||||
|
m_x *= v.m_x;
|
||||||
|
m_y *= v.m_y;
|
||||||
|
m_z *= v.m_z;
|
||||||
|
m_w *= v.m_w;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
Vec4 copy( left );
|
||||||
|
return copy += right;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
Vec4 copy( left );
|
||||||
|
return copy -= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
Vec4 copy( left );
|
||||||
|
return copy *= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns a*b + c
|
||||||
|
friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
||||||
|
{
|
||||||
|
return a*b + c;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns -( a*b - c )
|
||||||
|
friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
||||||
|
{
|
||||||
|
return c - a*b;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Reciprocal( Vec4::Arg v )
|
||||||
|
{
|
||||||
|
return Vec4(
|
||||||
|
1.0f/v.m_x,
|
||||||
|
1.0f/v.m_y,
|
||||||
|
1.0f/v.m_z,
|
||||||
|
1.0f/v.m_w
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Min( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4(
|
||||||
|
std::min( left.m_x, right.m_x ),
|
||||||
|
std::min( left.m_y, right.m_y ),
|
||||||
|
std::min( left.m_z, right.m_z ),
|
||||||
|
std::min( left.m_w, right.m_w )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Max( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4(
|
||||||
|
std::max( left.m_x, right.m_x ),
|
||||||
|
std::max( left.m_y, right.m_y ),
|
||||||
|
std::max( left.m_z, right.m_z ),
|
||||||
|
std::max( left.m_w, right.m_w )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Truncate( Vec4::Arg v )
|
||||||
|
{
|
||||||
|
return Vec4(
|
||||||
|
v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ),
|
||||||
|
v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ),
|
||||||
|
v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z ),
|
||||||
|
v.m_w > 0.0f ? std::floor( v.m_w ) : std::ceil( v.m_w )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return left.m_x < right.m_x
|
||||||
|
|| left.m_y < right.m_y
|
||||||
|
|| left.m_z < right.m_z
|
||||||
|
|| left.m_w < right.m_w;
|
||||||
|
}
|
||||||
|
|
||||||
Vec4& operator+=( Arg v )
|
|
||||||
{
|
|
||||||
m_x += v.m_x;
|
|
||||||
m_y += v.m_y;
|
|
||||||
m_z += v.m_z;
|
|
||||||
m_w += v.m_w;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec4& operator-=( Arg v )
|
|
||||||
{
|
|
||||||
m_x -= v.m_x;
|
|
||||||
m_y -= v.m_y;
|
|
||||||
m_z -= v.m_z;
|
|
||||||
m_w -= v.m_w;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec4& operator*=( Arg v )
|
|
||||||
{
|
|
||||||
m_x *= v.m_x;
|
|
||||||
m_y *= v.m_y;
|
|
||||||
m_z *= v.m_z;
|
|
||||||
m_w *= v.m_w;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
Vec4 copy( left );
|
|
||||||
return copy += right;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
Vec4 copy( left );
|
|
||||||
return copy -= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
Vec4 copy( left );
|
|
||||||
return copy *= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns a*b + c
|
|
||||||
friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
|
||||||
{
|
|
||||||
return a*b + c;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns -( a*b - c )
|
|
||||||
friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
|
||||||
{
|
|
||||||
return c - a*b;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Reciprocal( Vec4::Arg v )
|
|
||||||
{
|
|
||||||
return Vec4(
|
|
||||||
1.0f/v.m_x,
|
|
||||||
1.0f/v.m_y,
|
|
||||||
1.0f/v.m_z,
|
|
||||||
1.0f/v.m_w
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Min( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4(
|
|
||||||
std::min( left.m_x, right.m_x ),
|
|
||||||
std::min( left.m_y, right.m_y ),
|
|
||||||
std::min( left.m_z, right.m_z ),
|
|
||||||
std::min( left.m_w, right.m_w )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Max( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4(
|
|
||||||
std::max( left.m_x, right.m_x ),
|
|
||||||
std::max( left.m_y, right.m_y ),
|
|
||||||
std::max( left.m_z, right.m_z ),
|
|
||||||
std::max( left.m_w, right.m_w )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Truncate( Vec4::Arg v )
|
|
||||||
{
|
|
||||||
return Vec4(
|
|
||||||
v.m_x > 0.0f ? std::floor( v.m_x ) : std::ceil( v.m_x ),
|
|
||||||
v.m_y > 0.0f ? std::floor( v.m_y ) : std::ceil( v.m_y ),
|
|
||||||
v.m_z > 0.0f ? std::floor( v.m_z ) : std::ceil( v.m_z ),
|
|
||||||
v.m_w > 0.0f ? std::floor( v.m_w ) : std::ceil( v.m_w )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return left.m_x < right.m_x
|
|
||||||
|| left.m_y < right.m_y
|
|
||||||
|| left.m_z < right.m_z
|
|
||||||
|| left.m_w < right.m_w;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_x;
|
float m_x;
|
||||||
float m_y;
|
float m_y;
|
||||||
float m_z;
|
float m_z;
|
||||||
float m_w;
|
float m_w;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
282
thirdparty/squish/simd_sse.h
vendored
282
thirdparty/squish/simd_sse.h
vendored
@ -1,28 +1,28 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_SIMD_SSE_H
|
#ifndef SQUISH_SIMD_SSE_H
|
||||||
#define SQUISH_SIMD_SSE_H
|
#define SQUISH_SIMD_SSE_H
|
||||||
|
|
||||||
@ -31,11 +31,11 @@
|
|||||||
#include <emmintrin.h>
|
#include <emmintrin.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SQUISH_SSE_SPLAT( a ) \
|
#define SQUISH_SSE_SPLAT( a ) \
|
||||||
( ( a ) | ( ( a ) << 2 ) | ( ( a ) << 4 ) | ( ( a ) << 6 ) )
|
( ( a ) | ( ( a ) << 2 ) | ( ( a ) << 4 ) | ( ( a ) << 6 ) )
|
||||||
|
|
||||||
#define SQUISH_SSE_SHUF( x, y, z, w ) \
|
#define SQUISH_SSE_SHUF( x, y, z, w ) \
|
||||||
( ( x ) | ( ( y ) << 2 ) | ( ( z ) << 4 ) | ( ( w ) << 6 ) )
|
( ( x ) | ( ( y ) << 2 ) | ( ( z ) << 4 ) | ( ( w ) << 6 ) )
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
@ -44,135 +44,135 @@ namespace squish {
|
|||||||
class Vec4
|
class Vec4
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Vec4 const& Arg;
|
typedef Vec4 const& Arg;
|
||||||
|
|
||||||
Vec4() {}
|
Vec4() {}
|
||||||
|
|
||||||
explicit Vec4( __m128 v ) : m_v( v ) {}
|
explicit Vec4( __m128 v ) : m_v( v ) {}
|
||||||
|
|
||||||
Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {}
|
Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {}
|
||||||
|
|
||||||
Vec4& operator=( Vec4 const& arg )
|
Vec4& operator=( Vec4 const& arg )
|
||||||
{
|
{
|
||||||
m_v = arg.m_v;
|
m_v = arg.m_v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Vec4( float s ) : m_v( _mm_set1_ps( s ) ) {}
|
explicit Vec4( float s ) : m_v( _mm_set1_ps( s ) ) {}
|
||||||
|
|
||||||
Vec4( float x, float y, float z, float w ) : m_v( _mm_setr_ps( x, y, z, w ) ) {}
|
Vec4( float x, float y, float z, float w ) : m_v( _mm_setr_ps( x, y, z, w ) ) {}
|
||||||
|
|
||||||
Vec3 GetVec3() const
|
Vec3 GetVec3() const
|
||||||
{
|
{
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__attribute__ ((__aligned__ (16))) float c[4];
|
__attribute__ ((__aligned__ (16))) float c[4];
|
||||||
#else
|
#else
|
||||||
__declspec(align(16)) float c[4];
|
__declspec(align(16)) float c[4];
|
||||||
#endif
|
#endif
|
||||||
_mm_store_ps( c, m_v );
|
_mm_store_ps( c, m_v );
|
||||||
return Vec3( c[0], c[1], c[2] );
|
return Vec3( c[0], c[1], c[2] );
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 SplatX() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 0 ) ) ); }
|
|
||||||
Vec4 SplatY() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 1 ) ) ); }
|
|
||||||
Vec4 SplatZ() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 2 ) ) ); }
|
|
||||||
Vec4 SplatW() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 3 ) ) ); }
|
|
||||||
|
|
||||||
Vec4& operator+=( Arg v )
|
Vec4 SplatX() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 0 ) ) ); }
|
||||||
{
|
Vec4 SplatY() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 1 ) ) ); }
|
||||||
m_v = _mm_add_ps( m_v, v.m_v );
|
Vec4 SplatZ() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 2 ) ) ); }
|
||||||
return *this;
|
Vec4 SplatW() const { return Vec4( _mm_shuffle_ps( m_v, m_v, SQUISH_SSE_SPLAT( 3 ) ) ); }
|
||||||
}
|
|
||||||
|
|
||||||
Vec4& operator-=( Arg v )
|
|
||||||
{
|
|
||||||
m_v = _mm_sub_ps( m_v, v.m_v );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec4& operator*=( Arg v )
|
|
||||||
{
|
|
||||||
m_v = _mm_mul_ps( m_v, v.m_v );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4( _mm_add_ps( left.m_v, right.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4( _mm_sub_ps( left.m_v, right.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4( _mm_mul_ps( left.m_v, right.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns a*b + c
|
|
||||||
friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
|
||||||
{
|
|
||||||
return Vec4( _mm_add_ps( _mm_mul_ps( a.m_v, b.m_v ), c.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns -( a*b - c )
|
|
||||||
friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
|
||||||
{
|
|
||||||
return Vec4( _mm_sub_ps( c.m_v, _mm_mul_ps( a.m_v, b.m_v ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Reciprocal( Vec4::Arg v )
|
|
||||||
{
|
|
||||||
// get the reciprocal estimate
|
|
||||||
__m128 estimate = _mm_rcp_ps( v.m_v );
|
|
||||||
|
|
||||||
// one round of Newton-Rhaphson refinement
|
Vec4& operator+=( Arg v )
|
||||||
__m128 diff = _mm_sub_ps( _mm_set1_ps( 1.0f ), _mm_mul_ps( estimate, v.m_v ) );
|
{
|
||||||
return Vec4( _mm_add_ps( _mm_mul_ps( diff, estimate ), estimate ) );
|
m_v = _mm_add_ps( m_v, v.m_v );
|
||||||
}
|
return *this;
|
||||||
|
}
|
||||||
friend Vec4 Min( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
Vec4& operator-=( Arg v )
|
||||||
return Vec4( _mm_min_ps( left.m_v, right.m_v ) );
|
{
|
||||||
}
|
m_v = _mm_sub_ps( m_v, v.m_v );
|
||||||
|
return *this;
|
||||||
friend Vec4 Max( Vec4::Arg left, Vec4::Arg right )
|
}
|
||||||
{
|
|
||||||
return Vec4( _mm_max_ps( left.m_v, right.m_v ) );
|
Vec4& operator*=( Arg v )
|
||||||
}
|
{
|
||||||
|
m_v = _mm_mul_ps( m_v, v.m_v );
|
||||||
friend Vec4 Truncate( Vec4::Arg v )
|
return *this;
|
||||||
{
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( _mm_add_ps( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( _mm_sub_ps( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( _mm_mul_ps( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns a*b + c
|
||||||
|
friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
||||||
|
{
|
||||||
|
return Vec4( _mm_add_ps( _mm_mul_ps( a.m_v, b.m_v ), c.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns -( a*b - c )
|
||||||
|
friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
||||||
|
{
|
||||||
|
return Vec4( _mm_sub_ps( c.m_v, _mm_mul_ps( a.m_v, b.m_v ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Reciprocal( Vec4::Arg v )
|
||||||
|
{
|
||||||
|
// get the reciprocal estimate
|
||||||
|
__m128 estimate = _mm_rcp_ps( v.m_v );
|
||||||
|
|
||||||
|
// one round of Newton-Rhaphson refinement
|
||||||
|
__m128 diff = _mm_sub_ps( _mm_set1_ps( 1.0f ), _mm_mul_ps( estimate, v.m_v ) );
|
||||||
|
return Vec4( _mm_add_ps( _mm_mul_ps( diff, estimate ), estimate ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Min( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( _mm_min_ps( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Max( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( _mm_max_ps( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Truncate( Vec4::Arg v )
|
||||||
|
{
|
||||||
#if ( SQUISH_USE_SSE == 1 )
|
#if ( SQUISH_USE_SSE == 1 )
|
||||||
// convert to ints
|
// convert to ints
|
||||||
__m128 input = v.m_v;
|
__m128 input = v.m_v;
|
||||||
__m64 lo = _mm_cvttps_pi32( input );
|
__m64 lo = _mm_cvttps_pi32( input );
|
||||||
__m64 hi = _mm_cvttps_pi32( _mm_movehl_ps( input, input ) );
|
__m64 hi = _mm_cvttps_pi32( _mm_movehl_ps( input, input ) );
|
||||||
|
|
||||||
// convert to floats
|
// convert to floats
|
||||||
__m128 part = _mm_movelh_ps( input, _mm_cvtpi32_ps( input, hi ) );
|
__m128 part = _mm_movelh_ps( input, _mm_cvtpi32_ps( input, hi ) );
|
||||||
__m128 truncated = _mm_cvtpi32_ps( part, lo );
|
__m128 truncated = _mm_cvtpi32_ps( part, lo );
|
||||||
|
|
||||||
// clear out the MMX multimedia state to allow FP calls later
|
// clear out the MMX multimedia state to allow FP calls later
|
||||||
_mm_empty();
|
_mm_empty();
|
||||||
return Vec4( truncated );
|
return Vec4( truncated );
|
||||||
#else
|
#else
|
||||||
// use SSE2 instructions
|
// use SSE2 instructions
|
||||||
return Vec4( _mm_cvtepi32_ps( _mm_cvttps_epi32( v.m_v ) ) );
|
return Vec4( _mm_cvtepi32_ps( _mm_cvttps_epi32( v.m_v ) ) );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right )
|
friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right )
|
||||||
{
|
{
|
||||||
__m128 bits = _mm_cmplt_ps( left.m_v, right.m_v );
|
__m128 bits = _mm_cmplt_ps( left.m_v, right.m_v );
|
||||||
int value = _mm_movemask_ps( bits );
|
int value = _mm_movemask_ps( bits );
|
||||||
return value != 0;
|
return value != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
__m128 m_v;
|
__m128 m_v;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
280
thirdparty/squish/simd_ve.h
vendored
280
thirdparty/squish/simd_ve.h
vendored
@ -1,28 +1,28 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_SIMD_VE_H
|
#ifndef SQUISH_SIMD_VE_H
|
||||||
#define SQUISH_SIMD_VE_H
|
#define SQUISH_SIMD_VE_H
|
||||||
|
|
||||||
@ -31,134 +31,134 @@
|
|||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
#define VEC4_CONST( X ) Vec4( ( vector float )( X ) )
|
#define VEC4_CONST( X ) Vec4( ( vector float ){ X } )
|
||||||
|
|
||||||
class Vec4
|
class Vec4
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Vec4 Arg;
|
typedef Vec4 Arg;
|
||||||
|
|
||||||
Vec4() {}
|
Vec4() {}
|
||||||
|
|
||||||
explicit Vec4( vector float v ) : m_v( v ) {}
|
explicit Vec4( vector float v ) : m_v( v ) {}
|
||||||
|
|
||||||
Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {}
|
Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {}
|
||||||
|
|
||||||
Vec4& operator=( Vec4 const& arg )
|
Vec4& operator=( Vec4 const& arg )
|
||||||
{
|
{
|
||||||
m_v = arg.m_v;
|
m_v = arg.m_v;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Vec4( float s )
|
explicit Vec4( float s )
|
||||||
{
|
{
|
||||||
union { vector float v; float c[4]; } u;
|
union { vector float v; float c[4]; } u;
|
||||||
u.c[0] = s;
|
u.c[0] = s;
|
||||||
u.c[1] = s;
|
u.c[1] = s;
|
||||||
u.c[2] = s;
|
u.c[2] = s;
|
||||||
u.c[3] = s;
|
u.c[3] = s;
|
||||||
m_v = u.v;
|
m_v = u.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4( float x, float y, float z, float w )
|
Vec4( float x, float y, float z, float w )
|
||||||
{
|
{
|
||||||
union { vector float v; float c[4]; } u;
|
union { vector float v; float c[4]; } u;
|
||||||
u.c[0] = x;
|
u.c[0] = x;
|
||||||
u.c[1] = y;
|
u.c[1] = y;
|
||||||
u.c[2] = z;
|
u.c[2] = z;
|
||||||
u.c[3] = w;
|
u.c[3] = w;
|
||||||
m_v = u.v;
|
m_v = u.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3 GetVec3() const
|
Vec3 GetVec3() const
|
||||||
{
|
{
|
||||||
union { vector float v; float c[4]; } u;
|
union { vector float v; float c[4]; } u;
|
||||||
u.v = m_v;
|
u.v = m_v;
|
||||||
return Vec3( u.c[0], u.c[1], u.c[2] );
|
return Vec3( u.c[0], u.c[1], u.c[2] );
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 SplatX() const { return Vec4( vec_splat( m_v, 0 ) ); }
|
Vec4 SplatX() const { return Vec4( vec_splat( m_v, 0 ) ); }
|
||||||
Vec4 SplatY() const { return Vec4( vec_splat( m_v, 1 ) ); }
|
Vec4 SplatY() const { return Vec4( vec_splat( m_v, 1 ) ); }
|
||||||
Vec4 SplatZ() const { return Vec4( vec_splat( m_v, 2 ) ); }
|
Vec4 SplatZ() const { return Vec4( vec_splat( m_v, 2 ) ); }
|
||||||
Vec4 SplatW() const { return Vec4( vec_splat( m_v, 3 ) ); }
|
Vec4 SplatW() const { return Vec4( vec_splat( m_v, 3 ) ); }
|
||||||
|
|
||||||
|
Vec4& operator+=( Arg v )
|
||||||
|
{
|
||||||
|
m_v = vec_add( m_v, v.m_v );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4& operator-=( Arg v )
|
||||||
|
{
|
||||||
|
m_v = vec_sub( m_v, v.m_v );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4& operator*=( Arg v )
|
||||||
|
{
|
||||||
|
m_v = vec_madd( m_v, v.m_v, ( vector float ){ -0.0f } );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( vec_add( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( vec_sub( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( vec_madd( left.m_v, right.m_v, ( vector float ){ -0.0f } ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns a*b + c
|
||||||
|
friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
||||||
|
{
|
||||||
|
return Vec4( vec_madd( a.m_v, b.m_v, c.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Returns -( a*b - c )
|
||||||
|
friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
||||||
|
{
|
||||||
|
return Vec4( vec_nmsub( a.m_v, b.m_v, c.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Reciprocal( Vec4::Arg v )
|
||||||
|
{
|
||||||
|
// get the reciprocal estimate
|
||||||
|
vector float estimate = vec_re( v.m_v );
|
||||||
|
|
||||||
|
// one round of Newton-Rhaphson refinement
|
||||||
|
vector float diff = vec_nmsub( estimate, v.m_v, ( vector float ){ 1.0f } );
|
||||||
|
return Vec4( vec_madd( diff, estimate, estimate ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Min( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( vec_min( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Max( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return Vec4( vec_max( left.m_v, right.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend Vec4 Truncate( Vec4::Arg v )
|
||||||
|
{
|
||||||
|
return Vec4( vec_trunc( v.m_v ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right )
|
||||||
|
{
|
||||||
|
return vec_any_lt( left.m_v, right.m_v ) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
Vec4& operator+=( Arg v )
|
|
||||||
{
|
|
||||||
m_v = vec_add( m_v, v.m_v );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec4& operator-=( Arg v )
|
|
||||||
{
|
|
||||||
m_v = vec_sub( m_v, v.m_v );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec4& operator*=( Arg v )
|
|
||||||
{
|
|
||||||
m_v = vec_madd( m_v, v.m_v, ( vector float )( -0.0f ) );
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4( vec_add( left.m_v, right.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4( vec_sub( left.m_v, right.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4( vec_madd( left.m_v, right.m_v, ( vector float )( -0.0f ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns a*b + c
|
|
||||||
friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
|
||||||
{
|
|
||||||
return Vec4( vec_madd( a.m_v, b.m_v, c.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Returns -( a*b - c )
|
|
||||||
friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c )
|
|
||||||
{
|
|
||||||
return Vec4( vec_nmsub( a.m_v, b.m_v, c.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Reciprocal( Vec4::Arg v )
|
|
||||||
{
|
|
||||||
// get the reciprocal estimate
|
|
||||||
vector float estimate = vec_re( v.m_v );
|
|
||||||
|
|
||||||
// one round of Newton-Rhaphson refinement
|
|
||||||
vector float diff = vec_nmsub( estimate, v.m_v, ( vector float )( 1.0f ) );
|
|
||||||
return Vec4( vec_madd( diff, estimate, estimate ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Min( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4( vec_min( left.m_v, right.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Max( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return Vec4( vec_max( left.m_v, right.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend Vec4 Truncate( Vec4::Arg v )
|
|
||||||
{
|
|
||||||
return Vec4( vec_trunc( v.m_v ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right )
|
|
||||||
{
|
|
||||||
return vec_any_lt( left.m_v, right.m_v ) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vector float m_v;
|
vector float m_v;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
249
thirdparty/squish/singlecolourfit.cpp
vendored
249
thirdparty/squish/singlecolourfit.cpp
vendored
@ -1,173 +1,172 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "singlecolourfit.h"
|
#include "singlecolourfit.h"
|
||||||
#include "colourset.h"
|
#include "colourset.h"
|
||||||
#include "colourblock.h"
|
#include "colourblock.h"
|
||||||
#include <climits>
|
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
|
|
||||||
struct SourceBlock
|
struct SourceBlock
|
||||||
{
|
{
|
||||||
u8 start;
|
u8 start;
|
||||||
u8 end;
|
u8 end;
|
||||||
u8 error;
|
u8 error;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SingleColourLookup
|
struct SingleColourLookup
|
||||||
{
|
{
|
||||||
SourceBlock sources[2];
|
SourceBlock sources[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "singlecolourlookup.inl"
|
#include "singlecolourlookup.inl"
|
||||||
|
|
||||||
static int FloatToInt( float a, int limit )
|
static int FloatToInt( float a, int limit )
|
||||||
{
|
{
|
||||||
// use ANSI round-to-zero behaviour to get round-to-nearest
|
// use ANSI round-to-zero behaviour to get round-to-nearest
|
||||||
int i = ( int )( a + 0.5f );
|
int i = ( int )( a + 0.5f );
|
||||||
|
|
||||||
// clamp to the limit
|
// clamp to the limit
|
||||||
if( i < 0 )
|
if( i < 0 )
|
||||||
i = 0;
|
i = 0;
|
||||||
else if( i > limit )
|
else if( i > limit )
|
||||||
i = limit;
|
i = limit;
|
||||||
|
|
||||||
// done
|
// done
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleColourFit::SingleColourFit( ColourSet const* colours, int flags )
|
SingleColourFit::SingleColourFit( ColourSet const* colours, int flags )
|
||||||
: ColourFit( colours, flags )
|
: ColourFit( colours, flags )
|
||||||
{
|
{
|
||||||
// grab the single colour
|
// grab the single colour
|
||||||
Vec3 const* values = m_colours->GetPoints();
|
Vec3 const* values = m_colours->GetPoints();
|
||||||
m_colour[0] = ( u8 )FloatToInt( 255.0f*values->X(), 255 );
|
m_colour[0] = ( u8 )FloatToInt( 255.0f*values->X(), 255 );
|
||||||
m_colour[1] = ( u8 )FloatToInt( 255.0f*values->Y(), 255 );
|
m_colour[1] = ( u8 )FloatToInt( 255.0f*values->Y(), 255 );
|
||||||
m_colour[2] = ( u8 )FloatToInt( 255.0f*values->Z(), 255 );
|
m_colour[2] = ( u8 )FloatToInt( 255.0f*values->Z(), 255 );
|
||||||
|
|
||||||
// initialise the best error
|
// initialise the best error
|
||||||
m_besterror = INT_MAX;
|
m_besterror = INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleColourFit::Compress3( void* block )
|
void SingleColourFit::Compress3( void* block )
|
||||||
{
|
{
|
||||||
// build the table of lookups
|
// build the table of lookups
|
||||||
SingleColourLookup const* const lookups[] =
|
SingleColourLookup const* const lookups[] =
|
||||||
{
|
{
|
||||||
lookup_5_3,
|
lookup_5_3,
|
||||||
lookup_6_3,
|
lookup_6_3,
|
||||||
lookup_5_3
|
lookup_5_3
|
||||||
};
|
};
|
||||||
|
|
||||||
// find the best end-points and index
|
|
||||||
ComputeEndPoints( lookups );
|
|
||||||
|
|
||||||
// build the block if we win
|
|
||||||
if( m_error < m_besterror )
|
|
||||||
{
|
|
||||||
// remap the indices
|
|
||||||
u8 indices[16];
|
|
||||||
m_colours->RemapIndices( &m_index, indices );
|
|
||||||
|
|
||||||
// save the block
|
|
||||||
WriteColourBlock3( m_start, m_end, indices, block );
|
|
||||||
|
|
||||||
// save the error
|
// find the best end-points and index
|
||||||
m_besterror = m_error;
|
ComputeEndPoints( lookups );
|
||||||
}
|
|
||||||
|
// build the block if we win
|
||||||
|
if( m_error < m_besterror )
|
||||||
|
{
|
||||||
|
// remap the indices
|
||||||
|
u8 indices[16];
|
||||||
|
m_colours->RemapIndices( &m_index, indices );
|
||||||
|
|
||||||
|
// save the block
|
||||||
|
WriteColourBlock3( m_start, m_end, indices, block );
|
||||||
|
|
||||||
|
// save the error
|
||||||
|
m_besterror = m_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleColourFit::Compress4( void* block )
|
void SingleColourFit::Compress4( void* block )
|
||||||
{
|
{
|
||||||
// build the table of lookups
|
// build the table of lookups
|
||||||
SingleColourLookup const* const lookups[] =
|
SingleColourLookup const* const lookups[] =
|
||||||
{
|
{
|
||||||
lookup_5_4,
|
lookup_5_4,
|
||||||
lookup_6_4,
|
lookup_6_4,
|
||||||
lookup_5_4
|
lookup_5_4
|
||||||
};
|
};
|
||||||
|
|
||||||
// find the best end-points and index
|
|
||||||
ComputeEndPoints( lookups );
|
|
||||||
|
|
||||||
// build the block if we win
|
|
||||||
if( m_error < m_besterror )
|
|
||||||
{
|
|
||||||
// remap the indices
|
|
||||||
u8 indices[16];
|
|
||||||
m_colours->RemapIndices( &m_index, indices );
|
|
||||||
|
|
||||||
// save the block
|
|
||||||
WriteColourBlock4( m_start, m_end, indices, block );
|
|
||||||
|
|
||||||
// save the error
|
// find the best end-points and index
|
||||||
m_besterror = m_error;
|
ComputeEndPoints( lookups );
|
||||||
}
|
|
||||||
|
// build the block if we win
|
||||||
|
if( m_error < m_besterror )
|
||||||
|
{
|
||||||
|
// remap the indices
|
||||||
|
u8 indices[16];
|
||||||
|
m_colours->RemapIndices( &m_index, indices );
|
||||||
|
|
||||||
|
// save the block
|
||||||
|
WriteColourBlock4( m_start, m_end, indices, block );
|
||||||
|
|
||||||
|
// save the error
|
||||||
|
m_besterror = m_error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleColourFit::ComputeEndPoints( SingleColourLookup const* const* lookups )
|
void SingleColourFit::ComputeEndPoints( SingleColourLookup const* const* lookups )
|
||||||
{
|
{
|
||||||
// check each index combination (endpoint or intermediate)
|
// check each index combination (endpoint or intermediate)
|
||||||
m_error = INT_MAX;
|
m_error = INT_MAX;
|
||||||
for( int index = 0; index < 2; ++index )
|
for( int index = 0; index < 2; ++index )
|
||||||
{
|
{
|
||||||
// check the error for this codebook index
|
// check the error for this codebook index
|
||||||
SourceBlock const* sources[3];
|
SourceBlock const* sources[3];
|
||||||
int error = 0;
|
int error = 0;
|
||||||
for( int channel = 0; channel < 3; ++channel )
|
for( int channel = 0; channel < 3; ++channel )
|
||||||
{
|
{
|
||||||
// grab the lookup table and index for this channel
|
// grab the lookup table and index for this channel
|
||||||
SingleColourLookup const* lookup = lookups[channel];
|
SingleColourLookup const* lookup = lookups[channel];
|
||||||
int target = m_colour[channel];
|
int target = m_colour[channel];
|
||||||
|
|
||||||
// store a pointer to the source for this channel
|
// store a pointer to the source for this channel
|
||||||
sources[channel] = lookup[target].sources + index;
|
sources[channel] = lookup[target].sources + index;
|
||||||
|
|
||||||
// accumulate the error
|
// accumulate the error
|
||||||
int diff = sources[channel]->error;
|
int diff = sources[channel]->error;
|
||||||
error += diff*diff;
|
error += diff*diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep it if the error is lower
|
// keep it if the error is lower
|
||||||
if( error < m_error )
|
if( error < m_error )
|
||||||
{
|
{
|
||||||
m_start = Vec3(
|
m_start = Vec3(
|
||||||
( float )sources[0]->start/31.0f,
|
( float )sources[0]->start/31.0f,
|
||||||
( float )sources[1]->start/63.0f,
|
( float )sources[1]->start/63.0f,
|
||||||
( float )sources[2]->start/31.0f
|
( float )sources[2]->start/31.0f
|
||||||
);
|
);
|
||||||
m_end = Vec3(
|
m_end = Vec3(
|
||||||
( float )sources[0]->end/31.0f,
|
( float )sources[0]->end/31.0f,
|
||||||
( float )sources[1]->end/63.0f,
|
( float )sources[1]->end/63.0f,
|
||||||
( float )sources[2]->end/31.0f
|
( float )sources[2]->end/31.0f
|
||||||
);
|
);
|
||||||
m_index = ( u8 )( 2*index );
|
m_index = ( u8 )( 2*index );
|
||||||
m_error = error;
|
m_error = error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
66
thirdparty/squish/singlecolourfit.h
vendored
66
thirdparty/squish/singlecolourfit.h
vendored
@ -1,32 +1,32 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_SINGLECOLOURFIT_H
|
#ifndef SQUISH_SINGLECOLOURFIT_H
|
||||||
#define SQUISH_SINGLECOLOURFIT_H
|
#define SQUISH_SINGLECOLOURFIT_H
|
||||||
|
|
||||||
#include <squish.h>
|
#include "squish.h"
|
||||||
#include "colourfit.h"
|
#include "colourfit.h"
|
||||||
|
|
||||||
namespace squish {
|
namespace squish {
|
||||||
@ -37,20 +37,20 @@ struct SingleColourLookup;
|
|||||||
class SingleColourFit : public ColourFit
|
class SingleColourFit : public ColourFit
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SingleColourFit( ColourSet const* colours, int flags );
|
SingleColourFit( ColourSet const* colours, int flags );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Compress3( void* block );
|
virtual void Compress3( void* block );
|
||||||
virtual void Compress4( void* block );
|
virtual void Compress4( void* block );
|
||||||
|
|
||||||
void ComputeEndPoints( SingleColourLookup const* const* lookups );
|
void ComputeEndPoints( SingleColourLookup const* const* lookups );
|
||||||
|
|
||||||
u8 m_colour[3];
|
u8 m_colour[3];
|
||||||
Vec3 m_start;
|
Vec3 m_start;
|
||||||
Vec3 m_end;
|
Vec3 m_end;
|
||||||
u8 m_index;
|
u8 m_index;
|
||||||
int m_error;
|
int m_error;
|
||||||
int m_besterror;
|
int m_besterror;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
2080
thirdparty/squish/singlecolourlookup.inl
vendored
2080
thirdparty/squish/singlecolourlookup.inl
vendored
File diff suppressed because it is too large
Load Diff
536
thirdparty/squish/squish.cpp
vendored
536
thirdparty/squish/squish.cpp
vendored
@ -1,29 +1,30 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include <squish.h>
|
#include <string.h>
|
||||||
|
#include "squish.h"
|
||||||
#include "colourset.h"
|
#include "colourset.h"
|
||||||
#include "maths.h"
|
#include "maths.h"
|
||||||
#include "rangefit.h"
|
#include "rangefit.h"
|
||||||
@ -36,204 +37,359 @@ namespace squish {
|
|||||||
|
|
||||||
static int FixFlags( int flags )
|
static int FixFlags( int flags )
|
||||||
{
|
{
|
||||||
// grab the flag bits
|
// grab the flag bits
|
||||||
int method = flags & ( kDxt1 | kDxt3 | kDxt5 );
|
int method = flags & ( kDxt1 | kDxt3 | kDxt5 | kBc4 | kBc5 );
|
||||||
int fit = flags & ( kColourIterativeClusterFit | kColourClusterFit | kColourRangeFit );
|
int fit = flags & ( kColourIterativeClusterFit | kColourClusterFit | kColourRangeFit );
|
||||||
int metric = flags & ( kColourMetricPerceptual | kColourMetricUniform );
|
int extra = flags & kWeightColourByAlpha;
|
||||||
int extra = flags & kWeightColourByAlpha;
|
|
||||||
|
// set defaults
|
||||||
// set defaults
|
if ( method != kDxt3
|
||||||
if( method != kDxt3 && method != kDxt5 )
|
&& method != kDxt5
|
||||||
method = kDxt1;
|
&& method != kBc4
|
||||||
if( fit != kColourRangeFit )
|
&& method != kBc5 )
|
||||||
fit = kColourClusterFit;
|
{
|
||||||
if( metric != kColourMetricUniform )
|
method = kDxt1;
|
||||||
metric = kColourMetricPerceptual;
|
}
|
||||||
|
if( fit != kColourRangeFit && fit != kColourIterativeClusterFit )
|
||||||
// done
|
fit = kColourClusterFit;
|
||||||
return method | fit | metric | extra;
|
|
||||||
|
// done
|
||||||
|
return method | fit | extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compress( u8 const* rgba, void* block, int flags )
|
void CompressMasked( u8 const* rgba, int mask, void* block, int flags, float* metric )
|
||||||
{
|
{
|
||||||
// compress with full mask
|
// fix any bad flags
|
||||||
CompressMasked( rgba, 0xffff, block, flags );
|
flags = FixFlags( flags );
|
||||||
}
|
|
||||||
|
|
||||||
void CompressMasked( u8 const* rgba, int mask, void* block, int flags )
|
if ( ( flags & ( kBc4 | kBc5 ) ) != 0 )
|
||||||
{
|
{
|
||||||
// fix any bad flags
|
u8 alpha[16*4];
|
||||||
flags = FixFlags( flags );
|
for( int i = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
alpha[i*4 + 3] = rgba[i*4 + 0]; // copy R to A
|
||||||
|
}
|
||||||
|
|
||||||
// get the block locations
|
u8* rBlock = reinterpret_cast< u8* >( block );
|
||||||
void* colourBlock = block;
|
CompressAlphaDxt5( alpha, mask, rBlock );
|
||||||
void* alphaBock = block;
|
|
||||||
if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 )
|
|
||||||
colourBlock = reinterpret_cast< u8* >( block ) + 8;
|
|
||||||
|
|
||||||
// create the minimal point set
|
if ( ( flags & ( kBc5 ) ) != 0 )
|
||||||
ColourSet colours( rgba, mask, flags );
|
{
|
||||||
|
for( int i = 0; i < 16; ++i )
|
||||||
// check the compression type and compress colour
|
{
|
||||||
if( colours.GetCount() == 1 )
|
alpha[i*4 + 3] = rgba[i*4 + 1]; // copy G to A
|
||||||
{
|
}
|
||||||
// always do a single colour fit
|
|
||||||
SingleColourFit fit( &colours, flags );
|
u8* gBlock = reinterpret_cast< u8* >( block ) + 8;
|
||||||
fit.Compress( colourBlock );
|
CompressAlphaDxt5( alpha, mask, gBlock );
|
||||||
}
|
}
|
||||||
else if( ( flags & kColourRangeFit ) != 0 || colours.GetCount() == 0 )
|
|
||||||
{
|
return;
|
||||||
// do a range fit
|
}
|
||||||
RangeFit fit( &colours, flags );
|
|
||||||
fit.Compress( colourBlock );
|
// get the block locations
|
||||||
}
|
void* colourBlock = block;
|
||||||
else
|
void* alphaBlock = block;
|
||||||
{
|
if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 )
|
||||||
// default to a cluster fit (could be iterative or not)
|
colourBlock = reinterpret_cast< u8* >( block ) + 8;
|
||||||
ClusterFit fit( &colours, flags );
|
|
||||||
fit.Compress( colourBlock );
|
// create the minimal point set
|
||||||
}
|
ColourSet colours( rgba, mask, flags );
|
||||||
|
|
||||||
// compress alpha separately if necessary
|
// check the compression type and compress colour
|
||||||
if( ( flags & kDxt3 ) != 0 )
|
if( colours.GetCount() == 1 )
|
||||||
CompressAlphaDxt3( rgba, mask, alphaBock );
|
{
|
||||||
else if( ( flags & kDxt5 ) != 0 )
|
// always do a single colour fit
|
||||||
CompressAlphaDxt5( rgba, mask, alphaBock );
|
SingleColourFit fit( &colours, flags );
|
||||||
|
fit.Compress( colourBlock );
|
||||||
|
}
|
||||||
|
else if( ( flags & kColourRangeFit ) != 0 || colours.GetCount() == 0 )
|
||||||
|
{
|
||||||
|
// do a range fit
|
||||||
|
RangeFit fit( &colours, flags, metric );
|
||||||
|
fit.Compress( colourBlock );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// default to a cluster fit (could be iterative or not)
|
||||||
|
ClusterFit fit( &colours, flags, metric );
|
||||||
|
fit.Compress( colourBlock );
|
||||||
|
}
|
||||||
|
|
||||||
|
// compress alpha separately if necessary
|
||||||
|
if( ( flags & kDxt3 ) != 0 )
|
||||||
|
CompressAlphaDxt3( rgba, mask, alphaBlock );
|
||||||
|
else if( ( flags & kDxt5 ) != 0 )
|
||||||
|
CompressAlphaDxt5( rgba, mask, alphaBlock );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decompress( u8* rgba, void const* block, int flags )
|
void Decompress( u8* rgba, void const* block, int flags )
|
||||||
{
|
{
|
||||||
// fix any bad flags
|
// fix any bad flags
|
||||||
flags = FixFlags( flags );
|
flags = FixFlags( flags );
|
||||||
|
|
||||||
// get the block locations
|
// get the block locations
|
||||||
void const* colourBlock = block;
|
void const* colourBlock = block;
|
||||||
void const* alphaBock = block;
|
void const* alphaBlock = block;
|
||||||
if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 )
|
if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 )
|
||||||
colourBlock = reinterpret_cast< u8 const* >( block ) + 8;
|
colourBlock = reinterpret_cast< u8 const* >( block ) + 8;
|
||||||
|
|
||||||
// decompress colour
|
// decompress colour
|
||||||
DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
|
DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
|
||||||
|
|
||||||
// decompress alpha separately if necessary
|
// decompress alpha separately if necessary
|
||||||
if( ( flags & kDxt3 ) != 0 )
|
if( ( flags & kDxt3 ) != 0 )
|
||||||
DecompressAlphaDxt3( rgba, alphaBock );
|
DecompressAlphaDxt3( rgba, alphaBlock );
|
||||||
else if( ( flags & kDxt5 ) != 0 )
|
else if( ( flags & kDxt5 ) != 0 )
|
||||||
DecompressAlphaDxt5( rgba, alphaBock );
|
DecompressAlphaDxt5( rgba, alphaBlock );
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetStorageRequirements( int width, int height, int flags )
|
int GetStorageRequirements( int width, int height, int flags )
|
||||||
{
|
{
|
||||||
// fix any bad flags
|
// fix any bad flags
|
||||||
flags = FixFlags( flags );
|
flags = FixFlags( flags );
|
||||||
|
|
||||||
// compute the storage requirements
|
// compute the storage requirements
|
||||||
int blockcount = ( ( width + 3 )/4 ) * ( ( height + 3 )/4 );
|
int blockcount = ( ( width + 3 )/4 ) * ( ( height + 3 )/4 );
|
||||||
int blocksize = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
|
int blocksize = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16;
|
||||||
return blockcount*blocksize;
|
return blockcount*blocksize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags )
|
void CopyRGBA( u8 const* source, u8* dest, int flags )
|
||||||
{
|
{
|
||||||
// fix any bad flags
|
if (flags & kSourceBGRA)
|
||||||
flags = FixFlags( flags );
|
{
|
||||||
|
// convert from bgra to rgba
|
||||||
|
dest[0] = source[2];
|
||||||
|
dest[1] = source[1];
|
||||||
|
dest[2] = source[0];
|
||||||
|
dest[3] = source[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
*dest++ = *source++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// initialise the block output
|
void CompressImage( u8 const* rgba, int width, int height, int pitch, void* blocks, int flags, float* metric )
|
||||||
u8* targetBlock = reinterpret_cast< u8* >( blocks );
|
{
|
||||||
int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
|
// fix any bad flags
|
||||||
|
flags = FixFlags( flags );
|
||||||
|
|
||||||
// loop over blocks
|
// initialise the block output
|
||||||
for( int y = 0; y < height; y += 4 )
|
u8* targetBlock = reinterpret_cast< u8* >( blocks );
|
||||||
{
|
int bytesPerBlock = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16;
|
||||||
for( int x = 0; x < width; x += 4 )
|
|
||||||
{
|
// loop over blocks
|
||||||
// build the 4x4 block of pixels
|
for( int y = 0; y < height; y += 4 )
|
||||||
u8 sourceRgba[16*4];
|
{
|
||||||
u8* targetPixel = sourceRgba;
|
for( int x = 0; x < width; x += 4 )
|
||||||
int mask = 0;
|
{
|
||||||
for( int py = 0; py < 4; ++py )
|
// build the 4x4 block of pixels
|
||||||
{
|
u8 sourceRgba[16*4];
|
||||||
for( int px = 0; px < 4; ++px )
|
u8* targetPixel = sourceRgba;
|
||||||
{
|
int mask = 0;
|
||||||
// get the source pixel in the image
|
for( int py = 0; py < 4; ++py )
|
||||||
int sx = x + px;
|
{
|
||||||
int sy = y + py;
|
for( int px = 0; px < 4; ++px )
|
||||||
|
{
|
||||||
// enable if we're in the image
|
// get the source pixel in the image
|
||||||
if( sx < width && sy < height )
|
int sx = x + px;
|
||||||
{
|
int sy = y + py;
|
||||||
// copy the rgba value
|
|
||||||
u8 const* sourcePixel = rgba + 4*( width*sy + sx );
|
// enable if we're in the image
|
||||||
for( int i = 0; i < 4; ++i )
|
if( sx < width && sy < height )
|
||||||
*targetPixel++ = *sourcePixel++;
|
{
|
||||||
|
// copy the rgba value
|
||||||
// enable this pixel
|
u8 const* sourcePixel = rgba + pitch*sy + 4*sx;
|
||||||
mask |= ( 1 << ( 4*py + px ) );
|
CopyRGBA(sourcePixel, targetPixel, flags);
|
||||||
}
|
// enable this pixel
|
||||||
else
|
mask |= ( 1 << ( 4*py + px ) );
|
||||||
{
|
}
|
||||||
// skip this pixel as its outside the image
|
|
||||||
targetPixel += 4;
|
// advance to the next pixel
|
||||||
}
|
targetPixel += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compress it into the output
|
// compress it into the output
|
||||||
CompressMasked( sourceRgba, mask, targetBlock, flags );
|
CompressMasked( sourceRgba, mask, targetBlock, flags, metric );
|
||||||
|
|
||||||
// advance
|
// advance
|
||||||
targetBlock += bytesPerBlock;
|
targetBlock += bytesPerBlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags, float* metric )
|
||||||
|
{
|
||||||
|
CompressImage(rgba, width, height, width*4, blocks, flags, metric);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DecompressImage( u8* rgba, int width, int height, int pitch, void const* blocks, int flags )
|
||||||
|
{
|
||||||
|
// fix any bad flags
|
||||||
|
flags = FixFlags( flags );
|
||||||
|
|
||||||
|
// initialise the block input
|
||||||
|
u8 const* sourceBlock = reinterpret_cast< u8 const* >( blocks );
|
||||||
|
int bytesPerBlock = ( ( flags & ( kDxt1 | kBc4 ) ) != 0 ) ? 8 : 16;
|
||||||
|
|
||||||
|
// loop over blocks
|
||||||
|
for( int y = 0; y < height; y += 4 )
|
||||||
|
{
|
||||||
|
for( int x = 0; x < width; x += 4 )
|
||||||
|
{
|
||||||
|
// decompress the block
|
||||||
|
u8 targetRgba[4*16];
|
||||||
|
Decompress( targetRgba, sourceBlock, flags );
|
||||||
|
|
||||||
|
// write the decompressed pixels to the correct image locations
|
||||||
|
u8 const* sourcePixel = targetRgba;
|
||||||
|
for( int py = 0; py < 4; ++py )
|
||||||
|
{
|
||||||
|
for( int px = 0; px < 4; ++px )
|
||||||
|
{
|
||||||
|
// get the target location
|
||||||
|
int sx = x + px;
|
||||||
|
int sy = y + py;
|
||||||
|
|
||||||
|
// write if we're in the image
|
||||||
|
if( sx < width && sy < height )
|
||||||
|
{
|
||||||
|
// copy the rgba value
|
||||||
|
u8* targetPixel = rgba + pitch*sy + 4*sx;
|
||||||
|
CopyRGBA(sourcePixel, targetPixel, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance to the next pixel
|
||||||
|
sourcePixel += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance
|
||||||
|
sourceBlock += bytesPerBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags )
|
void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags )
|
||||||
{
|
{
|
||||||
// fix any bad flags
|
DecompressImage( rgba, width, height, width*4, blocks, flags );
|
||||||
flags = FixFlags( flags );
|
}
|
||||||
|
|
||||||
// initialise the block input
|
static double ErrorSq(double x, double y)
|
||||||
u8 const* sourceBlock = reinterpret_cast< u8 const* >( blocks );
|
{
|
||||||
int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
|
return (x - y) * (x - y);
|
||||||
|
}
|
||||||
|
|
||||||
// loop over blocks
|
static void ComputeBlockWMSE(u8 const *original, u8 const *compressed, unsigned int w, unsigned int h, double &cmse, double &amse)
|
||||||
for( int y = 0; y < height; y += 4 )
|
{
|
||||||
{
|
// Computes the MSE for the block and weights it by the variance of the original block.
|
||||||
for( int x = 0; x < width; x += 4 )
|
// If the variance of the original block is less than 4 (i.e. a standard deviation of 1 per channel)
|
||||||
{
|
// then the block is close to being a single colour. Quantisation errors in single colour blocks
|
||||||
// decompress the block
|
// are easier to see than similar errors in blocks that contain more colours, particularly when there
|
||||||
u8 targetRgba[4*16];
|
// are many such blocks in a large area (eg a blue sky background) as they cause banding. Given that
|
||||||
Decompress( targetRgba, sourceBlock, flags );
|
// banding is easier to see than small errors in "complex" blocks, we weight the errors by a factor
|
||||||
|
// of 5. This implies that images with large, single colour areas will have a higher potential WMSE
|
||||||
// write the decompressed pixels to the correct image locations
|
// than images with lots of detail.
|
||||||
u8 const* sourcePixel = targetRgba;
|
|
||||||
for( int py = 0; py < 4; ++py )
|
cmse = amse = 0;
|
||||||
{
|
unsigned int sum_p[4]; // per channel sum of pixels
|
||||||
for( int px = 0; px < 4; ++px )
|
unsigned int sum_p2[4]; // per channel sum of pixels squared
|
||||||
{
|
memset(sum_p, 0, sizeof(sum_p));
|
||||||
// get the target location
|
memset(sum_p2, 0, sizeof(sum_p2));
|
||||||
int sx = x + px;
|
for( unsigned int py = 0; py < 4; ++py )
|
||||||
int sy = y + py;
|
{
|
||||||
if( sx < width && sy < height )
|
for( unsigned int px = 0; px < 4; ++px )
|
||||||
{
|
{
|
||||||
u8* targetPixel = rgba + 4*( width*sy + sx );
|
if( px < w && py < h )
|
||||||
|
{
|
||||||
// copy the rgba value
|
double pixelCMSE = 0;
|
||||||
for( int i = 0; i < 4; ++i )
|
for( int i = 0; i < 3; ++i )
|
||||||
*targetPixel++ = *sourcePixel++;
|
{
|
||||||
}
|
pixelCMSE += ErrorSq(original[i], compressed[i]);
|
||||||
else
|
sum_p[i] += original[i];
|
||||||
{
|
sum_p2[i] += (unsigned int)original[i]*original[i];
|
||||||
// skip this pixel as its outside the image
|
}
|
||||||
sourcePixel += 4;
|
if( original[3] == 0 && compressed[3] == 0 )
|
||||||
}
|
pixelCMSE = 0; // transparent in both, so colour is inconsequential
|
||||||
}
|
amse += ErrorSq(original[3], compressed[3]);
|
||||||
}
|
cmse += pixelCMSE;
|
||||||
|
sum_p[3] += original[3];
|
||||||
// advance
|
sum_p2[3] += (unsigned int)original[3]*original[3];
|
||||||
sourceBlock += bytesPerBlock;
|
}
|
||||||
}
|
original += 4;
|
||||||
}
|
compressed += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsigned int variance = 0;
|
||||||
|
for( int i = 0; i < 4; ++i )
|
||||||
|
variance += w*h*sum_p2[i] - sum_p[i]*sum_p[i];
|
||||||
|
if( variance < 4 * w * w * h * h )
|
||||||
|
{
|
||||||
|
amse *= 5;
|
||||||
|
cmse *= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeMSE( u8 const *rgba, int width, int height, int pitch, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE )
|
||||||
|
{
|
||||||
|
// fix any bad flags
|
||||||
|
flags = FixFlags( flags );
|
||||||
|
colourMSE = alphaMSE = 0;
|
||||||
|
|
||||||
|
// initialise the block input
|
||||||
|
squish::u8 const* sourceBlock = dxt;
|
||||||
|
int bytesPerBlock = ( ( flags & squish::kDxt1 ) != 0 ) ? 8 : 16;
|
||||||
|
|
||||||
|
// loop over blocks
|
||||||
|
for( int y = 0; y < height; y += 4 )
|
||||||
|
{
|
||||||
|
for( int x = 0; x < width; x += 4 )
|
||||||
|
{
|
||||||
|
// decompress the block
|
||||||
|
u8 targetRgba[4*16];
|
||||||
|
Decompress( targetRgba, sourceBlock, flags );
|
||||||
|
u8 const* sourcePixel = targetRgba;
|
||||||
|
|
||||||
|
// copy across to a similar pixel block
|
||||||
|
u8 originalRgba[4*16];
|
||||||
|
u8* originalPixel = originalRgba;
|
||||||
|
|
||||||
|
for( int py = 0; py < 4; ++py )
|
||||||
|
{
|
||||||
|
for( int px = 0; px < 4; ++px )
|
||||||
|
{
|
||||||
|
int sx = x + px;
|
||||||
|
int sy = y + py;
|
||||||
|
if( sx < width && sy < height )
|
||||||
|
{
|
||||||
|
u8 const* targetPixel = rgba + pitch*sy + 4*sx;
|
||||||
|
CopyRGBA(targetPixel, originalPixel, flags);
|
||||||
|
}
|
||||||
|
sourcePixel += 4;
|
||||||
|
originalPixel += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the weighted MSE of the block
|
||||||
|
double blockCMSE, blockAMSE;
|
||||||
|
ComputeBlockWMSE(originalRgba, targetRgba, std::min(4, width - x), std::min(4, height - y), blockCMSE, blockAMSE);
|
||||||
|
colourMSE += blockCMSE;
|
||||||
|
alphaMSE += blockAMSE;
|
||||||
|
// advance
|
||||||
|
sourceBlock += bytesPerBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colourMSE /= (width * height * 3);
|
||||||
|
alphaMSE /= (width * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ComputeMSE( u8 const *rgba, int width, int height, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE )
|
||||||
|
{
|
||||||
|
ComputeMSE(rgba, width, height, width*4, dxt, flags, colourMSE, alphaMSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
407
thirdparty/squish/squish.h
vendored
407
thirdparty/squish/squish.h
vendored
@ -1,28 +1,28 @@
|
|||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
"Software"), to deal in the Software without restriction, including
|
"Software"), to deal in the Software without restriction, including
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
the following conditions:
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
The above copyright notice and this permission notice shall be included
|
||||||
in all copies or substantial portions of the Software.
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#ifndef SQUISH_H
|
#ifndef SQUISH_H
|
||||||
#define SQUISH_H
|
#define SQUISH_H
|
||||||
|
|
||||||
@ -38,124 +38,143 @@ typedef unsigned char u8;
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
//! Use DXT1 compression.
|
//! Use DXT1 compression.
|
||||||
kDxt1 = ( 1 << 0 ),
|
kDxt1 = ( 1 << 0 ),
|
||||||
|
|
||||||
//! Use DXT3 compression.
|
|
||||||
kDxt3 = ( 1 << 1 ),
|
|
||||||
|
|
||||||
//! Use DXT5 compression.
|
|
||||||
kDxt5 = ( 1 << 2 ),
|
|
||||||
|
|
||||||
//! Use a very slow but very high quality colour compressor.
|
|
||||||
kColourIterativeClusterFit = ( 1 << 8 ),
|
|
||||||
|
|
||||||
//! Use a slow but high quality colour compressor (the default).
|
|
||||||
kColourClusterFit = ( 1 << 3 ),
|
|
||||||
|
|
||||||
//! Use a fast but low quality colour compressor.
|
|
||||||
kColourRangeFit = ( 1 << 4 ),
|
|
||||||
|
|
||||||
//! Use a perceptual metric for colour error (the default).
|
|
||||||
kColourMetricPerceptual = ( 1 << 5 ),
|
|
||||||
|
|
||||||
//! Use a uniform metric for colour error.
|
//! Use DXT3 compression.
|
||||||
kColourMetricUniform = ( 1 << 6 ),
|
kDxt3 = ( 1 << 1 ),
|
||||||
|
|
||||||
//! Weight the colour by alpha during cluster fit (disabled by default).
|
//! Use DXT5 compression.
|
||||||
kWeightColourByAlpha = ( 1 << 7 )
|
kDxt5 = ( 1 << 2 ),
|
||||||
|
|
||||||
|
//! Use BC4 compression.
|
||||||
|
kBc4 = ( 1 << 3 ),
|
||||||
|
|
||||||
|
//! Use BC5 compression.
|
||||||
|
kBc5 = ( 1 << 4 ),
|
||||||
|
|
||||||
|
//! Use a slow but high quality colour compressor (the default).
|
||||||
|
kColourClusterFit = ( 1 << 5 ),
|
||||||
|
|
||||||
|
//! Use a fast but low quality colour compressor.
|
||||||
|
kColourRangeFit = ( 1 << 6 ),
|
||||||
|
|
||||||
|
//! Weight the colour by alpha during cluster fit (disabled by default).
|
||||||
|
kWeightColourByAlpha = ( 1 << 7 ),
|
||||||
|
|
||||||
|
//! Use a very slow but very high quality colour compressor.
|
||||||
|
kColourIterativeClusterFit = ( 1 << 8 ),
|
||||||
|
|
||||||
|
//! Source is BGRA rather than RGBA
|
||||||
|
kSourceBGRA = ( 1 << 9 )
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*! @brief Compresses a 4x4 block of pixels.
|
/*! @brief Compresses a 4x4 block of pixels.
|
||||||
|
|
||||||
@param rgba The rgba values of the 16 source pixels.
|
@param rgba The rgba values of the 16 source pixels.
|
||||||
@param block Storage for the compressed DXT block.
|
@param mask The valid pixel mask.
|
||||||
@param flags Compression flags.
|
@param block Storage for the compressed DXT block.
|
||||||
|
@param flags Compression flags.
|
||||||
The source pixels should be presented as a contiguous array of 16 rgba
|
@param metric An optional perceptual metric.
|
||||||
values, with each component as 1 byte each. In memory this should be:
|
|
||||||
|
The source pixels should be presented as a contiguous array of 16 rgba
|
||||||
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
values, with each component as 1 byte each. In memory this should be:
|
||||||
|
|
||||||
The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
|
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
||||||
however, DXT1 will be used by default if none is specified. When using DXT1
|
|
||||||
compression, 8 bytes of storage are required for the compressed DXT block.
|
The mask parameter enables only certain pixels within the block. The lowest
|
||||||
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
bit enables the first pixel and so on up to the 16th bit. Bits beyond the
|
||||||
|
16th bit are ignored. Pixels that are not enabled are allowed to take
|
||||||
The flags parameter can also specify a preferred colour compressor and
|
arbitrary colours in the output block. An example of how this can be used
|
||||||
colour error metric to use when fitting the RGB components of the data.
|
is in the CompressImage function to disable pixels outside the bounds of
|
||||||
Possible colour compressors are: kColourClusterFit (the default),
|
the image when the width or height is not divisible by 4.
|
||||||
kColourRangeFit or kColourIterativeClusterFit. Possible colour error metrics
|
|
||||||
are: kColourMetricPerceptual (the default) or kColourMetricUniform. If no
|
The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression,
|
||||||
flags are specified in any particular category then the default will be
|
however, DXT1 will be used by default if none is specified. When using DXT1
|
||||||
used. Unknown flags are ignored.
|
compression, 8 bytes of storage are required for the compressed DXT block.
|
||||||
|
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
||||||
When using kColourClusterFit, an additional flag can be specified to
|
|
||||||
weight the colour of each pixel by its alpha value. For images that are
|
The flags parameter can also specify a preferred colour compressor to use
|
||||||
rendered using alpha blending, this can significantly increase the
|
when fitting the RGB components of the data. Possible colour compressors
|
||||||
perceived quality.
|
are: kColourClusterFit (the default), kColourRangeFit (very fast, low
|
||||||
|
quality) or kColourIterativeClusterFit (slowest, best quality).
|
||||||
|
|
||||||
|
When using kColourClusterFit or kColourIterativeClusterFit, an additional
|
||||||
|
flag can be specified to weight the importance of each pixel by its alpha
|
||||||
|
value. For images that are rendered using alpha blending, this can
|
||||||
|
significantly increase the perceived quality.
|
||||||
|
|
||||||
|
The metric parameter can be used to weight the relative importance of each
|
||||||
|
colour channel, or pass NULL to use the default uniform weight of
|
||||||
|
{ 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that
|
||||||
|
allowed either uniform or "perceptual" weights with the fixed values
|
||||||
|
{ 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a
|
||||||
|
contiguous array of 3 floats.
|
||||||
*/
|
*/
|
||||||
void Compress( u8 const* rgba, void* block, int flags );
|
void CompressMasked( u8 const* rgba, int mask, void* block, int flags, float* metric = 0 );
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*! @brief Compresses a 4x4 block of pixels.
|
/*! @brief Compresses a 4x4 block of pixels.
|
||||||
|
|
||||||
@param rgba The rgba values of the 16 source pixels.
|
@param rgba The rgba values of the 16 source pixels.
|
||||||
@param mask The valid pixel mask.
|
@param block Storage for the compressed DXT block.
|
||||||
@param block Storage for the compressed DXT block.
|
@param flags Compression flags.
|
||||||
@param flags Compression flags.
|
@param metric An optional perceptual metric.
|
||||||
|
|
||||||
The source pixels should be presented as a contiguous array of 16 rgba
|
The source pixels should be presented as a contiguous array of 16 rgba
|
||||||
values, with each component as 1 byte each. In memory this should be:
|
values, with each component as 1 byte each. In memory this should be:
|
||||||
|
|
||||||
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
||||||
|
|
||||||
The mask parameter enables only certain pixels within the block. The lowest
|
The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression,
|
||||||
bit enables the first pixel and so on up to the 16th bit. Bits beyond the
|
however, DXT1 will be used by default if none is specified. When using DXT1
|
||||||
16th bit are ignored. Pixels that are not enabled are allowed to take
|
compression, 8 bytes of storage are required for the compressed DXT block.
|
||||||
arbitrary colours in the output block. An example of how this can be used
|
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
||||||
is in the CompressImage function to disable pixels outside the bounds of
|
|
||||||
the image when the width or height is not divisible by 4.
|
The flags parameter can also specify a preferred colour compressor to use
|
||||||
|
when fitting the RGB components of the data. Possible colour compressors
|
||||||
The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
|
are: kColourClusterFit (the default), kColourRangeFit (very fast, low
|
||||||
however, DXT1 will be used by default if none is specified. When using DXT1
|
quality) or kColourIterativeClusterFit (slowest, best quality).
|
||||||
compression, 8 bytes of storage are required for the compressed DXT block.
|
|
||||||
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
When using kColourClusterFit or kColourIterativeClusterFit, an additional
|
||||||
|
flag can be specified to weight the importance of each pixel by its alpha
|
||||||
The flags parameter can also specify a preferred colour compressor and
|
value. For images that are rendered using alpha blending, this can
|
||||||
colour error metric to use when fitting the RGB components of the data.
|
significantly increase the perceived quality.
|
||||||
Possible colour compressors are: kColourClusterFit (the default),
|
|
||||||
kColourRangeFit or kColourIterativeClusterFit. Possible colour error metrics
|
The metric parameter can be used to weight the relative importance of each
|
||||||
are: kColourMetricPerceptual (the default) or kColourMetricUniform. If no
|
colour channel, or pass NULL to use the default uniform weight of
|
||||||
flags are specified in any particular category then the default will be
|
{ 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that
|
||||||
used. Unknown flags are ignored.
|
allowed either uniform or "perceptual" weights with the fixed values
|
||||||
|
{ 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a
|
||||||
When using kColourClusterFit, an additional flag can be specified to
|
contiguous array of 3 floats.
|
||||||
weight the colour of each pixel by its alpha value. For images that are
|
|
||||||
rendered using alpha blending, this can significantly increase the
|
This method is an inline that calls CompressMasked with a mask of 0xffff,
|
||||||
perceived quality.
|
provided for compatibility with older versions of squish.
|
||||||
*/
|
*/
|
||||||
void CompressMasked( u8 const* rgba, int mask, void* block, int flags );
|
inline void Compress( u8 const* rgba, void* block, int flags, float* metric = 0 )
|
||||||
|
{
|
||||||
|
CompressMasked( rgba, 0xffff, block, flags, metric );
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*! @brief Decompresses a 4x4 block of pixels.
|
/*! @brief Decompresses a 4x4 block of pixels.
|
||||||
|
|
||||||
@param rgba Storage for the 16 decompressed pixels.
|
@param rgba Storage for the 16 decompressed pixels.
|
||||||
@param block The compressed DXT block.
|
@param block The compressed DXT block.
|
||||||
@param flags Compression flags.
|
@param flags Compression flags.
|
||||||
|
|
||||||
The decompressed pixels will be written as a contiguous array of 16 rgba
|
The decompressed pixels will be written as a contiguous array of 16 rgba
|
||||||
values, with each component as 1 byte each. In memory this is:
|
values, with each component as 1 byte each. In memory this is:
|
||||||
|
|
||||||
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
||||||
|
|
||||||
The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
|
The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression,
|
||||||
however, DXT1 will be used by default if none is specified. All other flags
|
however, DXT1 will be used by default if none is specified. All other flags
|
||||||
are ignored.
|
are ignored.
|
||||||
*/
|
*/
|
||||||
void Decompress( u8* rgba, void const* block, int flags );
|
void Decompress( u8* rgba, void const* block, int flags );
|
||||||
|
|
||||||
@ -163,17 +182,17 @@ void Decompress( u8* rgba, void const* block, int flags );
|
|||||||
|
|
||||||
/*! @brief Computes the amount of compressed storage required.
|
/*! @brief Computes the amount of compressed storage required.
|
||||||
|
|
||||||
@param width The width of the image.
|
@param width The width of the image.
|
||||||
@param height The height of the image.
|
@param height The height of the image.
|
||||||
@param flags Compression flags.
|
@param flags Compression flags.
|
||||||
|
|
||||||
The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
|
The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression,
|
||||||
however, DXT1 will be used by default if none is specified. All other flags
|
however, DXT1 will be used by default if none is specified. All other flags
|
||||||
are ignored.
|
are ignored.
|
||||||
|
|
||||||
Most DXT images will be a multiple of 4 in each dimension, but this
|
Most DXT images will be a multiple of 4 in each dimension, but this
|
||||||
function supports arbitrary size images by allowing the outer blocks to
|
function supports arbitrary size images by allowing the outer blocks to
|
||||||
be only partially used.
|
be only partially used.
|
||||||
*/
|
*/
|
||||||
int GetStorageRequirements( int width, int height, int flags );
|
int GetStorageRequirements( int width, int height, int flags );
|
||||||
|
|
||||||
@ -181,67 +200,101 @@ int GetStorageRequirements( int width, int height, int flags );
|
|||||||
|
|
||||||
/*! @brief Compresses an image in memory.
|
/*! @brief Compresses an image in memory.
|
||||||
|
|
||||||
@param rgba The pixels of the source.
|
@param rgba The pixels of the source.
|
||||||
@param width The width of the source image.
|
@param width The width of the source image.
|
||||||
@param height The height of the source image.
|
@param height The height of the source image.
|
||||||
@param blocks Storage for the compressed output.
|
@param pitch The pitch of the source image.
|
||||||
@param flags Compression flags.
|
@param blocks Storage for the compressed output.
|
||||||
|
@param flags Compression flags.
|
||||||
The source pixels should be presented as a contiguous array of width*height
|
@param metric An optional perceptual metric.
|
||||||
rgba values, with each component as 1 byte each. In memory this should be:
|
|
||||||
|
The source pixels should be presented as a contiguous array of width*height
|
||||||
{ r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height
|
rgba values, with each component as 1 byte each. In memory this should be:
|
||||||
|
|
||||||
The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
|
{ r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height
|
||||||
however, DXT1 will be used by default if none is specified. When using DXT1
|
|
||||||
compression, 8 bytes of storage are required for each compressed DXT block.
|
The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression,
|
||||||
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
however, DXT1 will be used by default if none is specified. When using DXT1
|
||||||
|
compression, 8 bytes of storage are required for each compressed DXT block.
|
||||||
The flags parameter can also specify a preferred colour compressor and
|
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
||||||
colour error metric to use when fitting the RGB components of the data.
|
|
||||||
Possible colour compressors are: kColourClusterFit (the default),
|
The flags parameter can also specify a preferred colour compressor to use
|
||||||
kColourRangeFit or kColourIterativeClusterFit. Possible colour error metrics
|
when fitting the RGB components of the data. Possible colour compressors
|
||||||
are: kColourMetricPerceptual (the default) or kColourMetricUniform. If no
|
are: kColourClusterFit (the default), kColourRangeFit (very fast, low
|
||||||
flags are specified in any particular category then the default will be
|
quality) or kColourIterativeClusterFit (slowest, best quality).
|
||||||
used. Unknown flags are ignored.
|
|
||||||
|
When using kColourClusterFit or kColourIterativeClusterFit, an additional
|
||||||
When using kColourClusterFit, an additional flag can be specified to
|
flag can be specified to weight the importance of each pixel by its alpha
|
||||||
weight the colour of each pixel by its alpha value. For images that are
|
value. For images that are rendered using alpha blending, this can
|
||||||
rendered using alpha blending, this can significantly increase the
|
significantly increase the perceived quality.
|
||||||
perceived quality.
|
|
||||||
|
The metric parameter can be used to weight the relative importance of each
|
||||||
Internally this function calls squish::Compress for each block. To see how
|
colour channel, or pass NULL to use the default uniform weight of
|
||||||
much memory is required in the compressed image, use
|
{ 1.0f, 1.0f, 1.0f }. This replaces the previous flag-based control that
|
||||||
squish::GetStorageRequirements.
|
allowed either uniform or "perceptual" weights with the fixed values
|
||||||
|
{ 0.2126f, 0.7152f, 0.0722f }. If non-NULL, the metric should point to a
|
||||||
|
contiguous array of 3 floats.
|
||||||
|
|
||||||
|
Internally this function calls squish::CompressMasked for each block, which
|
||||||
|
allows for pixels outside the image to take arbitrary values. The function
|
||||||
|
squish::GetStorageRequirements can be called to compute the amount of memory
|
||||||
|
to allocate for the compressed output.
|
||||||
*/
|
*/
|
||||||
void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags );
|
void CompressImage( u8 const* rgba, int width, int height, int pitch, void* blocks, int flags, float* metric = 0 );
|
||||||
|
void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags, float* metric = 0 );
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*! @brief Decompresses an image in memory.
|
/*! @brief Decompresses an image in memory.
|
||||||
|
|
||||||
@param rgba Storage for the decompressed pixels.
|
@param rgba Storage for the decompressed pixels.
|
||||||
@param width The width of the source image.
|
@param width The width of the source image.
|
||||||
@param height The height of the source image.
|
@param height The height of the source image.
|
||||||
@param blocks The compressed DXT blocks.
|
@param pitch The pitch of the decompressed pixels.
|
||||||
@param flags Compression flags.
|
@param blocks The compressed DXT blocks.
|
||||||
|
@param flags Compression flags.
|
||||||
The decompressed pixels will be written as a contiguous array of width*height
|
|
||||||
16 rgba values, with each component as 1 byte each. In memory this is:
|
|
||||||
|
|
||||||
{ r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height
|
|
||||||
|
|
||||||
The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
|
|
||||||
however, DXT1 will be used by default if none is specified. All other flags
|
|
||||||
are ignored.
|
|
||||||
|
|
||||||
Internally this function calls squish::Decompress for each block.
|
The decompressed pixels will be written as a contiguous array of width*height
|
||||||
|
16 rgba values, with each component as 1 byte each. In memory this is:
|
||||||
|
|
||||||
|
{ r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height
|
||||||
|
|
||||||
|
The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression,
|
||||||
|
however, DXT1 will be used by default if none is specified. All other flags
|
||||||
|
are ignored.
|
||||||
|
|
||||||
|
Internally this function calls squish::Decompress for each block.
|
||||||
*/
|
*/
|
||||||
|
void DecompressImage( u8* rgba, int width, int height, int pitch, void const* blocks, int flags );
|
||||||
void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags );
|
void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags );
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*! @brief Computes MSE of an compressed image in memory.
|
||||||
|
|
||||||
|
@param rgba The original image pixels.
|
||||||
|
@param width The width of the source image.
|
||||||
|
@param height The height of the source image.
|
||||||
|
@param pitch The pitch of the source image.
|
||||||
|
@param dxt The compressed dxt blocks
|
||||||
|
@param flags Compression flags.
|
||||||
|
@param colourMSE The MSE of the colour values.
|
||||||
|
@param alphaMSE The MSE of the alpha values.
|
||||||
|
|
||||||
|
The colour MSE and alpha MSE are computed across all pixels. The colour MSE is
|
||||||
|
averaged across all rgb values (i.e. colourMSE = sum sum_k ||dxt.k - rgba.k||/3)
|
||||||
|
|
||||||
|
The flags parameter should specify kDxt1, kDxt3, kDxt5, kBc4, or kBc5 compression,
|
||||||
|
however, DXT1 will be used by default if none is specified. All other flags
|
||||||
|
are ignored.
|
||||||
|
|
||||||
|
Internally this function calls squish::Decompress for each block.
|
||||||
|
*/
|
||||||
|
void ComputeMSE(u8 const *rgba, int width, int height, int pitch, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE);
|
||||||
|
void ComputeMSE(u8 const *rgba, int width, int height, u8 const *dxt, int flags, double &colourMSE, double &alphaMSE);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
} // namespace squish
|
} // namespace squish
|
||||||
|
|
||||||
#endif // ndef SQUISH_H
|
#endif // ndef SQUISH_H
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user