forked from sascha/godot
squish: Update to upstream 1.14
Sources are untouched, tarball from https://sourceforge.net/projects/libsquish
(cherry picked from commit 249836e530)
2.1
parent
1022705707
commit
8263fca121
@ -1,214 +1,214 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "colourblock.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
static int FloatToInt( float a, int limit )
|
||||
{
|
||||
// use ANSI round-to-zero behaviour to get round-to-nearest
|
||||
int i = ( int )( a + 0.5f );
|
||||
// use ANSI round-to-zero behaviour to get round-to-nearest
|
||||
int i = ( int )( a + 0.5f );
|
||||
|
||||
// clamp to the limit
|
||||
if( i < 0 )
|
||||
i = 0;
|
||||
else if( i > limit )
|
||||
i = limit;
|
||||
// clamp to the limit
|
||||
if( i < 0 )
|
||||
i = 0;
|
||||
else if( i > limit )
|
||||
i = limit;
|
||||
|
||||
// done
|
||||
return i;
|
||||
// done
|
||||
return i;
|
||||
}
|
||||
|
||||
static int FloatTo565( Vec3::Arg colour )
|
||||
{
|
||||
// get the components in the correct range
|
||||
int r = FloatToInt( 31.0f*colour.X(), 31 );
|
||||
int g = FloatToInt( 63.0f*colour.Y(), 63 );
|
||||
int b = FloatToInt( 31.0f*colour.Z(), 31 );
|
||||
|
||||
// pack into a single value
|
||||
return ( r << 11 ) | ( g << 5 ) | b;
|
||||
// get the components in the correct range
|
||||
int r = FloatToInt( 31.0f*colour.X(), 31 );
|
||||
int g = FloatToInt( 63.0f*colour.Y(), 63 );
|
||||
int b = FloatToInt( 31.0f*colour.Z(), 31 );
|
||||
|
||||
// pack into a single value
|
||||
return ( r << 11 ) | ( g << 5 ) | b;
|
||||
}
|
||||
|
||||
static void WriteColourBlock( int a, int b, u8* indices, void* block )
|
||||
{
|
||||
// get the block as bytes
|
||||
u8* bytes = ( u8* )block;
|
||||
|
||||
// write the endpoints
|
||||
bytes[0] = ( u8 )( a & 0xff );
|
||||
bytes[1] = ( u8 )( a >> 8 );
|
||||
bytes[2] = ( u8 )( b & 0xff );
|
||||
bytes[3] = ( u8 )( b >> 8 );
|
||||
|
||||
// write the indices
|
||||
for( int i = 0; i < 4; ++i )
|
||||
{
|
||||
u8 const* ind = indices + 4*i;
|
||||
bytes[4 + i] = ind[0] | ( ind[1] << 2 ) | ( ind[2] << 4 ) | ( ind[3] << 6 );
|
||||
}
|
||||
// get the block as bytes
|
||||
u8* bytes = ( u8* )block;
|
||||
|
||||
// write the endpoints
|
||||
bytes[0] = ( u8 )( a & 0xff );
|
||||
bytes[1] = ( u8 )( a >> 8 );
|
||||
bytes[2] = ( u8 )( b & 0xff );
|
||||
bytes[3] = ( u8 )( b >> 8 );
|
||||
|
||||
// write the indices
|
||||
for( int i = 0; i < 4; ++i )
|
||||
{
|
||||
u8 const* ind = indices + 4*i;
|
||||
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 )
|
||||
{
|
||||
// get the packed values
|
||||
int a = FloatTo565( start );
|
||||
int b = FloatTo565( end );
|
||||
|
||||
// remap the indices
|
||||
u8 remapped[16];
|
||||
if( a <= b )
|
||||
{
|
||||
// use the indices directly
|
||||
for( int i = 0; i < 16; ++i )
|
||||
remapped[i] = indices[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// swap a and b
|
||||
std::swap( a, b );
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
if( indices[i] == 0 )
|
||||
remapped[i] = 1;
|
||||
else if( indices[i] == 1 )
|
||||
remapped[i] = 0;
|
||||
else
|
||||
remapped[i] = indices[i];
|
||||
}
|
||||
}
|
||||
|
||||
// write the block
|
||||
WriteColourBlock( a, b, remapped, block );
|
||||
// get the packed values
|
||||
int a = FloatTo565( start );
|
||||
int b = FloatTo565( end );
|
||||
|
||||
// remap the indices
|
||||
u8 remapped[16];
|
||||
if( a <= b )
|
||||
{
|
||||
// use the indices directly
|
||||
for( int i = 0; i < 16; ++i )
|
||||
remapped[i] = indices[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// swap a and b
|
||||
std::swap( a, b );
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
if( indices[i] == 0 )
|
||||
remapped[i] = 1;
|
||||
else if( indices[i] == 1 )
|
||||
remapped[i] = 0;
|
||||
else
|
||||
remapped[i] = indices[i];
|
||||
}
|
||||
}
|
||||
|
||||
// write the block
|
||||
WriteColourBlock( a, b, remapped, block );
|
||||
}
|
||||
|
||||
void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block )
|
||||
{
|
||||
// get the packed values
|
||||
int a = FloatTo565( start );
|
||||
int b = FloatTo565( end );
|
||||
|
||||
// remap the indices
|
||||
u8 remapped[16];
|
||||
if( a < b )
|
||||
{
|
||||
// swap a and b
|
||||
std::swap( a, b );
|
||||
for( int i = 0; i < 16; ++i )
|
||||
remapped[i] = ( indices[i] ^ 0x1 ) & 0x3;
|
||||
}
|
||||
else if( a == b )
|
||||
{
|
||||
// use index 0
|
||||
for( int i = 0; i < 16; ++i )
|
||||
remapped[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// use the indices directly
|
||||
for( int i = 0; i < 16; ++i )
|
||||
remapped[i] = indices[i];
|
||||
}
|
||||
|
||||
// write the block
|
||||
WriteColourBlock( a, b, remapped, block );
|
||||
// get the packed values
|
||||
int a = FloatTo565( start );
|
||||
int b = FloatTo565( end );
|
||||
|
||||
// remap the indices
|
||||
u8 remapped[16];
|
||||
if( a < b )
|
||||
{
|
||||
// swap a and b
|
||||
std::swap( a, b );
|
||||
for( int i = 0; i < 16; ++i )
|
||||
remapped[i] = ( indices[i] ^ 0x1 ) & 0x3;
|
||||
}
|
||||
else if( a == b )
|
||||
{
|
||||
// use index 0
|
||||
for( int i = 0; i < 16; ++i )
|
||||
remapped[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// use the indices directly
|
||||
for( int i = 0; i < 16; ++i )
|
||||
remapped[i] = indices[i];
|
||||
}
|
||||
|
||||
// write the block
|
||||
WriteColourBlock( a, b, remapped, block );
|
||||
}
|
||||
|
||||
static int Unpack565( u8 const* packed, u8* colour )
|
||||
{
|
||||
// build the packed value
|
||||
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
|
||||
colour[0] = ( red << 3 ) | ( red >> 2 );
|
||||
colour[1] = ( green << 2 ) | ( green >> 4 );
|
||||
colour[2] = ( blue << 3 ) | ( blue >> 2 );
|
||||
colour[3] = 255;
|
||||
|
||||
// return the value
|
||||
return value;
|
||||
// build the packed value
|
||||
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
|
||||
colour[0] = ( red << 3 ) | ( red >> 2 );
|
||||
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 )
|
||||
{
|
||||
// get the block bytes
|
||||
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 )
|
||||
{
|
||||
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];
|
||||
}
|
||||
// get the block bytes
|
||||
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 )
|
||||
{
|
||||
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
|
||||
|
||||
@ -1,50 +1,54 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "colourfit.h"
|
||||
#include "colourset.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
ColourFit::ColourFit( ColourSet const* colours, int flags )
|
||||
: m_colours( colours ),
|
||||
m_flags( flags )
|
||||
ColourFit::ColourFit( ColourSet const* colours, int flags )
|
||||
: m_colours( colours ),
|
||||
m_flags( flags )
|
||||
{
|
||||
}
|
||||
|
||||
ColourFit::~ColourFit()
|
||||
{
|
||||
}
|
||||
|
||||
void ColourFit::Compress( void* block )
|
||||
{
|
||||
bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 );
|
||||
if( isDxt1 )
|
||||
{
|
||||
Compress3( block );
|
||||
if( !m_colours->IsTransparent() )
|
||||
Compress4( block );
|
||||
}
|
||||
else
|
||||
Compress4( block );
|
||||
bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 );
|
||||
if( isDxt1 )
|
||||
{
|
||||
Compress3( block );
|
||||
if( !m_colours->IsTransparent() )
|
||||
Compress4( block );
|
||||
}
|
||||
else
|
||||
Compress4( block );
|
||||
}
|
||||
|
||||
} // namespace squish
|
||||
|
||||
@ -1,121 +1,121 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "colourset.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
ColourSet::ColourSet( u8 const* rgba, int mask, int flags )
|
||||
: m_count( 0 ),
|
||||
m_transparent( false )
|
||||
: m_count( 0 ),
|
||||
m_transparent( false )
|
||||
{
|
||||
// check the compression mode for dxt1
|
||||
bool isDxt1 = ( ( flags & kDxt1 ) != 0 );
|
||||
bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 );
|
||||
|
||||
// create the minimal set
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
// check this pixel is enabled
|
||||
int bit = 1 << i;
|
||||
if( ( mask & bit ) == 0 )
|
||||
{
|
||||
m_remap[i] = -1;
|
||||
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
|
||||
for( int j = 0;; ++j )
|
||||
{
|
||||
// allocate a new point
|
||||
if( j == i )
|
||||
{
|
||||
// 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
|
||||
m_points[m_count] = Vec3( x, y, z );
|
||||
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] );
|
||||
// check the compression mode for dxt1
|
||||
bool isDxt1 = ( ( flags & kDxt1 ) != 0 );
|
||||
bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 );
|
||||
|
||||
// create the minimal set
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
// check this pixel is enabled
|
||||
int bit = 1 << i;
|
||||
if( ( mask & bit ) == 0 )
|
||||
{
|
||||
m_remap[i] = -1;
|
||||
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
|
||||
for( int j = 0;; ++j )
|
||||
{
|
||||
// allocate a new point
|
||||
if( j == i )
|
||||
{
|
||||
// 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
|
||||
m_points[m_count] = Vec3( x, y, z );
|
||||
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
|
||||
{
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
int j = m_remap[i];
|
||||
if( j == -1 )
|
||||
target[i] = 3;
|
||||
else
|
||||
target[i] = source[j];
|
||||
}
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
int j = m_remap[i];
|
||||
if( j == -1 )
|
||||
target[i] = 3;
|
||||
else
|
||||
target[i] = source[j];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace squish
|
||||
|
||||
@ -1,227 +1,259 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/*! @file
|
||||
|
||||
The symmetric eigensystem solver algorithm is from
|
||||
http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf
|
||||
The symmetric eigensystem solver algorithm is from
|
||||
http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf
|
||||
*/
|
||||
|
||||
#include "maths.h"
|
||||
#include "simd.h"
|
||||
#include <cfloat>
|
||||
|
||||
namespace squish {
|
||||
|
||||
Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights )
|
||||
{
|
||||
// compute the centroid
|
||||
float total = 0.0f;
|
||||
Vec3 centroid( 0.0f );
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
total += weights[i];
|
||||
centroid += weights[i]*points[i];
|
||||
}
|
||||
centroid /= total;
|
||||
|
||||
// accumulate the covariance matrix
|
||||
Sym3x3 covariance( 0.0f );
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
Vec3 a = points[i] - centroid;
|
||||
Vec3 b = weights[i]*a;
|
||||
|
||||
covariance[0] += a.X()*b.X();
|
||||
covariance[1] += a.X()*b.Y();
|
||||
covariance[2] += a.X()*b.Z();
|
||||
covariance[3] += a.Y()*b.Y();
|
||||
covariance[4] += a.Y()*b.Z();
|
||||
covariance[5] += a.Z()*b.Z();
|
||||
}
|
||||
|
||||
// return it
|
||||
return covariance;
|
||||
// compute the centroid
|
||||
float total = 0.0f;
|
||||
Vec3 centroid( 0.0f );
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
total += weights[i];
|
||||
centroid += weights[i]*points[i];
|
||||
}
|
||||
if( total > FLT_EPSILON )
|
||||
centroid /= total;
|
||||
|
||||
// accumulate the covariance matrix
|
||||
Sym3x3 covariance( 0.0f );
|
||||
for( int i = 0; i < n; ++i )
|
||||
{
|
||||
Vec3 a = points[i] - centroid;
|
||||
Vec3 b = weights[i]*a;
|
||||
|
||||
covariance[0] += a.X()*b.X();
|
||||
covariance[1] += a.X()*b.Y();
|
||||
covariance[2] += a.X()*b.Z();
|
||||
covariance[3] += a.Y()*b.Y();
|
||||
covariance[4] += a.Y()*b.Z();
|
||||
covariance[5] += a.Z()*b.Z();
|
||||
}
|
||||
|
||||
// return it
|
||||
return covariance;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static Vec3 GetMultiplicity1Evector( Sym3x3 const& matrix, float evalue )
|
||||
{
|
||||
// compute M
|
||||
Sym3x3 m;
|
||||
m[0] = matrix[0] - evalue;
|
||||
m[1] = matrix[1];
|
||||
m[2] = matrix[2];
|
||||
m[3] = matrix[3] - evalue;
|
||||
m[4] = matrix[4];
|
||||
m[5] = matrix[5] - evalue;
|
||||
|
||||
// compute U
|
||||
Sym3x3 u;
|
||||
u[0] = m[3]*m[5] - m[4]*m[4];
|
||||
u[1] = m[2]*m[4] - m[1]*m[5];
|
||||
u[2] = m[1]*m[4] - m[2]*m[3];
|
||||
u[3] = m[0]*m[5] - m[2]*m[2];
|
||||
u[4] = m[1]*m[2] - m[4]*m[0];
|
||||
u[5] = m[0]*m[3] - m[1]*m[1];
|
||||
|
||||
// find the largest component
|
||||
float mc = std::fabs( u[0] );
|
||||
int mi = 0;
|
||||
for( int i = 1; i < 6; ++i )
|
||||
{
|
||||
float c = std::fabs( u[i] );
|
||||
if( c > mc )
|
||||
{
|
||||
mc = c;
|
||||
mi = i;
|
||||
}
|
||||
}
|
||||
|
||||
// pick the column with this component
|
||||
switch( mi )
|
||||
{
|
||||
case 0:
|
||||
return Vec3( u[0], u[1], u[2] );
|
||||
|
||||
case 1:
|
||||
case 3:
|
||||
return Vec3( u[1], u[3], u[4] );
|
||||
|
||||
default:
|
||||
return Vec3( u[2], u[4], u[5] );
|
||||
}
|
||||
// compute M
|
||||
Sym3x3 m;
|
||||
m[0] = matrix[0] - evalue;
|
||||
m[1] = matrix[1];
|
||||
m[2] = matrix[2];
|
||||
m[3] = matrix[3] - evalue;
|
||||
m[4] = matrix[4];
|
||||
m[5] = matrix[5] - evalue;
|
||||
|
||||
// compute U
|
||||
Sym3x3 u;
|
||||
u[0] = m[3]*m[5] - m[4]*m[4];
|
||||
u[1] = m[2]*m[4] - m[1]*m[5];
|
||||
u[2] = m[1]*m[4] - m[2]*m[3];
|
||||
u[3] = m[0]*m[5] - m[2]*m[2];
|
||||
u[4] = m[1]*m[2] - m[4]*m[0];
|
||||
u[5] = m[0]*m[3] - m[1]*m[1];
|
||||
|
||||
// find the largest component
|
||||
float mc = std::fabs( u[0] );
|
||||
int mi = 0;
|
||||
for( int i = 1; i < 6; ++i )
|
||||
{
|
||||
float c = std::fabs( u[i] );
|
||||
if( c > mc )
|
||||
{
|
||||
mc = c;
|
||||
mi = i;
|
||||
}
|
||||
}
|
||||
|
||||
// pick the column with this component
|
||||
switch( mi )
|
||||
{
|
||||
case 0:
|
||||
return Vec3( u[0], u[1], u[2] );
|
||||
|
||||
case 1:
|
||||
case 3:
|
||||
return Vec3( u[1], u[3], u[4] );
|
||||
|
||||
default:
|
||||
return Vec3( u[2], u[4], u[5] );
|
||||
}
|
||||
}
|
||||
|
||||
static Vec3 GetMultiplicity2Evector( Sym3x3 const& matrix, float evalue )
|
||||
{
|
||||
// compute M
|
||||
Sym3x3 m;
|
||||
m[0] = matrix[0] - evalue;
|
||||
m[1] = matrix[1];
|
||||
m[2] = matrix[2];
|
||||
m[3] = matrix[3] - evalue;
|
||||
m[4] = matrix[4];
|
||||
m[5] = matrix[5] - evalue;
|
||||
|
||||
// find the largest component
|
||||
float mc = std::fabs( m[0] );
|
||||
int mi = 0;
|
||||
for( int i = 1; i < 6; ++i )
|
||||
{
|
||||
float c = std::fabs( m[i] );
|
||||
if( c > mc )
|
||||
{
|
||||
mc = c;
|
||||
mi = i;
|
||||
}
|
||||
}
|
||||
|
||||
// pick the first eigenvector based on this index
|
||||
switch( mi )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
return Vec3( -m[1], m[0], 0.0f );
|
||||
|
||||
case 2:
|
||||
return Vec3( m[2], 0.0f, -m[0] );
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
return Vec3( 0.0f, -m[4], m[3] );
|
||||
|
||||
default:
|
||||
return Vec3( 0.0f, -m[5], m[4] );
|
||||
}
|
||||
// compute M
|
||||
Sym3x3 m;
|
||||
m[0] = matrix[0] - evalue;
|
||||
m[1] = matrix[1];
|
||||
m[2] = matrix[2];
|
||||
m[3] = matrix[3] - evalue;
|
||||
m[4] = matrix[4];
|
||||
m[5] = matrix[5] - evalue;
|
||||
|
||||
// find the largest component
|
||||
float mc = std::fabs( m[0] );
|
||||
int mi = 0;
|
||||
for( int i = 1; i < 6; ++i )
|
||||
{
|
||||
float c = std::fabs( m[i] );
|
||||
if( c > mc )
|
||||
{
|
||||
mc = c;
|
||||
mi = i;
|
||||
}
|
||||
}
|
||||
|
||||
// pick the first eigenvector based on this index
|
||||
switch( mi )
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
return Vec3( -m[1], m[0], 0.0f );
|
||||
|
||||
case 2:
|
||||
return Vec3( m[2], 0.0f, -m[0] );
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
return Vec3( 0.0f, -m[4], m[3] );
|
||||
|
||||
default:
|
||||
return Vec3( 0.0f, -m[5], m[4] );
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 ComputePrincipleComponent( Sym3x3 const& matrix )
|
||||
{
|
||||
// compute the cubic coefficients
|
||||
float c0 = matrix[0]*matrix[3]*matrix[5]
|
||||
+ 2.0f*matrix[1]*matrix[2]*matrix[4]
|
||||
- matrix[0]*matrix[4]*matrix[4]
|
||||
- matrix[3]*matrix[2]*matrix[2]
|
||||
- matrix[5]*matrix[1]*matrix[1];
|
||||
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];
|
||||
float c2 = matrix[0] + matrix[3] + matrix[5];
|
||||
|
||||
// compute the quadratic coefficients
|
||||
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;
|
||||
|
||||
// compute the root count check
|
||||
float Q = 0.25f*b*b + ( 1.0f/27.0f )*a*a*a;
|
||||
|
||||
// test the multiplicity
|
||||
if( FLT_EPSILON < Q )
|
||||
{
|
||||
// only one root, which implies we have a multiple of the identity
|
||||
// compute the cubic coefficients
|
||||
float c0 = matrix[0]*matrix[3]*matrix[5]
|
||||
+ 2.0f*matrix[1]*matrix[2]*matrix[4]
|
||||
- matrix[0]*matrix[4]*matrix[4]
|
||||
- matrix[3]*matrix[2]*matrix[2]
|
||||
- matrix[5]*matrix[1]*matrix[1];
|
||||
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];
|
||||
float c2 = matrix[0] + matrix[3] + matrix[5];
|
||||
|
||||
// compute the quadratic coefficients
|
||||
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;
|
||||
|
||||
// compute the root count check
|
||||
float Q = 0.25f*b*b + ( 1.0f/27.0f )*a*a*a;
|
||||
|
||||
// test the multiplicity
|
||||
if( FLT_EPSILON < Q )
|
||||
{
|
||||
// only one root, which implies we have a multiple of the identity
|
||||
return Vec3( 1.0f );
|
||||
}
|
||||
else if( Q < -FLT_EPSILON )
|
||||
{
|
||||
// three distinct roots
|
||||
float theta = std::atan2( std::sqrt( -Q ), -0.5f*b );
|
||||
float rho = std::sqrt( 0.25f*b*b - Q );
|
||||
|
||||
float rt = std::pow( rho, 1.0f/3.0f );
|
||||
float ct = std::cos( theta/3.0f );
|
||||
float st = std::sin( theta/3.0f );
|
||||
|
||||
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 l3 = ( 1.0f/3.0f )*c2 - rt*( ct - ( float )sqrt( 3.0f )*st );
|
||||
|
||||
// pick the larger
|
||||
if( std::fabs( l2 ) > std::fabs( l1 ) )
|
||||
l1 = l2;
|
||||
if( std::fabs( l3 ) > std::fabs( l1 ) )
|
||||
l1 = l3;
|
||||
|
||||
// get the eigenvector
|
||||
return GetMultiplicity1Evector( matrix, l1 );
|
||||
}
|
||||
else // if( -FLT_EPSILON <= Q && Q <= FLT_EPSILON )
|
||||
{
|
||||
// two roots
|
||||
float rt;
|
||||
if( b < 0.0f )
|
||||
rt = -std::pow( -0.5f*b, 1.0f/3.0f );
|
||||
else
|
||||
rt = std::pow( 0.5f*b, 1.0f/3.0f );
|
||||
|
||||
float l1 = ( 1.0f/3.0f )*c2 + rt; // repeated
|
||||
float l2 = ( 1.0f/3.0f )*c2 - 2.0f*rt;
|
||||
|
||||
// get the eigenvector
|
||||
if( std::fabs( l1 ) > std::fabs( l2 ) )
|
||||
return GetMultiplicity2Evector( matrix, l1 );
|
||||
else
|
||||
return GetMultiplicity1Evector( matrix, l2 );
|
||||
}
|
||||
}
|
||||
else if( Q < -FLT_EPSILON )
|
||||
{
|
||||
// three distinct roots
|
||||
float theta = std::atan2( std::sqrt( -Q ), -0.5f*b );
|
||||
float rho = std::sqrt( 0.25f*b*b - Q );
|
||||
|
||||
float rt = std::pow( rho, 1.0f/3.0f );
|
||||
float ct = std::cos( theta/3.0f );
|
||||
float st = std::sin( theta/3.0f );
|
||||
|
||||
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 l3 = ( 1.0f/3.0f )*c2 - rt*( ct - ( float )sqrt( 3.0f )*st );
|
||||
|
||||
// pick the larger
|
||||
if( std::fabs( l2 ) > std::fabs( l1 ) )
|
||||
l1 = l2;
|
||||
if( std::fabs( l3 ) > std::fabs( l1 ) )
|
||||
l1 = l3;
|
||||
|
||||
// get the eigenvector
|
||||
return GetMultiplicity1Evector( matrix, l1 );
|
||||
}
|
||||
else // if( -FLT_EPSILON <= Q && Q <= FLT_EPSILON )
|
||||
{
|
||||
// two roots
|
||||
float rt;
|
||||
if( b < 0.0f )
|
||||
rt = -std::pow( -0.5f*b, 1.0f/3.0f );
|
||||
else
|
||||
rt = std::pow( 0.5f*b, 1.0f/3.0f );
|
||||
|
||||
float l1 = ( 1.0f/3.0f )*c2 + rt; // repeated
|
||||
float l2 = ( 1.0f/3.0f )*c2 - 2.0f*rt;
|
||||
|
||||
// get the eigenvector
|
||||
if( std::fabs( l1 ) > std::fabs( l2 ) )
|
||||
return GetMultiplicity2Evector( matrix, l1 );
|
||||
else
|
||||
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
|
||||
|
||||
@ -1,173 +1,172 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "singlecolourfit.h"
|
||||
#include "colourset.h"
|
||||
#include "colourblock.h"
|
||||
#include <climits>
|
||||
|
||||
namespace squish {
|
||||
|
||||
struct SourceBlock
|
||||
{
|
||||
u8 start;
|
||||
u8 end;
|
||||
u8 error;
|
||||
u8 start;
|
||||
u8 end;
|
||||
u8 error;
|
||||
};
|
||||
|
||||
struct SingleColourLookup
|
||||
{
|
||||
SourceBlock sources[2];
|
||||
SourceBlock sources[2];
|
||||
};
|
||||
|
||||
#include "singlecolourlookup.inl"
|
||||
|
||||
static int FloatToInt( float a, int limit )
|
||||
{
|
||||
// use ANSI round-to-zero behaviour to get round-to-nearest
|
||||
int i = ( int )( a + 0.5f );
|
||||
// use ANSI round-to-zero behaviour to get round-to-nearest
|
||||
int i = ( int )( a + 0.5f );
|
||||
|
||||
// clamp to the limit
|
||||
if( i < 0 )
|
||||
i = 0;
|
||||
else if( i > limit )
|
||||
i = limit;
|
||||
// clamp to the limit
|
||||
if( i < 0 )
|
||||
i = 0;
|
||||
else if( i > limit )
|
||||
i = limit;
|
||||
|
||||
// done
|
||||
return i;
|
||||
// done
|
||||
return i;
|
||||
}
|
||||
|
||||
SingleColourFit::SingleColourFit( ColourSet const* colours, int flags )
|
||||
: ColourFit( colours, flags )
|
||||
{
|
||||
// grab the single colour
|
||||
Vec3 const* values = m_colours->GetPoints();
|
||||
m_colour[0] = ( u8 )FloatToInt( 255.0f*values->X(), 255 );
|
||||
m_colour[1] = ( u8 )FloatToInt( 255.0f*values->Y(), 255 );
|
||||
m_colour[2] = ( u8 )FloatToInt( 255.0f*values->Z(), 255 );
|
||||
|
||||
// initialise the best error
|
||||
m_besterror = INT_MAX;
|
||||
// grab the single colour
|
||||
Vec3 const* values = m_colours->GetPoints();
|
||||
m_colour[0] = ( u8 )FloatToInt( 255.0f*values->X(), 255 );
|
||||
m_colour[1] = ( u8 )FloatToInt( 255.0f*values->Y(), 255 );
|
||||
m_colour[2] = ( u8 )FloatToInt( 255.0f*values->Z(), 255 );
|
||||
|
||||
// initialise the best error
|
||||
m_besterror = INT_MAX;
|
||||
}
|
||||
|
||||
void SingleColourFit::Compress3( void* block )
|
||||
{
|
||||
// build the table of lookups
|
||||
SingleColourLookup const* const lookups[] =
|
||||
{
|
||||
lookup_5_3,
|
||||
lookup_6_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
|
||||
m_besterror = m_error;
|
||||
}
|
||||
// build the table of lookups
|
||||
SingleColourLookup const* const lookups[] =
|
||||
{
|
||||
lookup_5_3,
|
||||
lookup_6_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
|
||||
m_besterror = m_error;
|
||||
}
|
||||
}
|
||||
|
||||
void SingleColourFit::Compress4( void* block )
|
||||
{
|
||||
// build the table of lookups
|
||||
SingleColourLookup const* const lookups[] =
|
||||
{
|
||||
lookup_5_4,
|
||||
lookup_6_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
|
||||
m_besterror = m_error;
|
||||
}
|
||||
// build the table of lookups
|
||||
SingleColourLookup const* const lookups[] =
|
||||
{
|
||||
lookup_5_4,
|
||||
lookup_6_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
|
||||
m_besterror = m_error;
|
||||
}
|
||||
}
|
||||
|
||||
void SingleColourFit::ComputeEndPoints( SingleColourLookup const* const* lookups )
|
||||
{
|
||||
// check each index combination (endpoint or intermediate)
|
||||
m_error = INT_MAX;
|
||||
for( int index = 0; index < 2; ++index )
|
||||
{
|
||||
// check the error for this codebook index
|
||||
SourceBlock const* sources[3];
|
||||
int error = 0;
|
||||
for( int channel = 0; channel < 3; ++channel )
|
||||
{
|
||||
// grab the lookup table and index for this channel
|
||||
SingleColourLookup const* lookup = lookups[channel];
|
||||
int target = m_colour[channel];
|
||||
|
||||
// store a pointer to the source for this channel
|
||||
sources[channel] = lookup[target].sources + index;
|
||||
|
||||
// accumulate the error
|
||||
int diff = sources[channel]->error;
|
||||
error += diff*diff;
|
||||
}
|
||||
|
||||
// keep it if the error is lower
|
||||
if( error < m_error )
|
||||
{
|
||||
m_start = Vec3(
|
||||
( float )sources[0]->start/31.0f,
|
||||
( float )sources[1]->start/63.0f,
|
||||
( float )sources[2]->start/31.0f
|
||||
);
|
||||
m_end = Vec3(
|
||||
( float )sources[0]->end/31.0f,
|
||||
( float )sources[1]->end/63.0f,
|
||||
( float )sources[2]->end/31.0f
|
||||
);
|
||||
m_index = ( u8 )( 2*index );
|
||||
m_error = error;
|
||||
}
|
||||
}
|
||||
// check each index combination (endpoint or intermediate)
|
||||
m_error = INT_MAX;
|
||||
for( int index = 0; index < 2; ++index )
|
||||
{
|
||||
// check the error for this codebook index
|
||||
SourceBlock const* sources[3];
|
||||
int error = 0;
|
||||
for( int channel = 0; channel < 3; ++channel )
|
||||
{
|
||||
// grab the lookup table and index for this channel
|
||||
SingleColourLookup const* lookup = lookups[channel];
|
||||
int target = m_colour[channel];
|
||||
|
||||
// store a pointer to the source for this channel
|
||||
sources[channel] = lookup[target].sources + index;
|
||||
|
||||
// accumulate the error
|
||||
int diff = sources[channel]->error;
|
||||
error += diff*diff;
|
||||
}
|
||||
|
||||
// keep it if the error is lower
|
||||
if( error < m_error )
|
||||
{
|
||||
m_start = Vec3(
|
||||
( float )sources[0]->start/31.0f,
|
||||
( float )sources[1]->start/63.0f,
|
||||
( float )sources[2]->start/31.0f
|
||||
);
|
||||
m_end = Vec3(
|
||||
( float )sources[0]->end/31.0f,
|
||||
( float )sources[1]->end/63.0f,
|
||||
( float )sources[2]->end/31.0f
|
||||
);
|
||||
m_index = ( u8 )( 2*index );
|
||||
m_error = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace squish
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue