flatten tree.
This commit is contained in:
52
src/nvtt/squish/CMakeLists.txt
Normal file
52
src/nvtt/squish/CMakeLists.txt
Normal file
@ -0,0 +1,52 @@
|
||||
PROJECT(squish)
|
||||
ENABLE_TESTING()
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
SET(SQUISH_SRCS
|
||||
alpha.cpp
|
||||
alpha.h
|
||||
clusterfit.cpp
|
||||
clusterfit.h
|
||||
fastclusterfit.cpp
|
||||
fastclusterfit.h
|
||||
weightedclusterfit.cpp
|
||||
weightedclusterfit.h
|
||||
colourblock.cpp
|
||||
colourblock.h
|
||||
colourfit.cpp
|
||||
colourfit.h
|
||||
colourset.cpp
|
||||
colourset.h
|
||||
config.h
|
||||
maths.cpp
|
||||
maths.h
|
||||
rangefit.cpp
|
||||
rangefit.h
|
||||
singlecolourfit.cpp
|
||||
singlecolourfit.h
|
||||
singlecolourlookup.inl
|
||||
squish.cpp
|
||||
squish.h
|
||||
simd.h
|
||||
simd_sse.h
|
||||
simd_ve.h)
|
||||
|
||||
ADD_LIBRARY(squish STATIC ${SQUISH_SRCS})
|
||||
|
||||
# libpng
|
||||
FIND_PACKAGE(PNG)
|
||||
|
||||
IF(PNG_FOUND)
|
||||
INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIR})
|
||||
ADD_EXECUTABLE(squishpng extra/squishpng.cpp)
|
||||
TARGET_LINK_LIBRARIES(squishpng squish ${PNG_LIBRARY})
|
||||
ENDIF(PNG_FOUND)
|
||||
|
||||
#ADD_EXECUTABLE(squishgen extra/squishgen.cpp)
|
||||
|
||||
ADD_EXECUTABLE(squishtest extra/squishtest.cpp)
|
||||
TARGET_LINK_LIBRARIES(squishtest squish)
|
||||
|
||||
ADD_TEST(SQUISHTEST squishtest)
|
||||
|
38
src/nvtt/squish/ChangeLog
Normal file
38
src/nvtt/squish/ChangeLog
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
1.7
|
||||
* Fixed floating-point equality issue in clusterfit sort (x86 affected only)
|
||||
* Implemented proper SSE(2) floor function for 50% speedup on SSE builds
|
||||
* The range fit implementation now uses the correct colour metric
|
||||
|
||||
1.6
|
||||
* Fixed bug in CompressImage where masked pixels were not skipped over
|
||||
* DXT3 and DXT5 alpha compression now properly use the mask to ignore pixels
|
||||
* Fixed major DXT1 bug that can generate unexpected transparent pixels
|
||||
|
||||
1.5
|
||||
* Added CompressMasked function to handle incomplete DXT blocks more cleanly
|
||||
* Added kWeightColourByAlpha flag for better quality images when alpha blending
|
||||
|
||||
1.4
|
||||
* Fixed stack overflow in rangefit
|
||||
|
||||
1.3
|
||||
* Worked around SSE floor implementation bug, proper fix needed!
|
||||
* This release has visual studio and makefile builds that work
|
||||
|
||||
1.2
|
||||
* Added provably optimal single colour compressor
|
||||
* Added extra/squishgen.cpp that generates single colour lookup tables
|
||||
|
||||
1.1
|
||||
* Fixed a DXT1 colour output bug
|
||||
* Changed argument order for Decompress function to match Compress
|
||||
* Added GetStorageRequirements function
|
||||
* Added CompressImage function
|
||||
* Added DecompressImage function
|
||||
* Moved squishtool.cpp to extra/squishpng.cpp
|
||||
* Added extra/squishtest.cpp
|
||||
|
||||
1.0
|
||||
* Initial release
|
||||
|
223
src/nvtt/squish/Doxyfile
Normal file
223
src/nvtt/squish/Doxyfile
Normal file
@ -0,0 +1,223 @@
|
||||
# Doxyfile 1.4.6
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = squish
|
||||
PROJECT_NUMBER = 1.1
|
||||
OUTPUT_DIRECTORY = docs
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
USE_WINDOWS_ENCODING = NO
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_DIRECTORIES = NO
|
||||
FILE_VERSION_FILTER =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = squish.h
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = NO
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = NO
|
||||
USE_PDFLATEX = NO
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH = /Applications/Graphviz.app/Contents/MacOS
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = NO
|
31
src/nvtt/squish/Makefile
Normal file
31
src/nvtt/squish/Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
include config
|
||||
|
||||
SRC = alpha.cpp clusterfit.cpp colourblock.cpp colourfit.cpp colourset.cpp maths.cpp rangefit.cpp singlecolourfit.cpp squish.cpp
|
||||
|
||||
OBJ = $(SRC:%.cpp=%.o)
|
||||
|
||||
LIB = libsquish.a
|
||||
|
||||
all : $(LIB)
|
||||
|
||||
install : $(LIB)
|
||||
install squish.h $(INSTALL_DIR)/include
|
||||
install libsquish.a $(INSTALL_DIR)/lib
|
||||
|
||||
uninstall:
|
||||
$(RM) $(INSTALL_DIR)/include/squish.h
|
||||
$(RM) $(INSTALL_DIR)/lib/libsquish.a
|
||||
|
||||
$(LIB) : $(OBJ)
|
||||
$(AR) cr $@ $?
|
||||
ranlib $@
|
||||
|
||||
%.o : %.cpp
|
||||
$(CXX) $(CPPFLAGS) -I. $(CXXFLAGS) -o$@ -c $<
|
||||
|
||||
clean :
|
||||
$(RM) $(OBJ) $(LIB)
|
||||
|
||||
|
||||
|
35
src/nvtt/squish/README
Normal file
35
src/nvtt/squish/README
Normal file
@ -0,0 +1,35 @@
|
||||
LICENSE
|
||||
-------
|
||||
|
||||
The squish library is distributed under the terms and conditions of the MIT
|
||||
license. This license is specified at the top of each source file and must be
|
||||
preserved in its entirety.
|
||||
|
||||
BUILDING AND INSTALLING THE LIBRARY
|
||||
-----------------------------------
|
||||
|
||||
If you are using Visual Studio 2003 or above under Windows then load the Visual
|
||||
Studio 2003 project in the vs7 folder. By default, the library is built using
|
||||
SSE optimisations. To change this either change or remove the SQUISH_USE_SSE=1
|
||||
from the preprocessor symbols.
|
||||
|
||||
If you are using a Mac then load the Xcode 2.2 project in the distribution. By
|
||||
default, the library is built using Altivec optimisations. To change this
|
||||
either change or remove SQUISH_USE_ALTIVEC=1 from the preprocessor symbols. I
|
||||
guess I'll have to think about changing this for the new Intel Macs that are
|
||||
rolling out...
|
||||
|
||||
If you are using unix then first edit the config file in the base directory of
|
||||
the distribution, enabling Altivec or SSE with the USE_ALTIVEC or USE_SSE
|
||||
variables, and editing the optimisation flags passed to the C++ compiler if
|
||||
necessary. Then make can be used to build the library, and make install (from
|
||||
the superuser account) can be used to install (into /usr/local by default).
|
||||
|
||||
REPORTING BUGS OR FEATURE REQUESTS
|
||||
----------------------------------
|
||||
|
||||
Feedback can be sent to Simon Brown (the developer) at si@sjbrown.co.uk
|
||||
|
||||
New releases are announced on the squish library homepage at
|
||||
http://sjbrown.co.uk/?code=squish
|
||||
|
326
src/nvtt/squish/alpha.cpp
Normal file
326
src/nvtt/squish/alpha.cpp
Normal file
@ -0,0 +1,326 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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 "alpha.h"
|
||||
#include <algorithm>
|
||||
|
||||
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 );
|
||||
|
||||
// clamp to the limit
|
||||
if( i < 0 )
|
||||
i = 0;
|
||||
else if( i > limit )
|
||||
i = limit;
|
||||
|
||||
// done
|
||||
return i;
|
||||
}
|
||||
|
||||
void CompressAlphaDxt3( u8 const* rgba, void* 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 );
|
||||
|
||||
// pack into the byte
|
||||
bytes[i] = ( u8 )( quant1 | ( quant2 << 4 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void DecompressAlphaDxt3( u8* rgba, void 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
|
||||
rgba[8*i + 3] = lo | ( lo << 4 );
|
||||
rgba[8*i + 7] = hi | ( hi >> 4 );
|
||||
}
|
||||
}
|
||||
|
||||
static void FixRange( int& min, int& max, int steps )
|
||||
{
|
||||
if( max - min < steps )
|
||||
max = std::min( min + steps, 255 );
|
||||
if( max - min < steps )
|
||||
min = std::max( 0, max - steps );
|
||||
}
|
||||
|
||||
static int FitCodes( u8 const* rgba, u8 const* codes, u8* indices )
|
||||
{
|
||||
// fit each alpha value to the codebook
|
||||
int err = 0;
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
// find the least error and corresponding index
|
||||
int value = rgba[4*i + 3];
|
||||
int least = INT_MAX;
|
||||
int index = 0;
|
||||
for( int j = 0; j < 8; ++j )
|
||||
{
|
||||
// get the squared error from this code
|
||||
int dist = ( int )value - ( int )codes[j];
|
||||
dist *= dist;
|
||||
|
||||
// compare with the best so far
|
||||
if( dist < least )
|
||||
{
|
||||
least = dist;
|
||||
index = j;
|
||||
}
|
||||
}
|
||||
|
||||
// save this index and accumulate the error
|
||||
indices[i] = ( u8 )index;
|
||||
err += least;
|
||||
}
|
||||
|
||||
// return the total error
|
||||
return err;
|
||||
}
|
||||
|
||||
static void WriteAlphaBlock( int alpha0, int alpha1, u8 const* indices, void* block )
|
||||
{
|
||||
u8* bytes = reinterpret_cast< u8* >( block );
|
||||
|
||||
// write the first two bytes
|
||||
bytes[0] = ( u8 )alpha0;
|
||||
bytes[1] = ( u8 )alpha1;
|
||||
|
||||
// pack the indices with 3 bits each
|
||||
u8* dest = bytes + 2;
|
||||
u8 const* src = indices;
|
||||
for( int i = 0; i < 2; ++i )
|
||||
{
|
||||
// pack 8 3-bit values
|
||||
int value = 0;
|
||||
for( int j = 0; j < 8; ++j )
|
||||
{
|
||||
int index = *src++;
|
||||
value |= ( index << 3*j );
|
||||
}
|
||||
|
||||
// store in 3 bytes
|
||||
for( int j = 0; j < 3; ++j )
|
||||
{
|
||||
int byte = ( value >> 8*j ) & 0xff;
|
||||
*dest++ = ( u8 )byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteAlphaBlock5( int alpha0, int alpha1, u8 const* indices, void* block )
|
||||
{
|
||||
// check the relative values of the endpoints
|
||||
if( alpha0 > alpha1 )
|
||||
{
|
||||
// swap the indices
|
||||
u8 swapped[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
u8 index = indices[i];
|
||||
if( index == 0 )
|
||||
swapped[i] = 1;
|
||||
else if( index == 1 )
|
||||
swapped[i] = 0;
|
||||
else if( index <= 5 )
|
||||
swapped[i] = 7 - index;
|
||||
else
|
||||
swapped[i] = index;
|
||||
}
|
||||
|
||||
// write the block
|
||||
WriteAlphaBlock( alpha1, alpha0, swapped, block );
|
||||
}
|
||||
else
|
||||
{
|
||||
// write the block
|
||||
WriteAlphaBlock( alpha0, alpha1, indices, block );
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteAlphaBlock7( int alpha0, int alpha1, u8 const* indices, void* block )
|
||||
{
|
||||
// check the relative values of the endpoints
|
||||
if( alpha0 < alpha1 )
|
||||
{
|
||||
// swap the indices
|
||||
u8 swapped[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
u8 index = indices[i];
|
||||
if( index == 0 )
|
||||
swapped[i] = 1;
|
||||
else if( index == 1 )
|
||||
swapped[i] = 0;
|
||||
else
|
||||
swapped[i] = 9 - index;
|
||||
}
|
||||
|
||||
// write the block
|
||||
WriteAlphaBlock( alpha1, alpha0, swapped, block );
|
||||
}
|
||||
else
|
||||
{
|
||||
// write the block
|
||||
WriteAlphaBlock( alpha0, alpha1, indices, block );
|
||||
}
|
||||
}
|
||||
|
||||
void CompressAlphaDxt5( u8 const* rgba, void* block )
|
||||
{
|
||||
// get the range for 5-alpha and 7-alpha interpolation
|
||||
int min5 = 255;
|
||||
int max5 = 0;
|
||||
int min7 = 255;
|
||||
int max7 = 0;
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
// incorporate into the min/max
|
||||
int value = rgba[4*i + 3];
|
||||
if( value < min7 )
|
||||
min7 = value;
|
||||
if( value > max7 )
|
||||
max7 = value;
|
||||
if( value != 0 && value < min5 )
|
||||
min5 = value;
|
||||
if( value != 255 && value > max5 )
|
||||
max5 = value;
|
||||
}
|
||||
|
||||
// handle the case that no valid range was found
|
||||
if( min5 > max5 )
|
||||
min5 = max5;
|
||||
if( min7 > max7 )
|
||||
min7 = max7;
|
||||
|
||||
// fix the range to be the minimum in each case
|
||||
FixRange( min5, max5, 5 );
|
||||
FixRange( min7, max7, 7 );
|
||||
|
||||
// set up the 5-alpha code book
|
||||
u8 codes5[8];
|
||||
codes5[0] = ( u8 )min5;
|
||||
codes5[1] = ( u8 )max5;
|
||||
for( int i = 1; i < 5; ++i )
|
||||
codes5[1 + i] = ( u8 )( ( ( 5 - i )*min5 + i*max5 )/5 );
|
||||
codes5[6] = 0;
|
||||
codes5[7] = 255;
|
||||
|
||||
// set up the 7-alpha code book
|
||||
u8 codes7[8];
|
||||
codes7[0] = ( u8 )min7;
|
||||
codes7[1] = ( u8 )max7;
|
||||
for( int i = 1; i < 7; ++i )
|
||||
codes7[1 + i] = ( u8 )( ( ( 7 - i )*min7 + i*max7 )/7 );
|
||||
|
||||
// fit the data to both code books
|
||||
u8 indices5[16];
|
||||
u8 indices7[16];
|
||||
int err5 = FitCodes( rgba, codes5, indices5 );
|
||||
int err7 = FitCodes( rgba, codes7, indices7 );
|
||||
|
||||
// save the block with least error
|
||||
if( err5 <= err7 )
|
||||
WriteAlphaBlock5( min5, max5, indices5, block );
|
||||
else
|
||||
WriteAlphaBlock7( min7, max7, indices7, block );
|
||||
}
|
||||
|
||||
void DecompressAlphaDxt5( u8* rgba, void const* block )
|
||||
{
|
||||
// get the two alpha values
|
||||
u8 const* bytes = reinterpret_cast< u8 const* >( block );
|
||||
int alpha0 = bytes[0];
|
||||
int alpha1 = bytes[1];
|
||||
|
||||
// compare the values to build the codebook
|
||||
u8 codes[8];
|
||||
codes[0] = ( u8 )alpha0;
|
||||
codes[1] = ( u8 )alpha1;
|
||||
if( alpha0 <= alpha1 )
|
||||
{
|
||||
// use 5-alpha codebook
|
||||
for( int i = 1; i < 5; ++i )
|
||||
codes[1 + i] = ( u8 )( ( ( 5 - i )*alpha0 + i*alpha1 )/5 );
|
||||
codes[6] = 0;
|
||||
codes[7] = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
// use 7-alpha codebook
|
||||
for( int i = 1; i < 7; ++i )
|
||||
codes[1 + i] = ( u8 )( ( ( 7 - i )*alpha0 + i*alpha1 )/7 );
|
||||
}
|
||||
|
||||
// decode the indices
|
||||
u8 indices[16];
|
||||
u8 const* src = bytes + 2;
|
||||
u8* dest = indices;
|
||||
for( int i = 0; i < 2; ++i )
|
||||
{
|
||||
// grab 3 bytes
|
||||
int value = 0;
|
||||
for( int j = 0; j < 3; ++j )
|
||||
{
|
||||
int byte = *src++;
|
||||
value |= ( byte << 8*j );
|
||||
}
|
||||
|
||||
// unpack 8 3-bit values from it
|
||||
for( int j = 0; j < 8; ++j )
|
||||
{
|
||||
int index = ( value >> 3*j ) & 0x7;
|
||||
*dest++ = ( u8 )index;
|
||||
}
|
||||
}
|
||||
|
||||
// write out the indexed codebook values
|
||||
for( int i = 0; i < 16; ++i )
|
||||
rgba[4*i + 3] = codes[indices[i]];
|
||||
}
|
||||
|
||||
} // namespace squish
|
41
src/nvtt/squish/alpha.h
Normal file
41
src/nvtt/squish/alpha.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_ALPHA_H
|
||||
#define SQUISH_ALPHA_H
|
||||
|
||||
#include <squish.h>
|
||||
|
||||
namespace squish {
|
||||
|
||||
void CompressAlphaDxt3( u8 const* rgba, void* block );
|
||||
void CompressAlphaDxt5( u8 const* rgba, void* block );
|
||||
|
||||
void DecompressAlphaDxt3( u8* rgba, void const* block );
|
||||
void DecompressAlphaDxt5( u8* rgba, void const* block );
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_ALPHA_H
|
499
src/nvtt/squish/clusterfit.cpp
Normal file
499
src/nvtt/squish/clusterfit.cpp
Normal file
@ -0,0 +1,499 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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 "clusterfit.h"
|
||||
#include "colourset.h"
|
||||
#include "colourblock.h"
|
||||
#include <cfloat>
|
||||
|
||||
namespace squish {
|
||||
|
||||
ClusterFit::ClusterFit( ColourSet const* colours, int flags )
|
||||
: ColourFit( colours, flags )
|
||||
{
|
||||
// initialise the best error
|
||||
#if SQUISH_USE_SIMD
|
||||
m_besterror = VEC4_CONST( FLT_MAX );
|
||||
#else
|
||||
m_besterror = FLT_MAX;
|
||||
#endif
|
||||
|
||||
/* // initialise the metric
|
||||
bool perceptual = ( ( m_flags & kColourMetricPerceptual ) != 0 );
|
||||
#if SQUISH_USE_SIMD
|
||||
if( perceptual )
|
||||
m_metric = Vec4( 0.2126f, 0.7152f, 0.0722f, 0.0f );
|
||||
else
|
||||
m_metric = VEC4_CONST( 1.0f );
|
||||
#else
|
||||
if( perceptual )
|
||||
m_metric = Vec3( 0.2126f, 0.7152f, 0.0722f );
|
||||
else
|
||||
m_metric = Vec3( 1.0f );
|
||||
#endif
|
||||
*/
|
||||
// cache some values
|
||||
int const count = m_colours->GetCount();
|
||||
Vec3 const* values = m_colours->GetPoints();
|
||||
|
||||
// get the covariance matrix
|
||||
Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() );
|
||||
|
||||
// compute the principle component
|
||||
Vec3 principle = ComputePrincipleComponent( covariance );
|
||||
|
||||
// build the list of values
|
||||
float dps[16];
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
dps[i] = Dot( values[i], principle );
|
||||
m_order[i] = i;
|
||||
}
|
||||
|
||||
// stable sort
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j )
|
||||
{
|
||||
std::swap( dps[j], dps[j - 1] );
|
||||
std::swap( m_order[j], m_order[j - 1] );
|
||||
}
|
||||
}
|
||||
|
||||
// weight all the points
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 const* unweighted = m_colours->GetPointsSimd();
|
||||
Vec4 const* weights = m_colours->GetWeightsSimd();
|
||||
m_xxsum = VEC4_CONST( 0.0f );
|
||||
#else
|
||||
Vec3 const* unweighted = m_colours->GetPoints();
|
||||
float const* weights = m_colours->GetWeights();
|
||||
m_xxsum = Vec3( 0.0f );
|
||||
#endif
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
int p = m_order[i];
|
||||
m_unweighted[i] = unweighted[p];
|
||||
m_weights[i] = weights[p];
|
||||
m_weighted[i] = weights[p]*unweighted[p];
|
||||
m_xxsum += m_weighted[i]*m_weighted[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ClusterFit::setMetric(float r, float g, float b)
|
||||
{
|
||||
#if SQUISH_USE_SIMD
|
||||
m_metric = Vec4(r, g, b, 0);
|
||||
#else
|
||||
m_metric = Vec3(r, g, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
float ClusterFit::bestError() const
|
||||
{
|
||||
#if SQUISH_USE_SIMD
|
||||
return m_besterror.GetVec3().X();
|
||||
#else
|
||||
return m_besterror;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ClusterFit::Compress3( void* block )
|
||||
{
|
||||
// declare variables
|
||||
int const count = m_colours->GetCount();
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 beststart = VEC4_CONST( 0.0f );
|
||||
Vec4 bestend = VEC4_CONST( 0.0f );
|
||||
Vec4 besterror = VEC4_CONST( FLT_MAX );
|
||||
Vec4 const half = VEC4_CONST( 0.5f );
|
||||
Vec4 const zero = VEC4_CONST( 0.0f );
|
||||
#else
|
||||
Vec3 beststart( 0.0f );
|
||||
Vec3 bestend( 0.0f );
|
||||
float besterror = FLT_MAX;
|
||||
float const half = 0.5f;
|
||||
float const zero = 0.0f;
|
||||
#endif
|
||||
|
||||
// check all possible clusters for this total order
|
||||
u8 indices[16];
|
||||
u8 bestindices[16];
|
||||
|
||||
// first cluster [0,i) is at the start
|
||||
for( int m = 0; m < count; ++m )
|
||||
{
|
||||
indices[m] = 0;
|
||||
m_alpha[m] = m_weights[m];
|
||||
m_beta[m] = zero;
|
||||
}
|
||||
for( int i = count; i >= 0; --i )
|
||||
{
|
||||
// second cluster [i,j) is half along
|
||||
for( int m = i; m < count; ++m )
|
||||
{
|
||||
indices[m] = 2;
|
||||
m_alpha[m] = m_beta[m] = half*m_weights[m];
|
||||
}
|
||||
for( int j = count; j > i; --j )
|
||||
{
|
||||
// last cluster [j,k) is at the end
|
||||
if( j < count )
|
||||
{
|
||||
indices[j] = 1;
|
||||
m_alpha[j] = zero;
|
||||
m_beta[j] = m_weights[j];
|
||||
}
|
||||
|
||||
// solve a least squares problem to place the endpoints
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 start, end;
|
||||
Vec4 error = SolveLeastSquares( start, end );
|
||||
#else
|
||||
Vec3 start, end;
|
||||
float error = SolveLeastSquares( start, end );
|
||||
#endif
|
||||
|
||||
// keep the solution if it wins
|
||||
#if SQUISH_USE_SIMD
|
||||
if( CompareAnyLessThan( error, besterror ) )
|
||||
#else
|
||||
if( error < besterror )
|
||||
#endif
|
||||
{
|
||||
beststart = start;
|
||||
bestend = end;
|
||||
for( int m = 0; m < 16; ++m ) // TODO: make this faster?
|
||||
bestindices[m] = indices[m];
|
||||
besterror = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
#if SQUISH_USE_SIMD
|
||||
if( CompareAnyLessThan( besterror, m_besterror ) )
|
||||
#else
|
||||
if( besterror < m_besterror )
|
||||
#endif
|
||||
{
|
||||
// remap the indices
|
||||
u8 unordered[16];
|
||||
for( int i = 0; i < count; ++i )
|
||||
unordered[m_order[i]] = bestindices[i];
|
||||
m_colours->RemapIndices( unordered, bestindices );
|
||||
|
||||
// save the block
|
||||
#if SQUISH_USE_SIMD
|
||||
WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
|
||||
#else
|
||||
WriteColourBlock3( beststart, bestend, bestindices, block );
|
||||
#endif
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
//static int run = 0;
|
||||
//static bool debug = false;
|
||||
|
||||
void ClusterFit::Compress4( void* block )
|
||||
{
|
||||
//debug = (run == 1);
|
||||
//run++;
|
||||
|
||||
// declare variables
|
||||
int const count = m_colours->GetCount();
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 beststart = VEC4_CONST( 0.0f );
|
||||
Vec4 bestend = VEC4_CONST( 0.0f );
|
||||
Vec4 besterror = m_besterror;
|
||||
Vec4 const twothirds = VEC4_CONST( 2.0f/3.0f );
|
||||
Vec4 const onethird = VEC4_CONST( 1.0f/3.0f );
|
||||
Vec4 const zero = VEC4_CONST( 0.0f );
|
||||
#else
|
||||
Vec3 beststart( 0.0f );
|
||||
Vec3 bestend( 0.0f );
|
||||
float besterror = m_besterror;
|
||||
float const twothirds = 2.0f/3.0f;
|
||||
float const onethird = 1.0f/3.0f;
|
||||
float const zero = 0.0f;
|
||||
#endif
|
||||
|
||||
// check all possible clusters for this total order
|
||||
u8 indices[16];
|
||||
u8 bestindices[16];
|
||||
|
||||
// first cluster [0,i) is at the start
|
||||
for( int m = 0; m < count; ++m )
|
||||
{
|
||||
indices[m] = 0;
|
||||
m_alpha[m] = m_weights[m];
|
||||
m_beta[m] = zero;
|
||||
}
|
||||
for( int i = count; i >= 0; --i )
|
||||
{
|
||||
// second cluster [i,j) is one third along
|
||||
for( int m = i; m < count; ++m )
|
||||
{
|
||||
indices[m] = 2;
|
||||
m_alpha[m] = twothirds*m_weights[m];
|
||||
m_beta[m] = onethird*m_weights[m];
|
||||
}
|
||||
for( int j = count; j >= i; --j )
|
||||
{
|
||||
// third cluster [j,k) is two thirds along
|
||||
for( int m = j; m < count; ++m )
|
||||
{
|
||||
indices[m] = 3;
|
||||
m_alpha[m] = onethird*m_weights[m];
|
||||
m_beta[m] = twothirds*m_weights[m];
|
||||
}
|
||||
for( int k = count; k >= j; --k )
|
||||
{
|
||||
if (j + k == 0) continue;
|
||||
|
||||
// last cluster [k,n) is at the end
|
||||
if( k < count )
|
||||
{
|
||||
indices[k] = 1;
|
||||
m_alpha[k] = zero;
|
||||
m_beta[k] = m_weights[k];
|
||||
}
|
||||
|
||||
/*unsigned int permutation = 0;
|
||||
for(int p = 0; p < 16; p++) {
|
||||
permutation |= indices[p] << (p * 2);
|
||||
}
|
||||
if (debug) printf("%X:\t", permutation);
|
||||
|
||||
if (debug && permutation == 0x55FFFFAA) __debugbreak();
|
||||
*/
|
||||
|
||||
// solve a least squares problem to place the endpoints
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 start, end;
|
||||
Vec4 error = SolveLeastSquares( start, end );
|
||||
#else
|
||||
Vec3 start, end;
|
||||
float error = SolveLeastSquares( start, end );
|
||||
#endif
|
||||
|
||||
// keep the solution if it wins
|
||||
#if SQUISH_USE_SIMD
|
||||
if( CompareAnyLessThan( error, besterror ) )
|
||||
#else
|
||||
if( error < besterror )
|
||||
#endif
|
||||
{
|
||||
beststart = start;
|
||||
bestend = end;
|
||||
for( int m = 0; m < 16; ++m ) // TODO: make this faster?
|
||||
bestindices[m] = indices[m];
|
||||
besterror = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
#if SQUISH_USE_SIMD
|
||||
if( CompareAnyLessThan( besterror, m_besterror ) )
|
||||
#else
|
||||
if( besterror < m_besterror )
|
||||
#endif
|
||||
{
|
||||
// remap the indices
|
||||
u8 unordered[16];
|
||||
for( int i = 0; i < count; ++i )
|
||||
unordered[m_order[i]] = bestindices[i];
|
||||
m_colours->RemapIndices( unordered, bestindices );
|
||||
|
||||
// save the block
|
||||
#if SQUISH_USE_SIMD
|
||||
WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
|
||||
#else
|
||||
WriteColourBlock4( beststart, bestend, bestindices, block );
|
||||
#endif
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 ClusterFit::SolveLeastSquares( Vec4& start, Vec4& end ) const
|
||||
{
|
||||
// accumulate all the quantities we need
|
||||
int const count = m_colours->GetCount();
|
||||
Vec4 alpha2_sum = VEC4_CONST( 0.0f );
|
||||
Vec4 beta2_sum = VEC4_CONST( 0.0f );
|
||||
Vec4 alphabeta_sum = VEC4_CONST( 0.0f );
|
||||
Vec4 alphax_sum = VEC4_CONST( 0.0f );
|
||||
Vec4 betax_sum = VEC4_CONST( 0.0f );
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
Vec4 alpha = m_alpha[i];
|
||||
Vec4 beta = m_beta[i];
|
||||
Vec4 x = m_weighted[i];
|
||||
|
||||
alpha2_sum = MultiplyAdd( alpha, alpha, alpha2_sum );
|
||||
beta2_sum = MultiplyAdd( beta, beta, beta2_sum );
|
||||
alphabeta_sum = MultiplyAdd( alpha, beta, alphabeta_sum );
|
||||
alphax_sum = MultiplyAdd( alpha, x, alphax_sum );
|
||||
betax_sum = MultiplyAdd( beta, x, betax_sum );
|
||||
}
|
||||
|
||||
// select the results
|
||||
Vec4 const zero = VEC4_CONST( 0.0f );
|
||||
Vec4 beta2_sum_zero = CompareEqual( beta2_sum, zero );
|
||||
Vec4 alpha2_sum_zero = CompareEqual( alpha2_sum, zero );
|
||||
|
||||
Vec4 a1 = alphax_sum*Reciprocal( alpha2_sum );
|
||||
Vec4 b1 = betax_sum*Reciprocal( beta2_sum );
|
||||
|
||||
Vec4 factor = Reciprocal( NegativeMultiplySubtract(
|
||||
alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum
|
||||
) );
|
||||
Vec4 a2 = NegativeMultiplySubtract(
|
||||
betax_sum, alphabeta_sum, alphax_sum*beta2_sum
|
||||
)*factor;
|
||||
Vec4 b2 = NegativeMultiplySubtract(
|
||||
alphax_sum, alphabeta_sum, betax_sum*alpha2_sum
|
||||
)*factor;
|
||||
|
||||
Vec4 a = Select( Select( a2, a1, beta2_sum_zero ), zero, alpha2_sum_zero );
|
||||
Vec4 b = Select( Select( b2, b1, alpha2_sum_zero ), zero, beta2_sum_zero );
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
Vec4 const one = VEC4_CONST( 1.0f );
|
||||
Vec4 const half = VEC4_CONST( 0.5f );
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
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( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f, 0.0f ); // IC: use approximate grid fitting.
|
||||
Vec4 const onethird = VEC4_CONST( 1.0f/3.0f );
|
||||
Vec4 const twothirds = VEC4_CONST( 2.0f/3.0f );
|
||||
a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp;
|
||||
b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec4 const two = VEC4_CONST( 2.0 );
|
||||
Vec4 e1 = MultiplyAdd( b*b, beta2_sum, m_xxsum );
|
||||
Vec4 e2 = MultiplyAdd( a, alphax_sum, b*betax_sum );
|
||||
Vec4 e3 = MultiplyAdd( a*a, alpha2_sum, e1 );
|
||||
Vec4 e4 = MultiplyAdd( a*b*alphabeta_sum - e2, two, e3 );
|
||||
|
||||
// apply the metric to the error term
|
||||
Vec4 e5 = e4*m_metric;
|
||||
Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ();
|
||||
|
||||
// save the start and end
|
||||
start = a;
|
||||
end = b;
|
||||
return error;
|
||||
}
|
||||
#else
|
||||
float ClusterFit::SolveLeastSquares( Vec3& start, Vec3& end ) const
|
||||
{
|
||||
// accumulate all the quantities we need
|
||||
int const count = m_colours->GetCount();
|
||||
float alpha2_sum = 0.0f;
|
||||
float beta2_sum = 0.0f;
|
||||
float alphabeta_sum = 0.0f;
|
||||
Vec3 alphax_sum( 0.0f );
|
||||
Vec3 betax_sum( 0.0f );
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
float alpha = m_alpha[i];
|
||||
float beta = m_beta[i];
|
||||
Vec3 const& x = m_weighted[i];
|
||||
|
||||
alpha2_sum += alpha*alpha;
|
||||
beta2_sum += beta*beta;
|
||||
alphabeta_sum += alpha*beta;
|
||||
alphax_sum += alpha*x;
|
||||
betax_sum += beta*x;
|
||||
}
|
||||
|
||||
//if (debug) printf("%f %f %f", alpha2_sum, beta2_sum, alphabeta_sum);
|
||||
|
||||
// zero where non-determinate
|
||||
Vec3 a, b;
|
||||
if( beta2_sum == 0.0f )
|
||||
{
|
||||
a = alphax_sum/alpha2_sum;
|
||||
b = Vec3( 0.0f );
|
||||
}
|
||||
else if( alpha2_sum == 0.0f )
|
||||
{
|
||||
a = Vec3( 0.0f );
|
||||
b = betax_sum/beta2_sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
float factor = 1.0f/( alpha2_sum*beta2_sum - alphabeta_sum*alphabeta_sum );
|
||||
|
||||
a = ( alphax_sum*beta2_sum - betax_sum*alphabeta_sum )*factor;
|
||||
b = ( betax_sum*alpha2_sum - alphax_sum*alphabeta_sum )*factor;
|
||||
}
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
Vec3 const one( 1.0f );
|
||||
Vec3 const zero( 0.0f );
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
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 gridrcp(0.03227752766457f, 0.01583151765563f, 0.03227752766457f); // IC: use approximate grid fitting.
|
||||
Vec3 const half( 0.5f );
|
||||
a = Floor( grid*a + half )*gridrcp;
|
||||
b = Floor( grid*b + half )*gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec3 e1 = a*a*alpha2_sum + b*b*beta2_sum /*+ m_xxsum*/
|
||||
+ 2.0f*( a*b*alphabeta_sum - a*alphax_sum - b*betax_sum );
|
||||
|
||||
// apply the metric to the error term
|
||||
float error = Dot( e1, m_metric );
|
||||
|
||||
//if (debug) printf(" - %f\n", error);
|
||||
|
||||
// save the start and end
|
||||
start = a;
|
||||
end = b;
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace squish
|
79
src/nvtt/squish/clusterfit.h
Normal file
79
src/nvtt/squish/clusterfit.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_CLUSTERFIT_H
|
||||
#define SQUISH_CLUSTERFIT_H
|
||||
|
||||
#include "squish.h"
|
||||
#include "maths.h"
|
||||
#include "simd.h"
|
||||
#include "colourfit.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
class ClusterFit : public ColourFit
|
||||
{
|
||||
public:
|
||||
ClusterFit( ColourSet const* colours, int flags );
|
||||
|
||||
void setMetric(float r, float g, float b);
|
||||
float bestError() const;
|
||||
|
||||
private:
|
||||
virtual void Compress3( void* block );
|
||||
virtual void Compress4( void* block );
|
||||
|
||||
void Reorder( Vec3::Arg principle );
|
||||
|
||||
Vec3 m_principle;
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 SolveLeastSquares( Vec4& start, Vec4& end ) const;
|
||||
|
||||
Vec4 m_weighted[16];
|
||||
Vec4 m_unweighted[16];
|
||||
Vec4 m_weights[16];
|
||||
Vec4 m_metric;
|
||||
Vec4 m_alpha[16];
|
||||
Vec4 m_beta[16];
|
||||
Vec4 m_xxsum;
|
||||
Vec4 m_besterror;
|
||||
#else
|
||||
float SolveLeastSquares( Vec3& start, Vec3& end ) const;
|
||||
|
||||
Vec3 m_weighted[16];
|
||||
Vec3 m_unweighted[16];
|
||||
float m_weights[16];
|
||||
Vec3 m_metric;
|
||||
float m_alpha[16];
|
||||
float m_beta[16];
|
||||
Vec3 m_xxsum;
|
||||
float m_besterror;
|
||||
#endif
|
||||
int m_order[16];
|
||||
};
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_CLUSTERFIT_H
|
278
src/nvtt/squish/colourblock.cpp
Normal file
278
src/nvtt/squish/colourblock.cpp
Normal file
@ -0,0 +1,278 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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 );
|
||||
|
||||
// clamp to the limit
|
||||
if( i < 0 )
|
||||
i = 0;
|
||||
else if( i > limit )
|
||||
i = limit;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
/*
|
||||
static void WriteColourBlock( int a, int b, uint 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 @@ Not sure that's correct...
|
||||
bytes[4] = ( u8 )((indices >> 24) & 0xff);
|
||||
bytes[5] = ( u8 )((indices >> 16) & 0xff);
|
||||
bytes[6] = ( u8 )((indices >> 8) & 0xff);
|
||||
bytes[7] = ( u8 )((indices >> 0) & 0xff);
|
||||
}
|
||||
|
||||
void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, uint indices, void* block )
|
||||
{
|
||||
// get the packed values
|
||||
int a = FloatTo565( start );
|
||||
int b = FloatTo565( end );
|
||||
|
||||
// remap the indices
|
||||
if( a > b )
|
||||
{
|
||||
// swap a and b
|
||||
std::swap( a, b );
|
||||
indices ^= (~indices >> 1) & 0x55555555;
|
||||
}
|
||||
else if ( a == b )
|
||||
{
|
||||
indices = 0;
|
||||
}
|
||||
|
||||
// write the block
|
||||
WriteColourBlock( a, b, indices, block );
|
||||
}
|
||||
|
||||
void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, uint indices, void* block )
|
||||
{
|
||||
// get the packed values
|
||||
int a = FloatTo565( start );
|
||||
int b = FloatTo565( end );
|
||||
|
||||
// remap the indices
|
||||
if( a < b )
|
||||
{
|
||||
// swap a and b
|
||||
std::swap( a, b );
|
||||
indices ^= 0x55555555;
|
||||
}
|
||||
else if( a == b )
|
||||
{
|
||||
indices = 0;
|
||||
}
|
||||
|
||||
// write the block
|
||||
WriteColourBlock( a, b, indices, 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;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace squish
|
43
src/nvtt/squish/colourblock.h
Normal file
43
src/nvtt/squish/colourblock.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_COLOURBLOCK_H
|
||||
#define SQUISH_COLOURBLOCK_H
|
||||
|
||||
#include "squish.h"
|
||||
#include "maths.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block );
|
||||
void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block );
|
||||
//void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, uint indices, void* block );
|
||||
//void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, uint indices, void* block );
|
||||
|
||||
void DecompressColour( u8* rgba, void const* block, bool isDxt1 );
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_COLOURBLOCK_H
|
54
src/nvtt/squish/colourfit.cpp
Normal file
54
src/nvtt/squish/colourfit.cpp
Normal file
@ -0,0 +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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#include "colourfit.h"
|
||||
#include "colourset.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
ColourFit::ColourFit( ColourSet const* colours, int flags )
|
||||
: m_colours( colours ),
|
||||
m_flags( flags )
|
||||
{
|
||||
}
|
||||
|
||||
void ColourFit::Compress( void* block )
|
||||
{
|
||||
bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 );
|
||||
if( isDxt1 )
|
||||
{
|
||||
Compress4( block );
|
||||
if( !m_colours->IsTransparent() )
|
||||
{
|
||||
Compress3( block );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Compress4( block );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace squish
|
53
src/nvtt/squish/colourfit.h
Normal file
53
src/nvtt/squish/colourfit.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_COLOURFIT_H
|
||||
#define SQUISH_COLOURFIT_H
|
||||
|
||||
#include "squish.h"
|
||||
#include "maths.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
class ColourSet;
|
||||
|
||||
class ColourFit
|
||||
{
|
||||
public:
|
||||
ColourFit( ColourSet const* colours, int flags );
|
||||
|
||||
void Compress( void* block );
|
||||
|
||||
protected:
|
||||
virtual void Compress3( void* block ) = 0;
|
||||
virtual void Compress4( void* block ) = 0;
|
||||
|
||||
ColourSet const* m_colours;
|
||||
int m_flags;
|
||||
};
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_COLOURFIT_H
|
134
src/nvtt/squish/colourset.cpp
Normal file
134
src/nvtt/squish/colourset.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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 flags )
|
||||
: 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 for transparent pixels when using dxt1
|
||||
if( isDxt1 && rgba[4*i + 3] == 0 )
|
||||
{
|
||||
m_remap[i] = -1;
|
||||
m_transparent = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 1
|
||||
// normalise coordinates to [0,1]
|
||||
float x = ( float )rgba[4*i + 2] / 255.0f;
|
||||
float y = ( float )rgba[4*i + 1] / 255.0f;
|
||||
float z = ( float )rgba[4*i + 0] / 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;
|
||||
#else
|
||||
// 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 + 2] / 255.0f;
|
||||
float y = ( float )rgba[4*i + 1] / 255.0f;
|
||||
float z = ( float )rgba[4*i + 0] / 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
|
||||
bool match = ( 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] != 0 || !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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SQUISH_USE_SIMD
|
||||
// generate vector values
|
||||
for( int i = 0; i < m_count; ++i )
|
||||
{
|
||||
m_points_simd[i] = Vec4(m_points[i].X(), m_points[i].Y(), m_points[i].Z(), 1);
|
||||
m_weights_simd[i] = VEC4_CONST(m_weights[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace squish
|
69
src/nvtt/squish/colourset.h
Normal file
69
src/nvtt/squish/colourset.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_COLOURSET_H
|
||||
#define SQUISH_COLOURSET_H
|
||||
|
||||
#include "squish.h"
|
||||
#include "maths.h"
|
||||
#include "simd.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
/*! @brief Represents a set of block colours
|
||||
*/
|
||||
class ColourSet
|
||||
{
|
||||
public:
|
||||
ColourSet( u8 const* rgba, int flags );
|
||||
|
||||
int GetCount() const { return m_count; }
|
||||
Vec3 const* GetPoints() const { return m_points; }
|
||||
float const* GetWeights() const { return m_weights; }
|
||||
bool IsTransparent() const { return m_transparent; }
|
||||
|
||||
void RemapIndices( u8 const* source, u8* target ) const;
|
||||
|
||||
private:
|
||||
int m_count;
|
||||
Vec3 m_points[16];
|
||||
float m_weights[16];
|
||||
int m_remap[16];
|
||||
bool m_transparent;
|
||||
|
||||
#if SQUISH_USE_SIMD
|
||||
public:
|
||||
Vec4 const* GetPointsSimd() const { return m_points_simd; }
|
||||
Vec4 const* GetWeightsSimd() const { return m_weights_simd; }
|
||||
|
||||
private:
|
||||
Vec4 m_points_simd[16];
|
||||
Vec4 m_weights_simd[16];
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace sqish
|
||||
|
||||
#endif // ndef SQUISH_COLOURSET_H
|
22
src/nvtt/squish/config
Normal file
22
src/nvtt/squish/config
Normal file
@ -0,0 +1,22 @@
|
||||
# config file used for the Makefile only
|
||||
|
||||
# define to 1 to use altivec instructions
|
||||
USE_ALTIVEC ?= 0
|
||||
|
||||
# define to 1 to use sse instructions
|
||||
USE_SSE ?= 0
|
||||
|
||||
# default flags
|
||||
CXXFLAGS ?= -O2
|
||||
ifeq ($(USE_ALTIVEC),1)
|
||||
CPPFLAGS += -DSQUISH_USE_ALTIVEC=1
|
||||
CXXFLAGS += -maltivec
|
||||
endif
|
||||
ifeq ($(USE_SSE),1)
|
||||
CPPFLAGS += -DSQUISH_USE_SSE=1
|
||||
CXXFLAGS += -msse
|
||||
endif
|
||||
|
||||
# where should we install to
|
||||
INSTALL_DIR ?= /usr/local
|
||||
|
55
src/nvtt/squish/config.h
Normal file
55
src/nvtt/squish/config.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_CONFIG_H
|
||||
#define SQUISH_CONFIG_H
|
||||
|
||||
// Set to 1 when building squish to use altivec instructions.
|
||||
#ifndef SQUISH_USE_ALTIVEC
|
||||
# define SQUISH_USE_ALTIVEC defined(__VEC__)
|
||||
#endif
|
||||
|
||||
// Set to 1 when building squish to use sse instructions.
|
||||
#ifndef SQUISH_USE_SSE
|
||||
# if defined(__SSE2__)
|
||||
# define SQUISH_USE_SSE 2
|
||||
# elif defined(__SSE__)
|
||||
# define SQUISH_USE_SSE 1
|
||||
# else
|
||||
# define SQUISH_USE_SSE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Internally et SQUISH_USE_SIMD when either altivec or sse is available.
|
||||
#if SQUISH_USE_ALTIVEC && SQUISH_USE_SSE
|
||||
# error "Cannot enable both altivec and sse!"
|
||||
#endif
|
||||
#if SQUISH_USE_ALTIVEC || SQUISH_USE_SSE
|
||||
# define SQUISH_USE_SIMD 1
|
||||
#else
|
||||
# define SQUISH_USE_SIMD 0
|
||||
#endif
|
||||
|
||||
#endif // ndef SQUISH_CONFIG_H
|
158
src/nvtt/squish/extra/squishgen.cpp
Normal file
158
src/nvtt/squish/extra/squishgen.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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 <iostream>
|
||||
|
||||
struct SourceBlock
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
int error;
|
||||
};
|
||||
|
||||
struct TargetValue
|
||||
{
|
||||
SourceBlock sources[4];
|
||||
};
|
||||
|
||||
static void GenerateData( std::string const& name, int bits, int colours )
|
||||
{
|
||||
TargetValue values[256];
|
||||
|
||||
// initialise the data
|
||||
for( int target = 0; target < 256; ++target )
|
||||
for( int index = 0; index < colours; ++index )
|
||||
values[target].sources[index].error = 255;
|
||||
|
||||
// loop over all possible source points
|
||||
int count = ( 1 << bits );
|
||||
for( int value1 = 0; value1 < count; ++value1 )
|
||||
{
|
||||
for( int value2 = 0; value2 < count; ++value2 )
|
||||
{
|
||||
// compute the 8-bit endpoints
|
||||
int a = ( value1 << ( 8 - bits ) ) | ( value1 >> ( 2*bits - 8 ) );
|
||||
int b = ( value2 << ( 8 - bits ) ) | ( value2 >> ( 2*bits - 8 ) );
|
||||
|
||||
// fill in the codebook with the these and intermediates
|
||||
int codes[4];
|
||||
codes[0] = a;
|
||||
codes[1] = b;
|
||||
if( colours == 3 )
|
||||
{
|
||||
codes[2] = ( a + b )/2;
|
||||
codes[3] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
codes[2] = ( 2*a + b )/3;
|
||||
codes[3] = ( a + 2*b )/3;
|
||||
}
|
||||
|
||||
// mark each target point with the endpoints and index needed for it
|
||||
for( int index = 0; index < colours; ++index )
|
||||
{
|
||||
int target = codes[index];
|
||||
|
||||
SourceBlock& block = values[target].sources[index];
|
||||
if( block.error != 0 )
|
||||
{
|
||||
block.start = value1;
|
||||
block.end = value2;
|
||||
block.error = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iteratively fill in the missing values
|
||||
for( ;; )
|
||||
{
|
||||
bool stable = true;
|
||||
for( int index = 0; index < colours; ++index )
|
||||
{
|
||||
for( int target = 0; target < 256; ++target )
|
||||
{
|
||||
if( target != 255 )
|
||||
{
|
||||
SourceBlock& current = values[target].sources[index];
|
||||
SourceBlock& next = values[target + 1].sources[index];
|
||||
if( current.error > next.error + 1 )
|
||||
{
|
||||
current.start = next.start;
|
||||
current.end = next.end;
|
||||
current.error = next.error + 1;
|
||||
stable = false;
|
||||
}
|
||||
}
|
||||
if( target != 0 )
|
||||
{
|
||||
SourceBlock& current = values[target].sources[index];
|
||||
SourceBlock& previous = values[target - 1].sources[index];
|
||||
if( current.error > previous.error + 1 )
|
||||
{
|
||||
current.start = previous.start;
|
||||
current.end = previous.end;
|
||||
current.error = previous.error + 1;
|
||||
stable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( stable )
|
||||
break;
|
||||
}
|
||||
|
||||
// debug
|
||||
std::cout << "\nstatic SingleColourLookup const " << name << "[] = \n{\n";
|
||||
for( int i = 0;; )
|
||||
{
|
||||
std::cout << "\t{ { ";
|
||||
for( int j = 0;; )
|
||||
{
|
||||
SourceBlock const& block = values[i].sources[j];
|
||||
if( j < colours )
|
||||
std::cout << "{ " << block.start << ", " << block.end << ", " << block.error << " }";
|
||||
else
|
||||
std::cout << "{ 0, 0, 0 }";
|
||||
if( ++j == 4 )
|
||||
break;
|
||||
std::cout << ", ";
|
||||
}
|
||||
std::cout << " } }";
|
||||
if( ++i == 256 )
|
||||
break;
|
||||
std::cout << ",\n";
|
||||
}
|
||||
std::cout << "\n};\n";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
GenerateData( "lookup_5_3", 5, 3 );
|
||||
GenerateData( "lookup_6_3", 6, 3 );
|
||||
GenerateData( "lookup_5_4", 5, 4 );
|
||||
GenerateData( "lookup_6_4", 6, 4 );
|
||||
}
|
603
src/nvtt/squish/extra/squishpng.cpp
Normal file
603
src/nvtt/squish/extra/squishpng.cpp
Normal file
@ -0,0 +1,603 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
|
||||
@brief Example program that converts between the PNG and DXT formats.
|
||||
|
||||
This program requires libpng for PNG input and output, and is designed
|
||||
to show how to prepare data for the squish library when it is not simply
|
||||
a contiguous block of memory.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
#include <squish.h>
|
||||
#include <png.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( disable: 4511 4512 )
|
||||
#endif // def _MSC_VER
|
||||
|
||||
using namespace squish;
|
||||
|
||||
//! Simple exception class.
|
||||
class Error : public std::exception
|
||||
{
|
||||
public:
|
||||
Error( std::string const& excuse ) : m_excuse( excuse ) {}
|
||||
~Error() throw() {}
|
||||
|
||||
virtual char const* what() const throw() { return m_excuse.c_str(); }
|
||||
|
||||
private:
|
||||
std::string m_excuse;
|
||||
};
|
||||
|
||||
//! Base class to make derived classes non-copyable
|
||||
class NonCopyable
|
||||
{
|
||||
public:
|
||||
NonCopyable() {}
|
||||
|
||||
private:
|
||||
NonCopyable( NonCopyable const& );
|
||||
NonCopyable& operator=( NonCopyable const& );
|
||||
};
|
||||
|
||||
//! Memory object.
|
||||
class Mem : NonCopyable
|
||||
{
|
||||
public:
|
||||
explicit Mem( int size ) : m_p( new u8[size] ) {}
|
||||
~Mem() { delete[] m_p; }
|
||||
|
||||
u8* Get() const { return m_p; }
|
||||
|
||||
private:
|
||||
u8* m_p;
|
||||
};
|
||||
|
||||
//! File object.
|
||||
class File : NonCopyable
|
||||
{
|
||||
public:
|
||||
explicit File( FILE* fp ) : m_fp( fp ) {}
|
||||
~File() { if( m_fp ) fclose( m_fp ); }
|
||||
|
||||
bool IsValid() const { return m_fp != 0; }
|
||||
FILE* Get() const { return m_fp; }
|
||||
|
||||
private:
|
||||
FILE* m_fp;
|
||||
};
|
||||
|
||||
//! PNG read object.
|
||||
class PngReadStruct : NonCopyable
|
||||
{
|
||||
public:
|
||||
PngReadStruct()
|
||||
: m_png( 0 ),
|
||||
m_info( 0 ),
|
||||
m_end( 0 )
|
||||
{
|
||||
m_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
|
||||
if( !m_png )
|
||||
throw Error( "failed to create png read struct" );
|
||||
|
||||
m_info = png_create_info_struct( m_png );
|
||||
m_end = png_create_info_struct( m_png );
|
||||
if( !m_info || !m_end )
|
||||
{
|
||||
png_infopp info = m_info ? &m_info : 0;
|
||||
png_infopp end = m_end ? &m_end : 0;
|
||||
png_destroy_read_struct( &m_png, info, end );
|
||||
throw Error( "failed to create png info structs" );
|
||||
}
|
||||
}
|
||||
|
||||
~PngReadStruct()
|
||||
{
|
||||
png_destroy_read_struct( &m_png, &m_info, &m_end );
|
||||
}
|
||||
|
||||
png_structp GetPng() const { return m_png; }
|
||||
png_infop GetInfo() const { return m_info; }
|
||||
|
||||
private:
|
||||
png_structp m_png;
|
||||
png_infop m_info, m_end;
|
||||
};
|
||||
|
||||
//! PNG write object.
|
||||
class PngWriteStruct : NonCopyable
|
||||
{
|
||||
public:
|
||||
PngWriteStruct()
|
||||
: m_png( 0 ),
|
||||
m_info( 0 )
|
||||
{
|
||||
m_png = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
|
||||
if( !m_png )
|
||||
throw Error( "failed to create png read struct" );
|
||||
|
||||
m_info = png_create_info_struct( m_png );
|
||||
if( !m_info )
|
||||
{
|
||||
png_infopp info = m_info ? &m_info : 0;
|
||||
png_destroy_write_struct( &m_png, info );
|
||||
throw Error( "failed to create png info structs" );
|
||||
}
|
||||
}
|
||||
|
||||
~PngWriteStruct()
|
||||
{
|
||||
png_destroy_write_struct( &m_png, &m_info );
|
||||
}
|
||||
|
||||
png_structp GetPng() const { return m_png; }
|
||||
png_infop GetInfo() const { return m_info; }
|
||||
|
||||
private:
|
||||
png_structp m_png;
|
||||
png_infop m_info;
|
||||
};
|
||||
|
||||
//! PNG rows object.
|
||||
class PngRows : NonCopyable
|
||||
{
|
||||
public:
|
||||
PngRows( int width, int height, int stride ) : m_width( width ), m_height( height )
|
||||
{
|
||||
m_rows = ( png_bytep* )malloc( m_height*sizeof( png_bytep ) );
|
||||
for( int i = 0; i < m_height; ++i )
|
||||
m_rows[i] = ( png_bytep )malloc( m_width*stride );
|
||||
}
|
||||
|
||||
~PngRows()
|
||||
{
|
||||
for( int i = 0; i < m_height; ++i )
|
||||
free( m_rows[i] );
|
||||
free( m_rows );
|
||||
}
|
||||
|
||||
png_bytep* Get() const { return m_rows; }
|
||||
|
||||
private:
|
||||
png_bytep* m_rows;
|
||||
int m_width, m_height;
|
||||
};
|
||||
|
||||
class PngImage
|
||||
{
|
||||
public:
|
||||
explicit PngImage( std::string const& fileName );
|
||||
|
||||
int GetWidth() const { return m_width; }
|
||||
int GetHeight() const { return m_height; }
|
||||
int GetStride() const { return m_stride; }
|
||||
bool IsColour() const { return m_colour; }
|
||||
bool IsAlpha() const { return m_alpha; }
|
||||
|
||||
u8 const* GetRow( int row ) const { return ( u8* )m_rows[row]; }
|
||||
|
||||
private:
|
||||
PngReadStruct m_png;
|
||||
|
||||
int m_width;
|
||||
int m_height;
|
||||
int m_stride;
|
||||
bool m_colour;
|
||||
bool m_alpha;
|
||||
|
||||
png_bytep* m_rows;
|
||||
};
|
||||
|
||||
PngImage::PngImage( std::string const& fileName )
|
||||
{
|
||||
// open the source file
|
||||
File file( fopen( fileName.c_str(), "rb" ) );
|
||||
if( !file.IsValid() )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "failed to open \"" << fileName << "\" for reading";
|
||||
throw Error( oss.str() );
|
||||
}
|
||||
|
||||
// check the signature bytes
|
||||
png_byte header[8];
|
||||
fread( header, 1, 8, file.Get() );
|
||||
if( png_sig_cmp( header, 0, 8 ) )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "\"" << fileName << "\" does not look like a png file";
|
||||
throw Error( oss.str() );
|
||||
}
|
||||
|
||||
// read the image into memory
|
||||
png_init_io( m_png.GetPng(), file.Get() );
|
||||
png_set_sig_bytes( m_png.GetPng(), 8 );
|
||||
png_read_png( m_png.GetPng(), m_png.GetInfo(), PNG_TRANSFORM_EXPAND, 0 );
|
||||
|
||||
// get the image info
|
||||
png_uint_32 width;
|
||||
png_uint_32 height;
|
||||
int bitDepth;
|
||||
int colourType;
|
||||
png_get_IHDR( m_png.GetPng(), m_png.GetInfo(), &width, &height, &bitDepth, &colourType, 0, 0, 0 );
|
||||
|
||||
// check the image is 8 bit
|
||||
if( bitDepth != 8 )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "cannot process " << bitDepth << "-bit image (bit depth must be 8)";
|
||||
throw Error( oss.str() );
|
||||
}
|
||||
|
||||
// save the info
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_colour = ( ( colourType & PNG_COLOR_MASK_COLOR ) != 0 );
|
||||
m_alpha = ( ( colourType & PNG_COLOR_MASK_ALPHA ) != 0 );
|
||||
m_stride = ( m_colour ? 3 : 1 ) + ( m_alpha ? 1 : 0 );
|
||||
|
||||
// get the image rows
|
||||
m_rows = png_get_rows( m_png.GetPng(), m_png.GetInfo() );
|
||||
if( !m_rows )
|
||||
throw Error( "failed to get image rows" );
|
||||
}
|
||||
|
||||
static void Compress( std::string const& sourceFileName, std::string const& targetFileName, int flags )
|
||||
{
|
||||
// load the source image
|
||||
PngImage sourceImage( sourceFileName );
|
||||
|
||||
// get the image info
|
||||
int width = sourceImage.GetWidth();
|
||||
int height = sourceImage.GetHeight();
|
||||
int stride = sourceImage.GetStride();
|
||||
bool colour = sourceImage.IsColour();
|
||||
bool alpha = sourceImage.IsAlpha();
|
||||
|
||||
// check the image dimensions
|
||||
if( ( width % 4 ) != 0 || ( height % 4 ) != 0 )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "cannot compress " << width << "x" << height
|
||||
<< "image (dimensions must be multiples of 4)";
|
||||
throw Error( oss.str() );
|
||||
}
|
||||
|
||||
// create the target data
|
||||
int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
|
||||
int targetDataSize = bytesPerBlock*width*height/16;
|
||||
Mem targetData( targetDataSize );
|
||||
|
||||
// loop over blocks and compress them
|
||||
clock_t start = std::clock();
|
||||
u8* targetBlock = targetData.Get();
|
||||
for( int y = 0; y < height; y += 4 )
|
||||
{
|
||||
// process a row of blocks
|
||||
for( int x = 0; x < width; x += 4 )
|
||||
{
|
||||
// get the block data
|
||||
u8 sourceRgba[16*4];
|
||||
for( int py = 0, i = 0; py < 4; ++py )
|
||||
{
|
||||
u8 const* row = sourceImage.GetRow( y + py ) + x*stride;
|
||||
for( int px = 0; px < 4; ++px, ++i )
|
||||
{
|
||||
// get the pixel colour
|
||||
if( colour )
|
||||
{
|
||||
for( int j = 0; j < 3; ++j )
|
||||
sourceRgba[4*i + j] = *row++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int j = 0; j < 3; ++j )
|
||||
sourceRgba[4*i + j] = *row;
|
||||
++row;
|
||||
}
|
||||
|
||||
// skip alpha for now
|
||||
if( alpha )
|
||||
sourceRgba[4*i + 3] = *row++;
|
||||
else
|
||||
sourceRgba[4*i + 3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
// compress this block
|
||||
Compress( sourceRgba, targetBlock, flags );
|
||||
|
||||
// advance
|
||||
targetBlock += bytesPerBlock;
|
||||
}
|
||||
}
|
||||
clock_t end = std::clock();
|
||||
double duration = ( double )( end - start ) / CLOCKS_PER_SEC;
|
||||
std::cout << "time taken: " << duration << " seconds" << std::endl;
|
||||
|
||||
// open the target file
|
||||
File targetFile( fopen( targetFileName.c_str(), "wb" ) );
|
||||
if( !targetFile.IsValid() )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "failed to open \"" << sourceFileName << "\" for writing";
|
||||
throw Error( oss.str() );
|
||||
}
|
||||
|
||||
// write the header
|
||||
fwrite( &width, sizeof( int ), 1, targetFile.Get() );
|
||||
fwrite( &height, sizeof( int ), 1, targetFile.Get() );
|
||||
|
||||
// write the data
|
||||
fwrite( targetData.Get(), 1, targetDataSize, targetFile.Get() );
|
||||
}
|
||||
|
||||
static void Decompress( std::string const& sourceFileName, std::string const& targetFileName, int flags )
|
||||
{
|
||||
// open the source file
|
||||
File sourceFile( fopen( sourceFileName.c_str(), "rb" ) );
|
||||
if( !sourceFile.IsValid() )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "failed to open \"" << sourceFileName << "\" for reading";
|
||||
throw Error( oss.str() );
|
||||
}
|
||||
|
||||
// get the width and height
|
||||
int width, height;
|
||||
fread( &width, sizeof( int ), 1, sourceFile.Get() );
|
||||
fread( &height, sizeof( int ), 1, sourceFile.Get() );
|
||||
|
||||
// work out the data size
|
||||
int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
|
||||
int sourceDataSize = bytesPerBlock*width*height/16;
|
||||
Mem sourceData( sourceDataSize );
|
||||
|
||||
// read the source data
|
||||
fread( sourceData.Get(), 1, sourceDataSize, sourceFile.Get() );
|
||||
|
||||
// create the target rows
|
||||
PngRows targetRows( width, height, 4 );
|
||||
|
||||
// loop over blocks and compress them
|
||||
u8 const* sourceBlock = sourceData.Get();
|
||||
for( int y = 0; y < height; y += 4 )
|
||||
{
|
||||
// process a row of blocks
|
||||
for( int x = 0; x < width; x += 4 )
|
||||
{
|
||||
// decompress back
|
||||
u8 targetRgba[16*4];
|
||||
Decompress( targetRgba, sourceBlock, flags );
|
||||
|
||||
// write the data into the target rows
|
||||
for( int py = 0, i = 0; py < 4; ++py )
|
||||
{
|
||||
u8* row = ( u8* )targetRows.Get()[y + py] + x*4;
|
||||
for( int px = 0; px < 4; ++px, ++i )
|
||||
{
|
||||
for( int j = 0; j < 4; ++j )
|
||||
*row++ = targetRgba[4*i + j];
|
||||
}
|
||||
}
|
||||
|
||||
// advance
|
||||
sourceBlock += bytesPerBlock;
|
||||
}
|
||||
}
|
||||
|
||||
// create the target PNG
|
||||
PngWriteStruct targetPng;
|
||||
|
||||
// set up the image
|
||||
png_set_IHDR(
|
||||
targetPng.GetPng(), targetPng.GetInfo(), width, height,
|
||||
8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
|
||||
);
|
||||
|
||||
// open the target file
|
||||
File targetFile( fopen( targetFileName.c_str(), "wb" ) );
|
||||
if( !targetFile.IsValid() )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "failed to open \"" << targetFileName << "\" for writing";
|
||||
throw Error( oss.str() );
|
||||
}
|
||||
|
||||
// write the image
|
||||
png_set_rows( targetPng.GetPng(), targetPng.GetInfo(), targetRows.Get() );
|
||||
png_init_io( targetPng.GetPng(), targetFile.Get() );
|
||||
png_write_png( targetPng.GetPng(), targetPng.GetInfo(), PNG_TRANSFORM_IDENTITY, 0 );
|
||||
}
|
||||
|
||||
static void Diff( std::string const& sourceFileName, std::string const& targetFileName )
|
||||
{
|
||||
// load the images
|
||||
PngImage sourceImage( sourceFileName );
|
||||
PngImage targetImage( targetFileName );
|
||||
|
||||
// get the image info
|
||||
int width = sourceImage.GetWidth();
|
||||
int height = sourceImage.GetHeight();
|
||||
int sourceStride = sourceImage.GetStride();
|
||||
int targetStride = targetImage.GetStride();
|
||||
int stride = std::min( sourceStride, targetStride );
|
||||
|
||||
// check they match
|
||||
if( width != targetImage.GetWidth() || height != targetImage.GetHeight() )
|
||||
throw Error( "source and target dimensions do not match" );
|
||||
|
||||
// work out the error
|
||||
double error = 0.0;
|
||||
for( int y = 0; y < height; ++y )
|
||||
{
|
||||
u8 const* sourceRow = sourceImage.GetRow( y );
|
||||
u8 const* targetRow = targetImage.GetRow( y );
|
||||
for( int x = 0; x < width; ++x )
|
||||
{
|
||||
u8 const* sourcePixel = sourceRow + x*sourceStride;
|
||||
u8 const* targetPixel = targetRow + x*targetStride;
|
||||
for( int i = 0; i < stride; ++i )
|
||||
{
|
||||
int diff = ( int )sourcePixel[i] - ( int )targetPixel[i];
|
||||
error += ( double )( diff*diff );
|
||||
}
|
||||
}
|
||||
}
|
||||
error = std::sqrt( error / ( width*height ) );
|
||||
|
||||
// print it out
|
||||
std::cout << "rms error: " << error << std::endl;
|
||||
}
|
||||
|
||||
enum Mode
|
||||
{
|
||||
kCompress,
|
||||
kDecompress,
|
||||
kDiff
|
||||
};
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
try
|
||||
{
|
||||
// parse the command-line
|
||||
std::string sourceFileName;
|
||||
std::string targetFileName;
|
||||
Mode mode = kCompress;
|
||||
int method = kDxt1;
|
||||
int metric = kColourMetricPerceptual;
|
||||
int fit = kColourClusterFit;
|
||||
int extra = 0;
|
||||
bool help = false;
|
||||
bool arguments = true;
|
||||
for( int i = 1; i < argc; ++i )
|
||||
{
|
||||
// check for options
|
||||
char const* word = argv[i];
|
||||
if( arguments && word[0] == '-' )
|
||||
{
|
||||
for( int j = 1; word[j] != '\0'; ++j )
|
||||
{
|
||||
switch( word[j] )
|
||||
{
|
||||
case 'h': help = true; break;
|
||||
case 'c': mode = kCompress; break;
|
||||
case 'd': mode = kDecompress; break;
|
||||
case 'e': mode = kDiff; break;
|
||||
case '1': method = kDxt1; break;
|
||||
case '3': method = kDxt3; break;
|
||||
case '5': method = kDxt5; break;
|
||||
case 'u': metric = kColourMetricUniform; break;
|
||||
case 'r': fit = kColourRangeFit; break;
|
||||
case 'w': extra = kWeightColourByAlpha; break;
|
||||
case '-': arguments = false; break;
|
||||
default:
|
||||
std::cerr << "unknown option '" << word[j] << "'" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( sourceFileName.empty() )
|
||||
sourceFileName.assign( word );
|
||||
else if( targetFileName.empty() )
|
||||
targetFileName.assign( word );
|
||||
else
|
||||
{
|
||||
std::cerr << "unexpected argument \"" << word << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check arguments
|
||||
if( help )
|
||||
{
|
||||
std::cout
|
||||
<< "SYNTAX" << std::endl
|
||||
<< "\tsquishpng [-cde135] <source> <target>" << std::endl
|
||||
<< "OPTIONS" << std::endl
|
||||
<< "\t-c\tCompress source png to target raw dxt (default)" << std::endl
|
||||
<< "\t-135\tSpecifies whether to use DXT1 (default), DXT3 or DXT5 compression" << std::endl
|
||||
<< "\t-u\tUse a uniform colour metric during colour compression" << std::endl
|
||||
<< "\t-r\tUse the fast but inferior range-based colour compressor" << std::endl
|
||||
<< "\t-w\tWeight colour values by alpha in the cluster colour compressor" << std::endl
|
||||
<< "\t-d\tDecompress source raw dxt to target png" << std::endl
|
||||
<< "\t-e\tDiff source and target png" << std::endl
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
if( sourceFileName.empty() )
|
||||
{
|
||||
std::cerr << "no source file given" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if( targetFileName.empty() )
|
||||
{
|
||||
std::cerr << "no target file given" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// do the work
|
||||
switch( mode )
|
||||
{
|
||||
case kCompress:
|
||||
Compress( sourceFileName, targetFileName, method | metric | fit | extra );
|
||||
break;
|
||||
|
||||
case kDecompress:
|
||||
Decompress( sourceFileName, targetFileName, method );
|
||||
break;
|
||||
|
||||
case kDiff:
|
||||
Diff( sourceFileName, targetFileName );
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "unknown mode" << std::endl;
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
catch( std::exception& excuse )
|
||||
{
|
||||
// complain
|
||||
std::cerr << "squishpng error: " << excuse.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// done
|
||||
return 0;
|
||||
}
|
205
src/nvtt/squish/extra/squishtest.cpp
Normal file
205
src/nvtt/squish/extra/squishtest.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
|
||||
@brief This program tests the error for 1 and 2-colour DXT compression.
|
||||
|
||||
This tests the effectiveness of the DXT compression algorithm for all
|
||||
possible 1 and 2-colour blocks of pixels.
|
||||
*/
|
||||
|
||||
#include <squish.h>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cfloat>
|
||||
|
||||
using namespace squish;
|
||||
|
||||
double GetColourError( u8 const* a, u8 const* b )
|
||||
{
|
||||
double error = 0.0;
|
||||
for( int i = 0; i < 16; ++i )
|
||||
{
|
||||
for( int j = 0; j < 3; ++j )
|
||||
{
|
||||
int index = 4*i + j;
|
||||
int diff = ( int )a[index] - ( int )b[index];
|
||||
error += ( double )( diff*diff );
|
||||
}
|
||||
}
|
||||
return error / 16.0;
|
||||
}
|
||||
|
||||
void TestOneColour( int flags )
|
||||
{
|
||||
u8 input[4*16];
|
||||
u8 output[4*16];
|
||||
u8 block[16];
|
||||
|
||||
double avg = 0.0, min = DBL_MAX, max = -DBL_MAX;
|
||||
int counter = 0;
|
||||
|
||||
// test all single-channel colours
|
||||
for( int i = 0; i < 16*4; ++i )
|
||||
input[i] = ( ( i % 4 ) == 3 ) ? 255 : 0;
|
||||
for( int channel = 0; channel < 3; ++channel )
|
||||
{
|
||||
for( int value = 0; value < 255; ++value )
|
||||
{
|
||||
// set the channnel value
|
||||
for( int i = 0; i < 16; ++i )
|
||||
input[4*i + channel] = ( u8 )value;
|
||||
|
||||
// compress and decompress
|
||||
Compress( input, block, flags );
|
||||
Decompress( output, block, flags );
|
||||
|
||||
// test the results
|
||||
double rm = GetColourError( input, output );
|
||||
double rms = std::sqrt( rm );
|
||||
|
||||
// accumulate stats
|
||||
min = std::min( min, rms );
|
||||
max = std::max( max, rms );
|
||||
avg += rm;
|
||||
++counter;
|
||||
}
|
||||
|
||||
// reset the channel value
|
||||
for( int i = 0; i < 16; ++i )
|
||||
input[4*i + channel] = 0;
|
||||
}
|
||||
|
||||
// finish stats
|
||||
avg = std::sqrt( avg/counter );
|
||||
|
||||
// show stats
|
||||
std::cout << "one colour error (min, max, avg): "
|
||||
<< min << ", " << max << ", " << avg << std::endl;
|
||||
}
|
||||
|
||||
void TestOneColourRandom( int flags )
|
||||
{
|
||||
u8 input[4*16];
|
||||
u8 output[4*16];
|
||||
u8 block[16];
|
||||
|
||||
double avg = 0.0, min = DBL_MAX, max = -DBL_MAX;
|
||||
int counter = 0;
|
||||
|
||||
// test all single-channel colours
|
||||
for( int test = 0; test < 1000; ++test )
|
||||
{
|
||||
// set a constant random colour
|
||||
for( int channel = 0; channel < 3; ++channel )
|
||||
{
|
||||
u8 value = ( u8 )( rand() & 0xff );
|
||||
for( int i = 0; i < 16; ++i )
|
||||
input[4*i + channel] = value;
|
||||
}
|
||||
for( int i = 0; i < 16; ++i )
|
||||
input[4*i + 3] = 255;
|
||||
|
||||
// compress and decompress
|
||||
Compress( input, block, flags );
|
||||
Decompress( output, block, flags );
|
||||
|
||||
// test the results
|
||||
double rm = GetColourError( input, output );
|
||||
double rms = std::sqrt( rm );
|
||||
|
||||
// accumulate stats
|
||||
min = std::min( min, rms );
|
||||
max = std::max( max, rms );
|
||||
avg += rm;
|
||||
++counter;
|
||||
}
|
||||
|
||||
// finish stats
|
||||
avg = std::sqrt( avg/counter );
|
||||
|
||||
// show stats
|
||||
std::cout << "random one colour error (min, max, avg): "
|
||||
<< min << ", " << max << ", " << avg << std::endl;
|
||||
}
|
||||
|
||||
void TestTwoColour( int flags )
|
||||
{
|
||||
u8 input[4*16];
|
||||
u8 output[4*16];
|
||||
u8 block[16];
|
||||
|
||||
double avg = 0.0, min = DBL_MAX, max = -DBL_MAX;
|
||||
int counter = 0;
|
||||
|
||||
// test all single-channel colours
|
||||
for( int i = 0; i < 16*4; ++i )
|
||||
input[i] = ( ( i % 4 ) == 3 ) ? 255 : 0;
|
||||
for( int channel = 0; channel < 3; ++channel )
|
||||
{
|
||||
for( int value1 = 0; value1 < 255; ++value1 )
|
||||
{
|
||||
for( int value2 = value1 + 1; value2 < 255; ++value2 )
|
||||
{
|
||||
// set the channnel value
|
||||
for( int i = 0; i < 16; ++i )
|
||||
input[4*i + channel] = ( u8 )( ( i < 8 ) ? value1 : value2 );
|
||||
|
||||
// compress and decompress
|
||||
Compress( input, block, flags );
|
||||
Decompress( output, block, flags );
|
||||
|
||||
// test the results
|
||||
double rm = GetColourError( input, output );
|
||||
double rms = std::sqrt( rm );
|
||||
|
||||
// accumulate stats
|
||||
min = std::min( min, rms );
|
||||
max = std::max( max, rms );
|
||||
avg += rm;
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
|
||||
// reset the channel value
|
||||
for( int i = 0; i < 16; ++i )
|
||||
input[4*i + channel] = 0;
|
||||
}
|
||||
|
||||
// finish stats
|
||||
avg = std::sqrt( avg/counter );
|
||||
|
||||
// show stats
|
||||
std::cout << "two colour error (min, max, avg): "
|
||||
<< min << ", " << max << ", " << avg << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TestOneColourRandom( kDxt1 | kColourRangeFit );
|
||||
TestOneColour( kDxt1 );
|
||||
TestTwoColour( kDxt1 );
|
||||
}
|
673
src/nvtt/squish/fastclusterfit.cpp
Normal file
673
src/nvtt/squish/fastclusterfit.cpp
Normal file
@ -0,0 +1,673 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
Copyright (c) 2006 Ignacio Castano icastano@nvidia.com
|
||||
|
||||
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 "fastclusterfit.h"
|
||||
#include "colourset.h"
|
||||
#include "colourblock.h"
|
||||
#include <cfloat>
|
||||
|
||||
namespace squish {
|
||||
|
||||
FastClusterFit::FastClusterFit( ColourSet const* colours, int flags ) :
|
||||
ColourFit( colours, flags )
|
||||
{
|
||||
// initialise the best error
|
||||
#if SQUISH_USE_SIMD
|
||||
m_besterror = VEC4_CONST( FLT_MAX );
|
||||
#else
|
||||
m_besterror = FLT_MAX;
|
||||
#endif
|
||||
|
||||
// cache some values
|
||||
int const count = m_colours->GetCount();
|
||||
Vec3 const* values = m_colours->GetPoints();
|
||||
|
||||
// get the covariance matrix
|
||||
Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() );
|
||||
|
||||
// compute the principle component
|
||||
Vec3 principle = ComputePrincipleComponent( covariance );
|
||||
|
||||
// build the list of values
|
||||
float dps[16];
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
dps[i] = Dot( values[i], principle );
|
||||
m_order[i] = i;
|
||||
}
|
||||
|
||||
// stable sort
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j )
|
||||
{
|
||||
std::swap( dps[j], dps[j - 1] );
|
||||
std::swap( m_order[j], m_order[j - 1] );
|
||||
}
|
||||
}
|
||||
|
||||
// weight all the points
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 const* unweighted = m_colours->GetPointsSimd();
|
||||
m_xxsum = VEC4_CONST( 0.0f );
|
||||
m_xsum = VEC4_CONST( 0.0f );
|
||||
#else
|
||||
Vec3 const* unweighted = m_colours->GetPoints();
|
||||
m_xxsum = Vec3( 0.0f );
|
||||
m_xsum = Vec3( 0.0f );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
int p = m_order[i];
|
||||
m_unweighted[i] = unweighted[p];
|
||||
m_xxsum += m_unweighted[i]*m_unweighted[i];
|
||||
m_xsum += m_unweighted[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct Precomp {
|
||||
float alpha2_sum;
|
||||
float beta2_sum;
|
||||
float alphabeta_sum;
|
||||
float factor;
|
||||
};
|
||||
|
||||
static Precomp s_threeElement[153];
|
||||
static Precomp s_fourElement[969];
|
||||
|
||||
void FastClusterFit::doPrecomputation()
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
// Three element clusters:
|
||||
for( int c0 = 0; c0 <= 16; c0++) // At least two clusters.
|
||||
{
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
int c2 = 16 - c0 - c1;
|
||||
|
||||
/*if (c2 == 16) {
|
||||
// a = b = x2 / 16
|
||||
s_threeElement[i].alpha2_sum = 0;
|
||||
s_threeElement[i].beta2_sum = 16;
|
||||
s_threeElement[i].alphabeta_sum = -16;
|
||||
s_threeElement[i].factor = 1.0f / 256.0f;
|
||||
}
|
||||
else if (c0 == 16) {
|
||||
// a = b = x0 / 16
|
||||
s_threeElement[i].alpha2_sum = 16;
|
||||
s_threeElement[i].beta2_sum = 0;
|
||||
s_threeElement[i].alphabeta_sum = -16;
|
||||
s_threeElement[i].factor = 1.0f / 256.0f;
|
||||
}
|
||||
else*/ {
|
||||
s_threeElement[i].alpha2_sum = c0 + c1 * 0.25f;
|
||||
s_threeElement[i].beta2_sum = c2 + c1 * 0.25f;
|
||||
s_threeElement[i].alphabeta_sum = c1 * 0.25f;
|
||||
s_threeElement[i].factor = 1.0f / (s_threeElement[i].alpha2_sum * s_threeElement[i].beta2_sum - s_threeElement[i].alphabeta_sum * s_threeElement[i].alphabeta_sum);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
//printf("%d three cluster elements\n", i);
|
||||
|
||||
// Four element clusters:
|
||||
i = 0;
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
for( int c2 = 0; c2 <= 16-c0-c1; c2++)
|
||||
{
|
||||
int c3 = 16 - c0 - c1 - c2;
|
||||
|
||||
/*if (c3 == 16) {
|
||||
// a = b = x3 / 16
|
||||
s_fourElement[i].alpha2_sum = 16.0f;
|
||||
s_fourElement[i].beta2_sum = 0.0f;
|
||||
s_fourElement[i].alphabeta_sum = -16.0f;
|
||||
s_fourElement[i].factor = 1.0f / 256.0f;
|
||||
}
|
||||
else if (c0 == 16) {
|
||||
// a = b = x0 / 16
|
||||
s_fourElement[i].alpha2_sum = 0.0f;
|
||||
s_fourElement[i].beta2_sum = 16.0f;
|
||||
s_fourElement[i].alphabeta_sum = -16.0f;
|
||||
s_fourElement[i].factor = 1.0f / 256.0f;
|
||||
}
|
||||
else*/ {
|
||||
s_fourElement[i].alpha2_sum = c0 + c1 * (4.0f/9.0f) + c2 * (1.0f/9.0f);
|
||||
s_fourElement[i].beta2_sum = c3 + c2 * (4.0f/9.0f) + c1 * (1.0f/9.0f);
|
||||
s_fourElement[i].alphabeta_sum = (c1 + c2) * (2.0f/9.0f);
|
||||
s_fourElement[i].factor = 1.0f / (s_fourElement[i].alpha2_sum * s_fourElement[i].beta2_sum - s_fourElement[i].alphabeta_sum * s_fourElement[i].alphabeta_sum);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf("%d four cluster elements\n", i);
|
||||
}
|
||||
|
||||
void FastClusterFit::setMetric(float r, float g, float b)
|
||||
{
|
||||
#if SQUISH_USE_SIMD
|
||||
m_metric = Vec4(r, g, b, 0);
|
||||
#else
|
||||
m_metric = Vec3(r, g, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
float FastClusterFit::bestError() const
|
||||
{
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 x = m_xxsum * m_metric;
|
||||
Vec4 error = m_besterror + x.SplatX() + x.SplatY() + x.SplatZ();
|
||||
return error.GetVec3().X();
|
||||
#else
|
||||
return m_besterror + Dot(m_xxsum, m_metric);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if SQUISH_USE_SIMD
|
||||
|
||||
void FastClusterFit::Compress3( void* block )
|
||||
{
|
||||
Vec4 const one = VEC4_CONST(1.0f);
|
||||
Vec4 const zero = VEC4_CONST(0.0f);
|
||||
Vec4 const half = VEC4_CONST(0.5f);
|
||||
Vec4 const two = VEC4_CONST(2.0);
|
||||
|
||||
// declare variables
|
||||
Vec4 beststart = VEC4_CONST( 0.0f );
|
||||
Vec4 bestend = VEC4_CONST( 0.0f );
|
||||
Vec4 besterror = VEC4_CONST( FLT_MAX );
|
||||
|
||||
Vec4 x0 = zero;
|
||||
Vec4 x1;
|
||||
int b0 = 0, b1 = 0;
|
||||
int i = 0;
|
||||
|
||||
// check all possible clusters for this total order
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
x1 = zero;
|
||||
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
Vec4 const alpha2_sum = VEC4_CONST(s_threeElement[i].alpha2_sum);
|
||||
Vec4 const beta2_sum = VEC4_CONST(s_threeElement[i].beta2_sum);
|
||||
Vec4 const alphabeta_sum = VEC4_CONST(s_threeElement[i].alphabeta_sum);
|
||||
Vec4 const factor = VEC4_CONST(s_threeElement[i].factor);
|
||||
i++;
|
||||
|
||||
Vec4 const alphax_sum = MultiplyAdd(half, x1, x0);
|
||||
Vec4 const betax_sum = m_xsum - alphax_sum;
|
||||
|
||||
Vec4 a = NegativeMultiplySubtract(betax_sum, alphabeta_sum, alphax_sum*beta2_sum) * factor;
|
||||
Vec4 b = NegativeMultiplySubtract(alphax_sum, alphabeta_sum, betax_sum*alpha2_sum) * factor;
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
|
||||
Vec4 const gridrcp( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f, 0.0f );
|
||||
a = Truncate( MultiplyAdd( grid, a, half ) ) * gridrcp;
|
||||
b = Truncate( MultiplyAdd( grid, b, half ) ) * gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec4 e1 = MultiplyAdd( a, alphax_sum, b*betax_sum );
|
||||
Vec4 e2 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
|
||||
Vec4 e3 = MultiplyAdd( a*b*alphabeta_sum - e1, two, e2 );
|
||||
|
||||
// apply the metric to the error term
|
||||
Vec4 e4 = e3 * m_metric;
|
||||
Vec4 error = e4.SplatX() + e4.SplatY() + e4.SplatZ();
|
||||
|
||||
// keep the solution if it wins
|
||||
if( CompareAnyLessThan( error, besterror ) )
|
||||
{
|
||||
besterror = error;
|
||||
beststart = a;
|
||||
bestend = b;
|
||||
b0 = c0;
|
||||
b1 = c1;
|
||||
}
|
||||
|
||||
x1 += m_unweighted[c0+c1];
|
||||
}
|
||||
|
||||
x0 += m_unweighted[c0];
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
if( CompareAnyLessThan( besterror, m_besterror ) )
|
||||
{
|
||||
// compute indices from cluster sizes.
|
||||
/*uint bestindices = 0;
|
||||
{
|
||||
int i = b0;
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices |= 2 << (2 * i);
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices |= 1 << (2 * i);
|
||||
}
|
||||
}*/
|
||||
u8 bestindices[16];
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < b0; i++) {
|
||||
bestindices[i] = 0;
|
||||
}
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices[i] = 2;
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 ordered[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
ordered[m_order[i]] = bestindices[i];
|
||||
|
||||
// save the block
|
||||
WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), ordered, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
void FastClusterFit::Compress4( void* block )
|
||||
{
|
||||
Vec4 const one = VEC4_CONST(1.0f);
|
||||
Vec4 const zero = VEC4_CONST(0.0f);
|
||||
Vec4 const half = VEC4_CONST(0.5f);
|
||||
Vec4 const two = VEC4_CONST(2.0);
|
||||
Vec4 const onethird = VEC4_CONST( 1.0f/3.0f );
|
||||
Vec4 const twothirds = VEC4_CONST( 2.0f/3.0f );
|
||||
|
||||
// declare variables
|
||||
Vec4 beststart = VEC4_CONST( 0.0f );
|
||||
Vec4 bestend = VEC4_CONST( 0.0f );
|
||||
Vec4 besterror = VEC4_CONST( FLT_MAX );
|
||||
|
||||
Vec4 x0 = zero;
|
||||
int b0 = 0, b1 = 0, b2 = 0;
|
||||
int i = 0;
|
||||
|
||||
// check all possible clusters for this total order
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
Vec4 x1 = zero;
|
||||
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
Vec4 x2 = zero;
|
||||
|
||||
for( int c2 = 0; c2 <= 16-c0-c1; c2++)
|
||||
{
|
||||
Vec4 const alpha2_sum = VEC4_CONST(s_fourElement[i].alpha2_sum);
|
||||
Vec4 const beta2_sum = VEC4_CONST(s_fourElement[i].beta2_sum);
|
||||
Vec4 const alphabeta_sum = VEC4_CONST(s_fourElement[i].alphabeta_sum);
|
||||
Vec4 const factor = VEC4_CONST(s_fourElement[i].factor);
|
||||
i++;
|
||||
|
||||
Vec4 const alphax_sum = x0 + MultiplyAdd(x1, twothirds, x2 * onethird);
|
||||
Vec4 const betax_sum = m_xsum - alphax_sum;
|
||||
|
||||
Vec4 a = NegativeMultiplySubtract(betax_sum, alphabeta_sum, alphax_sum*beta2_sum) * factor;
|
||||
Vec4 b = NegativeMultiplySubtract(alphax_sum, alphabeta_sum, betax_sum*alpha2_sum) * factor;
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
|
||||
Vec4 const gridrcp( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f, 0.0f );
|
||||
a = Truncate( MultiplyAdd( grid, a, half ) ) * gridrcp;
|
||||
b = Truncate( MultiplyAdd( grid, b, half ) ) * gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec4 e1 = MultiplyAdd( a, alphax_sum, b*betax_sum );
|
||||
Vec4 e2 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
|
||||
Vec4 e3 = MultiplyAdd( a*b*alphabeta_sum - e1, two, e2 );
|
||||
|
||||
// apply the metric to the error term
|
||||
Vec4 e4 = e3 * m_metric;
|
||||
Vec4 error = e4.SplatX() + e4.SplatY() + e4.SplatZ();
|
||||
|
||||
// keep the solution if it wins
|
||||
if( CompareAnyLessThan( error, besterror ) )
|
||||
{
|
||||
besterror = error;
|
||||
beststart = a;
|
||||
bestend = b;
|
||||
b0 = c0;
|
||||
b1 = c1;
|
||||
b2 = c2;
|
||||
}
|
||||
|
||||
x2 += m_unweighted[c0+c1+c2];
|
||||
}
|
||||
|
||||
x1 += m_unweighted[c0+c1];
|
||||
}
|
||||
|
||||
x0 += m_unweighted[c0];
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
if( CompareAnyLessThan( besterror, m_besterror ) )
|
||||
{
|
||||
// compute indices from cluster sizes.
|
||||
/*uint bestindices = 0;
|
||||
{
|
||||
int i = b0;
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices = 2 << (2 * m_order[i]);
|
||||
}
|
||||
for(; i < b0+b1+b2; i++) {
|
||||
bestindices = 3 << (2 * m_order[i]);
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices = 1 << (2 * m_order[i]);
|
||||
}
|
||||
}*/
|
||||
u8 bestindices[16];
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < b0; i++) {
|
||||
bestindices[i] = 0;
|
||||
}
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices[i] = 2;
|
||||
}
|
||||
for(; i < b0+b1+b2; i++) {
|
||||
bestindices[i] = 3;
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 ordered[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
ordered[m_order[i]] = bestindices[i];
|
||||
|
||||
// save the block
|
||||
WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), ordered, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void FastClusterFit::Compress3( void* block )
|
||||
{
|
||||
// declare variables
|
||||
Vec3 beststart( 0.0f );
|
||||
Vec3 bestend( 0.0f );
|
||||
float besterror = FLT_MAX;
|
||||
|
||||
Vec3 x0(0.0f);
|
||||
Vec3 x1;
|
||||
int b0 = 0, b1 = 0;
|
||||
int i = 0;
|
||||
|
||||
// check all possible clusters for this total order
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
x1 = Vec3(0);
|
||||
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
float const alpha2_sum = s_threeElement[i].alpha2_sum;
|
||||
float const beta2_sum = s_threeElement[i].beta2_sum;
|
||||
float const alphabeta_sum = s_threeElement[i].alphabeta_sum;
|
||||
float const factor = s_threeElement[i].factor;
|
||||
i++;
|
||||
|
||||
Vec3 const alphax_sum = x0 + x1 * 0.5f;
|
||||
Vec3 const betax_sum = m_xsum - alphax_sum;
|
||||
|
||||
Vec3 a = (alphax_sum*beta2_sum - betax_sum*alphabeta_sum) * factor;
|
||||
Vec3 b = (betax_sum*alpha2_sum - alphax_sum*alphabeta_sum) * factor;
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
Vec3 const one( 1.0f );
|
||||
Vec3 const zero( 0.0f );
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
Vec3 const grid( 31.0f, 63.0f, 31.0f );
|
||||
Vec3 const gridrcp( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f );
|
||||
Vec3 const half( 0.5f );
|
||||
a = Floor( grid*a + half )*gridrcp;
|
||||
b = Floor( grid*b + half )*gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec3 e1 = a*a*alpha2_sum + b*b*beta2_sum + 2.0f*( a*b*alphabeta_sum - a*alphax_sum - b*betax_sum );
|
||||
|
||||
// apply the metric to the error term
|
||||
float error = Dot( e1, m_metric );
|
||||
|
||||
// keep the solution if it wins
|
||||
if( error < besterror )
|
||||
{
|
||||
besterror = error;
|
||||
beststart = a;
|
||||
bestend = b;
|
||||
b0 = c0;
|
||||
b1 = c1;
|
||||
}
|
||||
|
||||
x1 += m_unweighted[c0+c1];
|
||||
}
|
||||
|
||||
x0 += m_unweighted[c0];
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
if( besterror < m_besterror )
|
||||
{
|
||||
// compute indices from cluster sizes.
|
||||
/*uint bestindices = 0;
|
||||
{
|
||||
int i = b0;
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices |= 2 << (2 * m_order[i]);
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices |= 1 << (2 * m_order[i]);
|
||||
}
|
||||
}*/
|
||||
u8 bestindices[16];
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < b0; i++) {
|
||||
bestindices[i] = 0;
|
||||
}
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices[i] = 2;
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 ordered[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
ordered[m_order[i]] = bestindices[i];
|
||||
|
||||
// save the block
|
||||
WriteColourBlock3( beststart, bestend, ordered, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
void FastClusterFit::Compress4( void* block )
|
||||
{
|
||||
// declare variables
|
||||
Vec3 beststart( 0.0f );
|
||||
Vec3 bestend( 0.0f );
|
||||
float besterror = FLT_MAX;
|
||||
|
||||
Vec3 x0(0.0f);
|
||||
Vec3 x1;
|
||||
Vec3 x2;
|
||||
int b0 = 0, b1 = 0, b2 = 0;
|
||||
int i = 0;
|
||||
|
||||
// check all possible clusters for this total order
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
x1 = Vec3(0.0f);
|
||||
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
x2 = Vec3(0.0f);
|
||||
|
||||
for( int c2 = 0; c2 <= 16-c0-c1; c2++)
|
||||
{
|
||||
float const alpha2_sum = s_fourElement[i].alpha2_sum;
|
||||
float const beta2_sum = s_fourElement[i].beta2_sum;
|
||||
float const alphabeta_sum = s_fourElement[i].alphabeta_sum;
|
||||
float const factor = s_fourElement[i].factor;
|
||||
i++;
|
||||
|
||||
Vec3 const alphax_sum = x0 + x1 * (2.0f / 3.0f) + x2 * (1.0f / 3.0f);
|
||||
Vec3 const betax_sum = m_xsum - alphax_sum;
|
||||
|
||||
Vec3 a = ( alphax_sum*beta2_sum - betax_sum*alphabeta_sum )*factor;
|
||||
Vec3 b = ( betax_sum*alpha2_sum - alphax_sum*alphabeta_sum )*factor;
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
Vec3 const one( 1.0f );
|
||||
Vec3 const zero( 0.0f );
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
Vec3 const grid( 31.0f, 63.0f, 31.0f );
|
||||
Vec3 const gridrcp( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f );
|
||||
Vec3 const half( 0.5f );
|
||||
a = Floor( grid*a + half )*gridrcp;
|
||||
b = Floor( grid*b + half )*gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec3 e1 = a*a*alpha2_sum + b*b*beta2_sum + 2.0f*( a*b*alphabeta_sum - a*alphax_sum - b*betax_sum );
|
||||
|
||||
// apply the metric to the error term
|
||||
float error = Dot( e1, m_metric );
|
||||
|
||||
// keep the solution if it wins
|
||||
if( error < besterror )
|
||||
{
|
||||
besterror = error;
|
||||
beststart = a;
|
||||
bestend = b;
|
||||
b0 = c0;
|
||||
b1 = c1;
|
||||
b2 = c2;
|
||||
}
|
||||
|
||||
x2 += m_unweighted[c0+c1+c2];
|
||||
}
|
||||
|
||||
x1 += m_unweighted[c0+c1];
|
||||
}
|
||||
|
||||
x0 += m_unweighted[c0];
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
if( besterror < m_besterror )
|
||||
{
|
||||
// compute indices from cluster sizes.
|
||||
/*uint bestindices = 0;
|
||||
{
|
||||
int i = b0;
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices = 2 << (2 * m_order[i]);
|
||||
}
|
||||
for(; i < b0+b1+b2; i++) {
|
||||
bestindices = 3 << (2 * m_order[i]);
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices = 1 << (2 * m_order[i]);
|
||||
}
|
||||
}*/
|
||||
u8 bestindices[16];
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < b0; i++) {
|
||||
bestindices[i] = 0;
|
||||
}
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices[i] = 2;
|
||||
}
|
||||
for(; i < b0+b1+b2; i++) {
|
||||
bestindices[i] = 3;
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 ordered[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
ordered[m_order[i]] = bestindices[i];
|
||||
|
||||
// save the block
|
||||
WriteColourBlock4( beststart, bestend, ordered, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace squish
|
74
src/nvtt/squish/fastclusterfit.h
Normal file
74
src/nvtt/squish/fastclusterfit.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
Copyright (c) 2006 Ignacio Castano icastano@nvidia.com
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_FASTCLUSTERFIT_H
|
||||
#define SQUISH_FASTCLUSTERFIT_H
|
||||
|
||||
#include "squish.h"
|
||||
#include "maths.h"
|
||||
#include "simd.h"
|
||||
#include "colourfit.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
class FastClusterFit : public ColourFit
|
||||
{
|
||||
public:
|
||||
FastClusterFit( ColourSet const* colours, int flags );
|
||||
|
||||
void setMetric(float r, float g, float b);
|
||||
float bestError() const;
|
||||
|
||||
static void doPrecomputation();
|
||||
|
||||
// Make them public
|
||||
virtual void Compress3( void* block );
|
||||
virtual void Compress4( void* block );
|
||||
|
||||
private:
|
||||
|
||||
Vec3 m_principle;
|
||||
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 m_unweighted[16];
|
||||
Vec4 m_metric;
|
||||
Vec4 m_xxsum;
|
||||
Vec4 m_xsum;
|
||||
Vec4 m_besterror;
|
||||
#else
|
||||
Vec3 m_unweighted[16];
|
||||
Vec3 m_metric;
|
||||
Vec3 m_xxsum;
|
||||
Vec3 m_xsum;
|
||||
float m_besterror;
|
||||
#endif
|
||||
|
||||
int m_order[16];
|
||||
};
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_FASTCLUSTERFIT_H
|
252
src/nvtt/squish/maths.cpp
Normal file
252
src/nvtt/squish/maths.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#include "maths.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;
|
||||
}
|
||||
|
||||
/*
|
||||
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] );
|
||||
}
|
||||
}
|
||||
|
||||
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] );
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
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 );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Vec3 ComputePrincipleComponent( Sym3x3 const& matrix )
|
||||
{
|
||||
const int NUM = 8;
|
||||
|
||||
Vec3 v(1, 1, 1);
|
||||
for(int i = 0; i < NUM; i++) {
|
||||
float x = v.X() * matrix[0] + v.Y() * matrix[1] + v.Z() * matrix[2];
|
||||
float y = v.X() * matrix[1] + v.Y() * matrix[3] + v.Z() * matrix[4];
|
||||
float z = v.X() * matrix[2] + v.Y() * matrix[4] + v.Z() * matrix[5];
|
||||
|
||||
float norm = std::max(std::max(x, y), z);
|
||||
float iv = 1.0f / norm;
|
||||
if (norm == 0.0f) { // @@ I think this is not necessary in this case!!
|
||||
return Vec3(0.0f);
|
||||
}
|
||||
|
||||
v = Vec3(x*iv, y*iv, z*iv);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
} // namespace squish
|
239
src/nvtt/squish/maths.h
Normal file
239
src/nvtt/squish/maths.h
Normal file
@ -0,0 +1,239 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_MATHS_H
|
||||
#define SQUISH_MATHS_H
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "config.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
class Vec3
|
||||
{
|
||||
public:
|
||||
typedef Vec3 const& Arg;
|
||||
|
||||
Vec3()
|
||||
{
|
||||
}
|
||||
|
||||
explicit Vec3( float a )
|
||||
{
|
||||
m_x = a;
|
||||
m_y = a;
|
||||
m_z = a;
|
||||
}
|
||||
|
||||
Vec3( float a, float b, float c )
|
||||
{
|
||||
m_x = a;
|
||||
m_y = b;
|
||||
m_z = c;
|
||||
}
|
||||
|
||||
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, float right )
|
||||
{
|
||||
Vec3 copy( left );
|
||||
return copy += Vec3(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 Floor( Arg v )
|
||||
{
|
||||
return Vec3(
|
||||
std::floor( v.m_x ),
|
||||
std::floor( v.m_y ),
|
||||
std::floor( v.m_z )
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
float m_x;
|
||||
float m_y;
|
||||
float m_z;
|
||||
};
|
||||
|
||||
inline float LengthSquared( Vec3::Arg v )
|
||||
{
|
||||
return Dot( v, v );
|
||||
}
|
||||
|
||||
class Sym3x3
|
||||
{
|
||||
public:
|
||||
Sym3x3()
|
||||
{
|
||||
}
|
||||
|
||||
Sym3x3( float a )
|
||||
{
|
||||
for( int i = 0; i < 6; ++i )
|
||||
m_x[i] = a;
|
||||
}
|
||||
|
||||
float operator[]( int index ) const
|
||||
{
|
||||
return m_x[index];
|
||||
}
|
||||
|
||||
float& operator[]( int index )
|
||||
{
|
||||
return m_x[index];
|
||||
}
|
||||
|
||||
private:
|
||||
float m_x[6];
|
||||
};
|
||||
|
||||
Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights );
|
||||
Vec3 ComputePrincipleComponent( Sym3x3 const& matrix );
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_MATHS_H
|
202
src/nvtt/squish/rangefit.cpp
Normal file
202
src/nvtt/squish/rangefit.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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 "rangefit.h"
|
||||
#include "colourset.h"
|
||||
#include "colourblock.h"
|
||||
#include <cfloat>
|
||||
|
||||
namespace squish {
|
||||
|
||||
RangeFit::RangeFit( ColourSet const* colours, int flags )
|
||||
: ColourFit( colours, flags )
|
||||
{
|
||||
// initialise the metric
|
||||
bool perceptual = ( ( m_flags & kColourMetricPerceptual ) != 0 );
|
||||
if( perceptual )
|
||||
m_metric = Vec3( 0.2126f, 0.7152f, 0.0722f );
|
||||
else
|
||||
m_metric = Vec3( 1.0f );
|
||||
|
||||
// initialise the best error
|
||||
m_besterror = FLT_MAX;
|
||||
|
||||
// cache some values
|
||||
int const count = m_colours->GetCount();
|
||||
Vec3 const* values = m_colours->GetPoints();
|
||||
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
|
||||
Vec3 start( 0.0f );
|
||||
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 = Floor( grid*start + half )*gridrcp;
|
||||
m_end = Floor( grid*end + half )*gridrcp;
|
||||
}
|
||||
|
||||
void RangeFit::Compress3( void* block )
|
||||
{
|
||||
// cache some values
|
||||
int const count = m_colours->GetCount();
|
||||
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
|
||||
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 < 3; ++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
|
||||
WriteColourBlock3( m_start, m_end, indices, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = error;
|
||||
}
|
||||
}
|
||||
|
||||
void RangeFit::Compress4( void* block )
|
||||
{
|
||||
// cache some values
|
||||
int const count = m_colours->GetCount();
|
||||
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
|
||||
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
|
54
src/nvtt/squish/rangefit.h
Normal file
54
src/nvtt/squish/rangefit.h
Normal file
@ -0,0 +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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_RANGEFIT_H
|
||||
#define SQUISH_RANGEFIT_H
|
||||
|
||||
#include <squish.h>
|
||||
#include "colourfit.h"
|
||||
#include "maths.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
class ColourSet;
|
||||
|
||||
class RangeFit : public ColourFit
|
||||
{
|
||||
public:
|
||||
RangeFit( ColourSet const* colours, int flags );
|
||||
|
||||
private:
|
||||
virtual void Compress3( void* block );
|
||||
virtual void Compress4( void* block );
|
||||
|
||||
Vec3 m_metric;
|
||||
Vec3 m_start;
|
||||
Vec3 m_end;
|
||||
float m_besterror;
|
||||
};
|
||||
|
||||
} // squish
|
||||
|
||||
#endif // ndef SQUISH_RANGEFIT_H
|
39
src/nvtt/squish/simd.h
Normal file
39
src/nvtt/squish/simd.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_SIMD_H
|
||||
#define SQUISH_SIMD_H
|
||||
|
||||
#include "maths.h"
|
||||
|
||||
#if SQUISH_USE_ALTIVEC
|
||||
#include "simd_ve.h"
|
||||
#endif
|
||||
|
||||
#if SQUISH_USE_SSE
|
||||
#include "simd_sse.h"
|
||||
#endif
|
||||
|
||||
#endif // ndef SQUISH_SIMD_H
|
192
src/nvtt/squish/simd_sse.h
Normal file
192
src/nvtt/squish/simd_sse.h
Normal file
@ -0,0 +1,192 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_SIMD_SSE_H
|
||||
#define SQUISH_SIMD_SSE_H
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#if ( SQUISH_USE_SSE > 1 )
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#include <cassert>
|
||||
|
||||
#define SQUISH_SSE_SPLAT( a ) \
|
||||
( ( a ) | ( ( a ) << 2 ) | ( ( a ) << 4 ) | ( ( a ) << 6 ) )
|
||||
|
||||
namespace squish {
|
||||
|
||||
#define VEC4_CONST( X ) Vec4( _mm_set1_ps( X ) )
|
||||
|
||||
class Vec4
|
||||
{
|
||||
public:
|
||||
typedef Vec4 const& Arg;
|
||||
|
||||
Vec4() {}
|
||||
|
||||
explicit Vec4( __m128 v ) : m_v( v ) {}
|
||||
|
||||
Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {}
|
||||
|
||||
Vec4& operator=( Vec4 const& arg )
|
||||
{
|
||||
m_v = arg.m_v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vec4( float x, float y, float z, float w )
|
||||
{
|
||||
m_v = _mm_setr_ps( x, y, z, w );
|
||||
}
|
||||
|
||||
Vec3 GetVec3() const
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((__aligned__ (16))) float c[4];
|
||||
#else
|
||||
__declspec(align(16)) float c[4];
|
||||
#endif
|
||||
_mm_store_ps( c, m_v );
|
||||
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 )
|
||||
{
|
||||
m_v = _mm_add_ps( m_v, v.m_v );
|
||||
return *this;
|
||||
}
|
||||
|
||||
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
|
||||
__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 )
|
||||
// convert to ints
|
||||
__m128 input = v.m_v;
|
||||
__m64 lo = _mm_cvttps_pi32( input );
|
||||
__m64 hi = _mm_cvttps_pi32( _mm_movehl_ps( input, input ) );
|
||||
|
||||
// convert to floats
|
||||
__m128 part = _mm_movelh_ps( input, _mm_cvtpi32_ps( input, hi ) );
|
||||
__m128 truncated = _mm_cvtpi32_ps( part, lo );
|
||||
|
||||
// clear out the MMX multimedia state to allow FP calls later
|
||||
_mm_empty();
|
||||
return Vec4( truncated );
|
||||
#else
|
||||
// use SSE2 instructions
|
||||
return Vec4( _mm_cvtepi32_ps( _mm_cvttps_epi32( v.m_v ) ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
friend Vec4 CompareEqual( Vec4::Arg left, Vec4::Arg right )
|
||||
{
|
||||
return Vec4( _mm_cmpeq_ps( left.m_v, right.m_v ) );
|
||||
}
|
||||
|
||||
friend Vec4 Select( Vec4::Arg off, Vec4::Arg on, Vec4::Arg bits )
|
||||
{
|
||||
__m128 a = _mm_andnot_ps( bits.m_v, off.m_v );
|
||||
__m128 b = _mm_and_ps( bits.m_v, on.m_v );
|
||||
|
||||
return Vec4( _mm_or_ps( a, b ) );
|
||||
}
|
||||
|
||||
friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right )
|
||||
{
|
||||
__m128 bits = _mm_cmplt_ps( left.m_v, right.m_v );
|
||||
int value = _mm_movemask_ps( bits );
|
||||
return value != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
__m128 m_v;
|
||||
};
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_SIMD_SSE_H
|
166
src/nvtt/squish/simd_ve.h
Normal file
166
src/nvtt/squish/simd_ve.h
Normal file
@ -0,0 +1,166 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_SIMD_VE_H
|
||||
#define SQUISH_SIMD_VE_H
|
||||
|
||||
#include <altivec.h>
|
||||
#undef bool
|
||||
|
||||
namespace squish {
|
||||
|
||||
#define VEC4_CONST( X ) Vec4( ( vector float )( X ) )
|
||||
|
||||
class Vec4
|
||||
{
|
||||
public:
|
||||
typedef Vec4 Arg;
|
||||
|
||||
Vec4() {}
|
||||
|
||||
explicit Vec4( vector float v ) : m_v( v ) {}
|
||||
|
||||
Vec4( Vec4 const& arg ) : m_v( arg.m_v ) {}
|
||||
|
||||
Vec4& operator=( Vec4 const& arg )
|
||||
{
|
||||
m_v = arg.m_v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vec4( float x, float y, float z, float w )
|
||||
{
|
||||
union { vector float v; float c[4]; } u;
|
||||
u.c[0] = x;
|
||||
u.c[1] = y;
|
||||
u.c[2] = z;
|
||||
u.c[3] = w;
|
||||
m_v = u.v;
|
||||
}
|
||||
|
||||
Vec3 GetVec3() const
|
||||
{
|
||||
union { vector float v; float c[4]; } u;
|
||||
u.v = m_v;
|
||||
return Vec3( u.c[0], u.c[1], u.c[2] );
|
||||
}
|
||||
|
||||
Vec4 SplatX() const { return Vec4( vec_splat( m_v, 0 ) ); }
|
||||
Vec4 SplatY() const { return Vec4( vec_splat( m_v, 1 ) ); }
|
||||
Vec4 SplatZ() const { return Vec4( vec_splat( m_v, 2 ) ); }
|
||||
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 Vec4 CompareEqual( Vec4::Arg left, Vec4::Arg right )
|
||||
{
|
||||
return Vec4( ( vector float )vec_cmpeq( left.m_v, right.m_v ) );
|
||||
}
|
||||
|
||||
friend Vec4 Select( Vec4::Arg off, Vec4::Arg on, Vec4::Arg bits )
|
||||
{
|
||||
return Vec4( vec_sel( off.m_v, on.m_v, ( vector unsigned int )bits.m_v ) );
|
||||
}
|
||||
|
||||
friend bool CompareAnyLessThan( Vec4::Arg left, Vec4::Arg right )
|
||||
{
|
||||
return vec_any_lt( left.m_v, right.m_v ) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
vector float m_v;
|
||||
};
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_SIMD_VE_H
|
144
src/nvtt/squish/singlechannelfit.cpp
Normal file
144
src/nvtt/squish/singlechannelfit.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
Copyright (c) 2006 Ignacio Castano castanyo@yahoo.es
|
||||
|
||||
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 "singlechannelfit.h"
|
||||
#include "colourset.h"
|
||||
#include "colourblock.h"
|
||||
#include <cfloat>
|
||||
|
||||
namespace squish {
|
||||
|
||||
SingleChannelFit::SingleChannelFit( ColourSet const* colours, int const flags )
|
||||
: ColourFit( colours, flags )
|
||||
{
|
||||
// cache some values
|
||||
int const count = m_colours->GetCount();
|
||||
Vec3 const* values = m_colours->GetPoints();
|
||||
|
||||
// Find bounds of the search space.
|
||||
m_g_min = 63;
|
||||
m_g_max = 0;
|
||||
|
||||
for(uint i = 0; i < count; i++) {
|
||||
|
||||
int grey = int(values[i].Y() * 255.0f); // @@ rounding?
|
||||
grey = std::min(grey, 255); // clamp to [0, 1)
|
||||
grey = std::max(grey, 0);
|
||||
m_greys[i] = u8(grey);
|
||||
|
||||
m_g_min = std::min(m_g_min, grey >> 2);
|
||||
m_g_max = std::max(m_g_max, grey >> 2);
|
||||
}
|
||||
|
||||
int const g_pad = m_g_max - m_g_min + 1;
|
||||
|
||||
m_g_min = std::max(0, m_g_min - g_pad);
|
||||
m_g_max = std::min(63, m_g_max + g_pad);
|
||||
}
|
||||
|
||||
void SingleChannelFit::Compress3( void* block )
|
||||
{
|
||||
// do not do anything.
|
||||
}
|
||||
|
||||
void SingleChannelFit::Compress4( void* block )
|
||||
{
|
||||
int const count = m_colours->GetCount();
|
||||
Vec3 const* values = m_colours->GetPoints();
|
||||
float const* weights = m_colours->GetWeights();
|
||||
|
||||
int best_g0;
|
||||
int best_g1;
|
||||
float best_error = FLT_MAX;
|
||||
|
||||
// Brute force approach, try all the possible endpoints with g0 > g1.
|
||||
for(int g0 = m_g_min+1; g0 <= m_g_max; g0++) {
|
||||
for(int g1 = m_g_min; g1 < g0; g1++) {
|
||||
|
||||
// Compute palette.
|
||||
const int c0 = (g0 << 2) | (g0 >> 4);
|
||||
const int c1 = (g1 << 2) | (g1 >> 4);
|
||||
const int c2 = (2 * c0 + c1) / 3;
|
||||
const int c3 = (2 * c1 + c0) / 3;
|
||||
|
||||
// Evaluate palette error.
|
||||
float error = 0;
|
||||
for(int i = 0; i < count; i++) {
|
||||
const int grey = m_greys[i];
|
||||
|
||||
int min_dist = abs(c0 - grey); // Use absolute distance, not squared.
|
||||
min_dist = std::min(min_dist, abs(c1 - grey));
|
||||
min_dist = std::min(min_dist, abs(c2 - grey));
|
||||
min_dist = std::min(min_dist, abs(c3 - grey));
|
||||
|
||||
error += min_dist * weights[i];
|
||||
}
|
||||
|
||||
if(error < best_error) {
|
||||
best_error = error;
|
||||
best_g0 = g0;
|
||||
best_g1 = g1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute best palette.
|
||||
const int best_c0 = (best_g0 << 2) | (best_g0 >> 4);
|
||||
const int best_c1 = (best_g1 << 2) | (best_g1 >> 4);
|
||||
const int best_c2 = (2 * best_c0 + best_c1) / 3;
|
||||
const int best_c3 = (2 * best_c1 + best_c0) / 3;
|
||||
|
||||
// Compute best indices.
|
||||
u8 closest[16];
|
||||
for(int i = 0; i < count; i++) {
|
||||
const int grey = m_greys[i];
|
||||
|
||||
int dist = abs(best_c0 - grey);
|
||||
int min_dist = dist;
|
||||
int min_i = 0;
|
||||
|
||||
dist = abs(best_c1 - grey);
|
||||
if( dist < min_dist ) { min_dist = dist; min_i = 1; }
|
||||
|
||||
dist = abs(best_c2 - grey);
|
||||
if( dist < min_dist ) { min_dist = dist; min_i = 2; }
|
||||
|
||||
dist = abs(best_c3 - grey);
|
||||
if( dist < min_dist ) { min_dist = dist; min_i = 3; }
|
||||
|
||||
closest[i] = min_i;
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 indices[16];
|
||||
m_colours->RemapIndices( closest, indices );
|
||||
|
||||
// Output block.
|
||||
WriteColourBlock(best_g0 << 5, best_g1 << 5, indices, block);
|
||||
}
|
||||
|
||||
|
||||
} // namespace squish
|
53
src/nvtt/squish/singlechannelfit.h
Normal file
53
src/nvtt/squish/singlechannelfit.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
Copyright (c) 2006 Ignacio Castano castanyo@yahoo.es
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_SINGLECHANNELFIT_H
|
||||
#define SQUISH_SINGLECHANNELFIT_H
|
||||
|
||||
#include <squish.h>
|
||||
#include "maths.h"
|
||||
#include "colourfit.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
class SingleChannelFit : public ColourFit
|
||||
{
|
||||
public:
|
||||
SingleChannelFit( ColourSet const* colours, int flags );
|
||||
|
||||
private:
|
||||
virtual void Compress3( void* block );
|
||||
virtual void Compress4( void* block );
|
||||
|
||||
private:
|
||||
u8 m_greys[16];
|
||||
int m_g_min;
|
||||
int m_g_max;
|
||||
};
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_SINGLECHANNELFIT_H
|
172
src/nvtt/squish/singlecolourfit.cpp
Normal file
172
src/nvtt/squish/singlecolourfit.cpp
Normal file
@ -0,0 +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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#include "singlecolourfit.h"
|
||||
#include "colourset.h"
|
||||
#include "colourblock.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
struct SourceBlock
|
||||
{
|
||||
u8 start;
|
||||
u8 end;
|
||||
u8 error;
|
||||
};
|
||||
|
||||
struct SingleColourLookup
|
||||
{
|
||||
SourceBlock sources[4];
|
||||
};
|
||||
|
||||
#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 );
|
||||
|
||||
// clamp to the limit
|
||||
if( i < 0 )
|
||||
i = 0;
|
||||
else if( i > limit )
|
||||
i = limit;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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( 3, 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( 4, 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( int count, SingleColourLookup const* const* lookups )
|
||||
{
|
||||
// check each index combination
|
||||
m_error = INT_MAX;
|
||||
for( int index = 0; index < count; ++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 )index;
|
||||
m_error = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace squish
|
58
src/nvtt/squish/singlecolourfit.h
Normal file
58
src/nvtt/squish/singlecolourfit.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_SINGLECOLOURFIT_H
|
||||
#define SQUISH_SINGLECOLOURFIT_H
|
||||
|
||||
#include <squish.h>
|
||||
#include "colourfit.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
class ColourSet;
|
||||
struct SingleColourLookup;
|
||||
|
||||
class SingleColourFit : public ColourFit
|
||||
{
|
||||
public:
|
||||
SingleColourFit( ColourSet const* colours, int flags );
|
||||
|
||||
private:
|
||||
virtual void Compress3( void* block );
|
||||
virtual void Compress4( void* block );
|
||||
|
||||
void ComputeEndPoints( int count, SingleColourLookup const* const* lookups );
|
||||
|
||||
u8 m_colour[3];
|
||||
Vec3 m_start;
|
||||
Vec3 m_end;
|
||||
u8 m_index;
|
||||
int m_error;
|
||||
int m_besterror;
|
||||
};
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_SINGLECOLOURFIT_H
|
1040
src/nvtt/squish/singlecolourlookup.inl
Normal file
1040
src/nvtt/squish/singlecolourlookup.inl
Normal file
File diff suppressed because it is too large
Load Diff
225
src/nvtt/squish/squish.cpp
Normal file
225
src/nvtt/squish/squish.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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 <squish.h>
|
||||
#include "colourset.h"
|
||||
#include "maths.h"
|
||||
#include "rangefit.h"
|
||||
#include "clusterfit.h"
|
||||
#include "colourblock.h"
|
||||
#include "alpha.h"
|
||||
#include "singlecolourfit.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
static int FixFlags( int flags )
|
||||
{
|
||||
// grab the flag bits
|
||||
int method = flags & ( kDxt1 | kDxt3 | kDxt5 );
|
||||
int fit = flags & ( kColourClusterFit | kColourRangeFit );
|
||||
int metric = flags & ( kColourMetricPerceptual | kColourMetricUniform );
|
||||
int extra = flags & kWeightColourByAlpha;
|
||||
|
||||
// set defaults
|
||||
if( method != kDxt3 && method != kDxt5 )
|
||||
method = kDxt1;
|
||||
if( fit != kColourRangeFit )
|
||||
fit = kColourClusterFit;
|
||||
if( metric != kColourMetricUniform )
|
||||
metric = kColourMetricPerceptual;
|
||||
|
||||
// done
|
||||
return method | fit | metric | extra;
|
||||
}
|
||||
|
||||
|
||||
void Compress( u8 const* rgba, void* block, int flags )
|
||||
{
|
||||
// fix any bad flags
|
||||
flags = FixFlags( flags );
|
||||
|
||||
// get the block locations
|
||||
void* colourBlock = block;
|
||||
void* alphaBock = block;
|
||||
if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 )
|
||||
colourBlock = reinterpret_cast< u8* >( block ) + 8;
|
||||
|
||||
// create the minimal point set
|
||||
ColourSet colours( rgba, flags );
|
||||
|
||||
// check the compression type and compress colour
|
||||
if( colours.GetCount() == 1 )
|
||||
{
|
||||
// always do a single colour fit
|
||||
SingleColourFit fit( &colours, flags );
|
||||
fit.Compress( colourBlock );
|
||||
}
|
||||
else if( ( flags & kColourRangeFit ) != 0 )
|
||||
{
|
||||
// do a range fit
|
||||
RangeFit fit( &colours, flags );
|
||||
fit.Compress( colourBlock );
|
||||
}
|
||||
else
|
||||
{
|
||||
// default to a cluster fit
|
||||
ClusterFit fit( &colours, flags );
|
||||
fit.Compress( colourBlock );
|
||||
}
|
||||
|
||||
// compress alpha separately if necessary
|
||||
if( ( flags & kDxt3 ) != 0 )
|
||||
CompressAlphaDxt3( rgba, alphaBock );
|
||||
else if( ( flags & kDxt5 ) != 0 )
|
||||
CompressAlphaDxt5( rgba, alphaBock );
|
||||
}
|
||||
|
||||
|
||||
void Decompress( u8* rgba, void const* block, int flags )
|
||||
{
|
||||
// fix any bad flags
|
||||
flags = FixFlags( flags );
|
||||
|
||||
// get the block locations
|
||||
void const* colourBlock = block;
|
||||
void const* alphaBock = block;
|
||||
if( ( flags & ( kDxt3 | kDxt5 ) ) != 0 )
|
||||
colourBlock = reinterpret_cast< u8 const* >( block ) + 8;
|
||||
|
||||
// decompress colour
|
||||
DecompressColour( rgba, colourBlock, ( flags & kDxt1 ) != 0 );
|
||||
|
||||
// decompress alpha separately if necessary
|
||||
if( ( flags & kDxt3 ) != 0 )
|
||||
DecompressAlphaDxt3( rgba, alphaBock );
|
||||
else if( ( flags & kDxt5 ) != 0 )
|
||||
DecompressAlphaDxt5( rgba, alphaBock );
|
||||
}
|
||||
|
||||
int GetStorageRequirements( int width, int height, int flags )
|
||||
{
|
||||
// fix any bad flags
|
||||
flags = FixFlags( flags );
|
||||
|
||||
// compute the storage requirements
|
||||
int blockcount = ( ( width + 3 )/4 ) * ( ( height + 3 )/4 );
|
||||
int blocksize = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
|
||||
return blockcount*blocksize;
|
||||
}
|
||||
|
||||
void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags )
|
||||
{
|
||||
// fix any bad flags
|
||||
flags = FixFlags( flags );
|
||||
|
||||
// initialise the block output
|
||||
u8* targetBlock = reinterpret_cast< u8* >( blocks );
|
||||
int bytesPerBlock = ( ( flags & kDxt1 ) != 0 ) ? 8 : 16;
|
||||
|
||||
int bh = std::min(width, 4);
|
||||
int bw = std::min(height, 4);
|
||||
|
||||
// loop over blocks
|
||||
for( int y = 0; y < height; y += 4 )
|
||||
{
|
||||
for( int x = 0; x < width; x += 4 )
|
||||
{
|
||||
// build the 4x4 block of pixels
|
||||
u8 sourceRgba[16*4];
|
||||
u8* targetPixel = sourceRgba;
|
||||
for( int py = 0; py < 4; ++py )
|
||||
{
|
||||
for( int px = 0; px < 4; ++px )
|
||||
{
|
||||
// get the source pixel in the image
|
||||
int sx = x + (px % bw);
|
||||
int sy = y + (py % bh);
|
||||
|
||||
// copy the rgba value
|
||||
u8 const* sourcePixel = rgba + 4*( width*sy + sx );
|
||||
for( int i = 0; i < 4; ++i )
|
||||
*targetPixel++ = *sourcePixel++;
|
||||
}
|
||||
}
|
||||
|
||||
// compress it into the output
|
||||
Compress( sourceRgba, targetBlock, flags );
|
||||
|
||||
// advance
|
||||
targetBlock += bytesPerBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DecompressImage( u8* rgba, int width, int height, 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 ) != 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;
|
||||
if( sx < width && sy < height )
|
||||
{
|
||||
u8* targetPixel = rgba + 4*( width*sy + sx );
|
||||
|
||||
// copy the rgba value
|
||||
for( int i = 0; i < 4; ++i )
|
||||
*targetPixel++ = *sourcePixel++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip this pixel as its outside the image
|
||||
sourcePixel += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// advance
|
||||
sourceBlock += bytesPerBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace squish
|
244
src/nvtt/squish/squish.h
Normal file
244
src/nvtt/squish/squish.h
Normal file
@ -0,0 +1,244 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_H
|
||||
#define SQUISH_H
|
||||
|
||||
//! All squish API functions live in this namespace.
|
||||
namespace squish {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
//! Typedef a quantity that is a single unsigned byte.
|
||||
typedef unsigned char u8;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
enum
|
||||
{
|
||||
//! Use DXT1 compression.
|
||||
kDxt1 = ( 1 << 0 ),
|
||||
|
||||
//! Use DXT3 compression.
|
||||
kDxt3 = ( 1 << 1 ),
|
||||
|
||||
//! Use DXT5 compression.
|
||||
kDxt5 = ( 1 << 2 ),
|
||||
|
||||
//! 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.
|
||||
kColourMetricUniform = ( 1 << 6 ),
|
||||
|
||||
//! Weight the colour by alpha during cluster fit (disabled by default).
|
||||
kWeightColourByAlpha = ( 1 << 7 )
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! @brief Compresses a 4x4 block of pixels.
|
||||
|
||||
@param rgba The rgba values of the 16 source pixels.
|
||||
@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
|
||||
values, with each component as 1 byte each. In memory this should be:
|
||||
|
||||
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
||||
|
||||
The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
|
||||
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.
|
||||
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
||||
|
||||
The flags parameter can also specify a preferred colour compressor and
|
||||
colour error metric to use when fitting the RGB components of the data.
|
||||
Possible colour compressors are: kColourClusterFit (the default) or
|
||||
kColourRangeFit. Possible colour error metrics are: kColourMetricPerceptual
|
||||
(the default) or kColourMetricUniform. If no flags are specified in any
|
||||
particular category then the default will be used. Unknown flags are
|
||||
ignored.
|
||||
|
||||
When using kColourClusterFit, an additional flag can be specified to
|
||||
weight the colour of each pixel by its alpha value. For images that are
|
||||
rendered using alpha blending, this can significantly increase the
|
||||
perceived quality.
|
||||
*/
|
||||
void Compress( u8 const* rgba, void* block, int flags );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! @brief Compresses a 4x4 block of 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 flags Compression flags.
|
||||
|
||||
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:
|
||||
|
||||
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
||||
|
||||
The mask parameter enables only certain pixels within the block. The lowest
|
||||
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
|
||||
arbitrary colours in the output block. An example of how this can be used
|
||||
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 should specify either kDxt1, kDxt3 or kDxt5 compression,
|
||||
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.
|
||||
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
||||
|
||||
The flags parameter can also specify a preferred colour compressor and
|
||||
colour error metric to use when fitting the RGB components of the data.
|
||||
Possible colour compressors are: kColourClusterFit (the default) or
|
||||
kColourRangeFit. Possible colour error metrics are: kColourMetricPerceptual
|
||||
(the default) or kColourMetricUniform. If no flags are specified in any
|
||||
particular category then the default will be used. Unknown flags are
|
||||
ignored.
|
||||
|
||||
When using kColourClusterFit, an additional flag can be specified to
|
||||
weight the colour of each pixel by its alpha value. For images that are
|
||||
rendered using alpha blending, this can significantly increase the
|
||||
perceived quality.
|
||||
*/
|
||||
void CompressMasked( u8 const* rgba, int mask, void* block, int flags );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! @brief Decompresses a 4x4 block of pixels.
|
||||
|
||||
@param rgba Storage for the 16 decompressed pixels.
|
||||
@param block The compressed DXT block.
|
||||
@param flags Compression flags.
|
||||
|
||||
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:
|
||||
|
||||
{ r1, g1, b1, a1, .... , r16, g16, b16, a16 }
|
||||
|
||||
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.
|
||||
*/
|
||||
void Decompress( u8* rgba, void const* block, int flags );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! @brief Computes the amount of compressed storage required.
|
||||
|
||||
@param width The width of the image.
|
||||
@param height The height of the image.
|
||||
@param flags Compression flags.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
be only partially used.
|
||||
*/
|
||||
int GetStorageRequirements( int width, int height, int flags );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! @brief Compresses an image in memory.
|
||||
|
||||
@param rgba The pixels of the source.
|
||||
@param width The width of the source image.
|
||||
@param height The height of the source image.
|
||||
@param blocks Storage for the compressed output.
|
||||
@param flags Compression flags.
|
||||
|
||||
The source pixels should be presented as a contiguous array of width*height
|
||||
rgba values, with each component as 1 byte each. In memory this should be:
|
||||
|
||||
{ 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. When using DXT1
|
||||
compression, 8 bytes of storage are required for each compressed DXT block.
|
||||
DXT3 and DXT5 compression require 16 bytes of storage per block.
|
||||
|
||||
The flags parameter can also specify a preferred colour compressor and
|
||||
colour error metric to use when fitting the RGB components of the data.
|
||||
Possible colour compressors are: kColourClusterFit (the default) or
|
||||
kColourRangeFit. Possible colour error metrics are: kColourMetricPerceptual
|
||||
(the default) or kColourMetricUniform. If no flags are specified in any
|
||||
particular category then the default will be used. Unknown flags are
|
||||
ignored.
|
||||
|
||||
When using kColourClusterFit, an additional flag can be specified to
|
||||
weight the colour of each pixel by its alpha value. For images that are
|
||||
rendered using alpha blending, this can significantly increase the
|
||||
perceived quality.
|
||||
|
||||
Internally this function calls squish::Compress for each block. To see how
|
||||
much memory is required in the compressed image, use
|
||||
squish::GetStorageRequirements.
|
||||
*/
|
||||
void CompressImage( u8 const* rgba, int width, int height, void* blocks, int flags );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! @brief Decompresses an image in memory.
|
||||
|
||||
@param rgba Storage for the decompressed pixels.
|
||||
@param width The width of the source image.
|
||||
@param height The height of the source image.
|
||||
@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.
|
||||
*/
|
||||
void DecompressImage( u8* rgba, int width, int height, void const* blocks, int flags );
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_H
|
||||
|
531
src/nvtt/squish/squish.xcodeproj/project.pbxproj
Normal file
531
src/nvtt/squish/squish.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,531 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 42;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
133FA0DC096A7B8E0050752E /* alpha.h in Headers */ = {isa = PBXBuildFile; fileRef = 133FA0DA096A7B8E0050752E /* alpha.h */; };
|
||||
133FA0DD096A7B8E0050752E /* alpha.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 133FA0DB096A7B8E0050752E /* alpha.cpp */; };
|
||||
1342B4160999DF1900152915 /* libsquish.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libsquish.a */; };
|
||||
1342B41A0999DF7000152915 /* squishpng.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1342B4190999DF7000152915 /* squishpng.cpp */; };
|
||||
1342B43F0999E0CC00152915 /* squishtest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1342B43E0999E0CC00152915 /* squishtest.cpp */; };
|
||||
1342B4420999E0EC00152915 /* libsquish.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libsquish.a */; };
|
||||
1350D71A092AA858005EE038 /* clusterfit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1350D70B092AA857005EE038 /* clusterfit.cpp */; };
|
||||
1350D71B092AA858005EE038 /* clusterfit.h in Headers */ = {isa = PBXBuildFile; fileRef = 1350D70C092AA858005EE038 /* clusterfit.h */; };
|
||||
1350D71E092AA858005EE038 /* colourblock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1350D70F092AA858005EE038 /* colourblock.cpp */; };
|
||||
1350D71F092AA858005EE038 /* colourblock.h in Headers */ = {isa = PBXBuildFile; fileRef = 1350D710092AA858005EE038 /* colourblock.h */; };
|
||||
1350D720092AA858005EE038 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 1350D711092AA858005EE038 /* config.h */; };
|
||||
1350D721092AA858005EE038 /* maths.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1350D712092AA858005EE038 /* maths.cpp */; };
|
||||
1350D722092AA858005EE038 /* maths.h in Headers */ = {isa = PBXBuildFile; fileRef = 1350D713092AA858005EE038 /* maths.h */; };
|
||||
1350D725092AA858005EE038 /* rangefit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1350D716092AA858005EE038 /* rangefit.cpp */; };
|
||||
1350D726092AA858005EE038 /* rangefit.h in Headers */ = {isa = PBXBuildFile; fileRef = 1350D717092AA858005EE038 /* rangefit.h */; };
|
||||
1350D727092AA858005EE038 /* squish.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1350D718092AA858005EE038 /* squish.cpp */; };
|
||||
1350D728092AA858005EE038 /* squish.h in Headers */ = {isa = PBXBuildFile; fileRef = 1350D719092AA858005EE038 /* squish.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
139C21CF09ADAB0800A2500D /* squishgen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 139C21CE09ADAB0800A2500D /* squishgen.cpp */; };
|
||||
139C234F09B0602700A2500D /* singlecolourfit.h in Headers */ = {isa = PBXBuildFile; fileRef = 139C234D09B0602700A2500D /* singlecolourfit.h */; };
|
||||
139C235009B0602700A2500D /* singlecolourfit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 139C234E09B0602700A2500D /* singlecolourfit.cpp */; };
|
||||
13A7CCA40952BE63001C963A /* colourfit.h in Headers */ = {isa = PBXBuildFile; fileRef = 13A7CCA20952BE63001C963A /* colourfit.h */; };
|
||||
13A7CCA50952BE63001C963A /* colourfit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 13A7CCA30952BE63001C963A /* colourfit.cpp */; };
|
||||
13C4C7AD0941C18000AC5B89 /* colourset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 13C4C7AB0941C18000AC5B89 /* colourset.cpp */; };
|
||||
13C4C7AE0941C18000AC5B89 /* colourset.h in Headers */ = {isa = PBXBuildFile; fileRef = 13C4C7AC0941C18000AC5B89 /* colourset.h */; };
|
||||
13CD64C2092BCF8A00488C97 /* simd.h in Headers */ = {isa = PBXBuildFile; fileRef = 13CD64C0092BCF8A00488C97 /* simd.h */; };
|
||||
13D0DC910931F93A00909807 /* simd_ve.h in Headers */ = {isa = PBXBuildFile; fileRef = 13D0DC900931F93A00909807 /* simd_ve.h */; };
|
||||
13D0DC970931F9D600909807 /* simd_sse.h in Headers */ = {isa = PBXBuildFile; fileRef = 13D0DC960931F9D600909807 /* simd_sse.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
1342B52B099BF72F00152915 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D2AAC045055464E500DB518D;
|
||||
remoteInfo = squish;
|
||||
};
|
||||
1342B58E099BF93D00152915 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D2AAC045055464E500DB518D;
|
||||
remoteInfo = squish;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
133FA0DA096A7B8E0050752E /* alpha.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = alpha.h; sourceTree = "<group>"; };
|
||||
133FA0DB096A7B8E0050752E /* alpha.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = alpha.cpp; sourceTree = "<group>"; };
|
||||
1342B4110999DE7F00152915 /* squishpng */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = squishpng; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1342B4190999DF7000152915 /* squishpng.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = squishpng.cpp; path = extra/squishpng.cpp; sourceTree = "<group>"; };
|
||||
1342B4370999E07C00152915 /* squishtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = squishtest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1342B43E0999E0CC00152915 /* squishtest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = squishtest.cpp; path = extra/squishtest.cpp; sourceTree = "<group>"; };
|
||||
1350D70B092AA857005EE038 /* clusterfit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clusterfit.cpp; sourceTree = "<group>"; };
|
||||
1350D70C092AA858005EE038 /* clusterfit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clusterfit.h; sourceTree = "<group>"; };
|
||||
1350D70F092AA858005EE038 /* colourblock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = colourblock.cpp; sourceTree = "<group>"; };
|
||||
1350D710092AA858005EE038 /* colourblock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = colourblock.h; sourceTree = "<group>"; };
|
||||
1350D711092AA858005EE038 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
|
||||
1350D712092AA858005EE038 /* maths.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = maths.cpp; sourceTree = "<group>"; };
|
||||
1350D713092AA858005EE038 /* maths.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = maths.h; sourceTree = "<group>"; };
|
||||
1350D716092AA858005EE038 /* rangefit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = rangefit.cpp; sourceTree = "<group>"; };
|
||||
1350D717092AA858005EE038 /* rangefit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rangefit.h; sourceTree = "<group>"; };
|
||||
1350D718092AA858005EE038 /* squish.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = squish.cpp; sourceTree = "<group>"; };
|
||||
1350D719092AA858005EE038 /* squish.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = squish.h; sourceTree = "<group>"; };
|
||||
13906CE3096938880000A6A7 /* texture_compression_s3tc.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = texture_compression_s3tc.txt; sourceTree = "<group>"; };
|
||||
139C21C409ADAA7000A2500D /* squishgen */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = squishgen; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
139C21CE09ADAB0800A2500D /* squishgen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = squishgen.cpp; path = extra/squishgen.cpp; sourceTree = "<group>"; };
|
||||
139C234D09B0602700A2500D /* singlecolourfit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = singlecolourfit.h; sourceTree = "<group>"; };
|
||||
139C234E09B0602700A2500D /* singlecolourfit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = singlecolourfit.cpp; sourceTree = "<group>"; };
|
||||
139C236D09B060A900A2500D /* singlecolourlookup.inl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = singlecolourlookup.inl; sourceTree = "<group>"; };
|
||||
13A7CCA20952BE63001C963A /* colourfit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colourfit.h; sourceTree = "<group>"; };
|
||||
13A7CCA30952BE63001C963A /* colourfit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colourfit.cpp; sourceTree = "<group>"; };
|
||||
13C4C7AB0941C18000AC5B89 /* colourset.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = colourset.cpp; sourceTree = "<group>"; };
|
||||
13C4C7AC0941C18000AC5B89 /* colourset.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = colourset.h; sourceTree = "<group>"; };
|
||||
13CD64C0092BCF8A00488C97 /* simd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simd.h; sourceTree = "<group>"; };
|
||||
13D0DC900931F93A00909807 /* simd_ve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simd_ve.h; sourceTree = "<group>"; };
|
||||
13D0DC960931F9D600909807 /* simd_sse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simd_sse.h; sourceTree = "<group>"; };
|
||||
D2AAC046055464E500DB518D /* libsquish.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libsquish.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
1342B40F0999DE7F00152915 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1342B4160999DF1900152915 /* libsquish.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
1342B4350999E07C00152915 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1342B4420999E0EC00152915 /* libsquish.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
139C21C209ADAA7000A2500D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D289987405E68DCB004EDB86 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
08FB7794FE84155DC02AAC07 /* squish */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
08FB7795FE84155DC02AAC07 /* Source */,
|
||||
C6A0FF2B0290797F04C91782 /* Documentation */,
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */,
|
||||
);
|
||||
name = squish;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
08FB7795FE84155DC02AAC07 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
133FA0DB096A7B8E0050752E /* alpha.cpp */,
|
||||
133FA0DA096A7B8E0050752E /* alpha.h */,
|
||||
1350D70B092AA857005EE038 /* clusterfit.cpp */,
|
||||
1350D70C092AA858005EE038 /* clusterfit.h */,
|
||||
13A7CCA30952BE63001C963A /* colourfit.cpp */,
|
||||
13A7CCA20952BE63001C963A /* colourfit.h */,
|
||||
13C4C7AB0941C18000AC5B89 /* colourset.cpp */,
|
||||
13C4C7AC0941C18000AC5B89 /* colourset.h */,
|
||||
1350D70F092AA858005EE038 /* colourblock.cpp */,
|
||||
1350D710092AA858005EE038 /* colourblock.h */,
|
||||
13906CE3096938880000A6A7 /* texture_compression_s3tc.txt */,
|
||||
1350D711092AA858005EE038 /* config.h */,
|
||||
1350D712092AA858005EE038 /* maths.cpp */,
|
||||
1350D713092AA858005EE038 /* maths.h */,
|
||||
1350D716092AA858005EE038 /* rangefit.cpp */,
|
||||
1350D717092AA858005EE038 /* rangefit.h */,
|
||||
13CD64C0092BCF8A00488C97 /* simd.h */,
|
||||
13D0DC960931F9D600909807 /* simd_sse.h */,
|
||||
13D0DC900931F93A00909807 /* simd_ve.h */,
|
||||
139C234E09B0602700A2500D /* singlecolourfit.cpp */,
|
||||
139C234D09B0602700A2500D /* singlecolourfit.h */,
|
||||
139C236D09B060A900A2500D /* singlecolourlookup.inl */,
|
||||
1350D718092AA858005EE038 /* squish.cpp */,
|
||||
1350D719092AA858005EE038 /* squish.h */,
|
||||
139C21CE09ADAB0800A2500D /* squishgen.cpp */,
|
||||
1342B4190999DF7000152915 /* squishpng.cpp */,
|
||||
1342B43E0999E0CC00152915 /* squishtest.cpp */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1AB674ADFE9D54B511CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2AAC046055464E500DB518D /* libsquish.a */,
|
||||
1342B4110999DE7F00152915 /* squishpng */,
|
||||
1342B4370999E07C00152915 /* squishtest */,
|
||||
139C21C409ADAA7000A2500D /* squishgen */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C6A0FF2B0290797F04C91782 /* Documentation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Documentation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
D2AAC043055464E500DB518D /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1350D71B092AA858005EE038 /* clusterfit.h in Headers */,
|
||||
1350D71F092AA858005EE038 /* colourblock.h in Headers */,
|
||||
1350D720092AA858005EE038 /* config.h in Headers */,
|
||||
1350D722092AA858005EE038 /* maths.h in Headers */,
|
||||
1350D726092AA858005EE038 /* rangefit.h in Headers */,
|
||||
1350D728092AA858005EE038 /* squish.h in Headers */,
|
||||
13CD64C2092BCF8A00488C97 /* simd.h in Headers */,
|
||||
13D0DC910931F93A00909807 /* simd_ve.h in Headers */,
|
||||
13D0DC970931F9D600909807 /* simd_sse.h in Headers */,
|
||||
13C4C7AE0941C18000AC5B89 /* colourset.h in Headers */,
|
||||
13A7CCA40952BE63001C963A /* colourfit.h in Headers */,
|
||||
133FA0DC096A7B8E0050752E /* alpha.h in Headers */,
|
||||
139C234F09B0602700A2500D /* singlecolourfit.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
1342B4100999DE7F00152915 /* squishpng */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1342B4130999DE9F00152915 /* Build configuration list for PBXNativeTarget "squishpng" */;
|
||||
buildPhases = (
|
||||
1342B40E0999DE7F00152915 /* Sources */,
|
||||
1342B40F0999DE7F00152915 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
1342B58F099BF93D00152915 /* PBXTargetDependency */,
|
||||
);
|
||||
name = squishpng;
|
||||
productName = squishpng;
|
||||
productReference = 1342B4110999DE7F00152915 /* squishpng */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
1342B4360999E07C00152915 /* squishtest */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1342B43B0999E0C000152915 /* Build configuration list for PBXNativeTarget "squishtest" */;
|
||||
buildPhases = (
|
||||
1342B4340999E07C00152915 /* Sources */,
|
||||
1342B4350999E07C00152915 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
1342B52C099BF72F00152915 /* PBXTargetDependency */,
|
||||
);
|
||||
name = squishtest;
|
||||
productName = squishtest;
|
||||
productReference = 1342B4370999E07C00152915 /* squishtest */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
139C21C309ADAA7000A2500D /* squishgen */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 139C21CB09ADAB0300A2500D /* Build configuration list for PBXNativeTarget "squishgen" */;
|
||||
buildPhases = (
|
||||
139C21C109ADAA7000A2500D /* Sources */,
|
||||
139C21C209ADAA7000A2500D /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = squishgen;
|
||||
productName = squishgen;
|
||||
productReference = 139C21C409ADAA7000A2500D /* squishgen */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
D2AAC045055464E500DB518D /* squish */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "squish" */;
|
||||
buildPhases = (
|
||||
D2AAC043055464E500DB518D /* Headers */,
|
||||
D2AAC044055464E500DB518D /* Sources */,
|
||||
D289987405E68DCB004EDB86 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = squish;
|
||||
productName = squish;
|
||||
productReference = D2AAC046055464E500DB518D /* libsquish.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "squish" */;
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* squish */;
|
||||
projectDirPath = "";
|
||||
targets = (
|
||||
D2AAC045055464E500DB518D /* squish */,
|
||||
1342B4100999DE7F00152915 /* squishpng */,
|
||||
1342B4360999E07C00152915 /* squishtest */,
|
||||
139C21C309ADAA7000A2500D /* squishgen */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
1342B40E0999DE7F00152915 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1342B41A0999DF7000152915 /* squishpng.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
1342B4340999E07C00152915 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1342B43F0999E0CC00152915 /* squishtest.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
139C21C109ADAA7000A2500D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
139C21CF09ADAB0800A2500D /* squishgen.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D2AAC044055464E500DB518D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1350D71A092AA858005EE038 /* clusterfit.cpp in Sources */,
|
||||
1350D71E092AA858005EE038 /* colourblock.cpp in Sources */,
|
||||
1350D721092AA858005EE038 /* maths.cpp in Sources */,
|
||||
1350D725092AA858005EE038 /* rangefit.cpp in Sources */,
|
||||
1350D727092AA858005EE038 /* squish.cpp in Sources */,
|
||||
13C4C7AD0941C18000AC5B89 /* colourset.cpp in Sources */,
|
||||
13A7CCA50952BE63001C963A /* colourfit.cpp in Sources */,
|
||||
133FA0DD096A7B8E0050752E /* alpha.cpp in Sources */,
|
||||
139C235009B0602700A2500D /* singlecolourfit.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
1342B52C099BF72F00152915 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D2AAC045055464E500DB518D /* squish */;
|
||||
targetProxy = 1342B52B099BF72F00152915 /* PBXContainerItemProxy */;
|
||||
};
|
||||
1342B58F099BF93D00152915 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D2AAC045055464E500DB518D /* squish */;
|
||||
targetProxy = 1342B58E099BF93D00152915 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
1342B4140999DE9F00152915 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
..,
|
||||
/sw/include,
|
||||
);
|
||||
INSTALL_PATH = "$(HOME)/bin";
|
||||
LIBRARY_SEARCH_PATHS = /sw/lib;
|
||||
OTHER_LDFLAGS = "-lpng";
|
||||
PRODUCT_NAME = squishpng;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1342B4150999DE9F00152915 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
..,
|
||||
/sw/include,
|
||||
);
|
||||
INSTALL_PATH = "$(HOME)/bin";
|
||||
LIBRARY_SEARCH_PATHS = /sw/lib;
|
||||
OTHER_LDFLAGS = "-lpng";
|
||||
PRODUCT_NAME = squishpng;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
1342B43C0999E0C000152915 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = ..;
|
||||
INSTALL_PATH = "$(HOME)/bin";
|
||||
PRODUCT_NAME = squishtest;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1342B43D0999E0C000152915 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = ..;
|
||||
INSTALL_PATH = "$(HOME)/bin";
|
||||
PRODUCT_NAME = squishtest;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
139C21CC09ADAB0300A2500D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = ..;
|
||||
INSTALL_PATH = "$(HOME)/bin";
|
||||
PRODUCT_NAME = squishgen;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
139C21CD09ADAB0300A2500D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = ..;
|
||||
INSTALL_PATH = "$(HOME)/bin";
|
||||
PRODUCT_NAME = squishgen;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
1DEB91EC08733DB70010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "SQUISH_USE_ALTIVEC=1";
|
||||
INSTALL_PATH = /usr/local/lib;
|
||||
OTHER_CFLAGS = "-maltivec";
|
||||
PRODUCT_NAME = squish;
|
||||
STRIP_INSTALLED_PRODUCT = NO;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB91ED08733DB70010E9CD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "SQUISH_USE_ALTIVEC=1";
|
||||
INSTALL_PATH = /usr/local/lib;
|
||||
OTHER_CFLAGS = "-maltivec";
|
||||
PRODUCT_NAME = squish;
|
||||
STRIP_INSTALLED_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
1DEB91F008733DB70010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_DYNAMIC_NO_PIC = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_PEDANTIC = YES;
|
||||
GCC_WARN_SHADOW = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||
GCC_WARN_UNUSED_VALUE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB91F108733DB70010E9CD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_DYNAMIC_NO_PIC = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 3;
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_UNROLL_LOOPS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_PEDANTIC = YES;
|
||||
GCC_WARN_SHADOW = YES;
|
||||
GCC_WARN_SIGN_COMPARE = YES;
|
||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||
GCC_WARN_UNUSED_VALUE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
1342B4130999DE9F00152915 /* Build configuration list for PBXNativeTarget "squishpng" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1342B4140999DE9F00152915 /* Debug */,
|
||||
1342B4150999DE9F00152915 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
1342B43B0999E0C000152915 /* Build configuration list for PBXNativeTarget "squishtest" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1342B43C0999E0C000152915 /* Debug */,
|
||||
1342B43D0999E0C000152915 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
139C21CB09ADAB0300A2500D /* Build configuration list for PBXNativeTarget "squishgen" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
139C21CC09ADAB0300A2500D /* Debug */,
|
||||
139C21CD09ADAB0300A2500D /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "squish" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1DEB91EC08733DB70010E9CD /* Debug */,
|
||||
1DEB91ED08733DB70010E9CD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "squish" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
1DEB91F008733DB70010E9CD /* Debug */,
|
||||
1DEB91F108733DB70010E9CD /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
|
||||
}
|
508
src/nvtt/squish/texture_compression_s3tc.txt
Normal file
508
src/nvtt/squish/texture_compression_s3tc.txt
Normal file
@ -0,0 +1,508 @@
|
||||
Name
|
||||
|
||||
EXT_texture_compression_s3tc
|
||||
|
||||
Name Strings
|
||||
|
||||
GL_EXT_texture_compression_s3tc
|
||||
|
||||
Contact
|
||||
|
||||
Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com)
|
||||
|
||||
Status
|
||||
|
||||
FINAL
|
||||
|
||||
Version
|
||||
|
||||
1.1, 16 November 2001 (containing only clarifications relative to
|
||||
version 1.0, dated 7 July 2000)
|
||||
|
||||
Number
|
||||
|
||||
198
|
||||
|
||||
Dependencies
|
||||
|
||||
OpenGL 1.1 is required.
|
||||
|
||||
GL_ARB_texture_compression is required.
|
||||
|
||||
This extension is written against the OpenGL 1.2.1 Specification.
|
||||
|
||||
Overview
|
||||
|
||||
This extension provides additional texture compression functionality
|
||||
specific to S3's S3TC format (called DXTC in Microsoft's DirectX API),
|
||||
subject to all the requirements and limitations described by the extension
|
||||
GL_ARB_texture_compression.
|
||||
|
||||
This extension supports DXT1, DXT3, and DXT5 texture compression formats.
|
||||
For the DXT1 image format, this specification supports an RGB-only mode
|
||||
and a special RGBA mode with single-bit "transparent" alpha.
|
||||
|
||||
IP Status
|
||||
|
||||
Contact S3 Incorporated (http://www.s3.com) regarding any intellectual
|
||||
property issues associated with implementing this extension.
|
||||
|
||||
WARNING: Vendors able to support S3TC texture compression in Direct3D
|
||||
drivers do not necessarily have the right to use the same functionality in
|
||||
OpenGL.
|
||||
|
||||
Issues
|
||||
|
||||
(1) Should DXT2 and DXT4 (premultiplied alpha) formats be supported?
|
||||
|
||||
RESOLVED: No -- insufficient interest. Supporting DXT2 and DXT4
|
||||
would require some rework to the TexEnv definition (maybe add a new
|
||||
base internal format RGBA_PREMULTIPLIED_ALPHA) for these formats.
|
||||
Note that the EXT_texture_env_combine extension (which extends normal
|
||||
TexEnv modes) can be used to support textures with premultipled alpha.
|
||||
|
||||
(2) Should generic "RGB_S3TC_EXT" and "RGBA_S3TC_EXT" enums be supported
|
||||
or should we use only the DXT<n> enums?
|
||||
|
||||
RESOLVED: No. A generic RGBA_S3TC_EXT is problematic because DXT3
|
||||
and DXT5 are both nominally RGBA (and DXT1 with the 1-bit alpha is
|
||||
also) yet one format must be chosen up front.
|
||||
|
||||
(3) Should TexSubImage support all block-aligned edits or just the minimal
|
||||
functionality required by the ARB_texture_compression extension?
|
||||
|
||||
RESOLVED: Allow all valid block-aligned edits.
|
||||
|
||||
(4) A pre-compressed image with a DXT1 format can be used as either an
|
||||
RGB_S3TC_DXT1 or an RGBA_S3TC_DXT1 image. If the image has
|
||||
transparent texels, how are they treated in each format?
|
||||
|
||||
RESOLVED: The renderer has to make sure that an RGB_S3TC_DXT1 format
|
||||
is decoded as RGB (where alpha is effectively one for all texels),
|
||||
while RGBA_S3TC_DXT1 is decoded as RGBA (where alpha is zero for all
|
||||
texels with "transparent" encodings). Otherwise, the formats are
|
||||
identical.
|
||||
|
||||
(5) Is the encoding of the RGB components for DXT1 formats correct in this
|
||||
spec? MSDN documentation does not specify an RGB color for the
|
||||
"transparent" encoding. Is it really black?
|
||||
|
||||
RESOLVED: Yes. The specification for the DXT1 format initially
|
||||
required black, but later changed that requirement to a
|
||||
recommendation. All vendors involved in the definition of this
|
||||
specification support black. In addition, specifying black has a
|
||||
useful behavior.
|
||||
|
||||
When blending multiple texels (GL_LINEAR filtering), mixing opaque and
|
||||
transparent samples is problematic. Defining a black color on
|
||||
transparent texels achieves a sensible result that works like a
|
||||
texture with premultiplied alpha. For example, if three opaque white
|
||||
and one transparent sample is being averaged, the result would be a
|
||||
75% intensity gray (with an alpha of 75%). This is the same result on
|
||||
the color channels as would be obtained using a white color, 75%
|
||||
alpha, and a SRC_ALPHA blend factor.
|
||||
|
||||
(6) Is the encoding of the RGB components for DXT3 and DXT5 formats
|
||||
correct in this spec? MSDN documentation suggests that the RGB blocks
|
||||
for DXT3 and DXT5 are decoded as described by the DXT1 format.
|
||||
|
||||
RESOLVED: Yes -- this appears to be a bug in the MSDN documentation.
|
||||
The specification for the DXT2-DXT5 formats require decoding using the
|
||||
opaque block encoding, regardless of the relative values of "color0"
|
||||
and "color1".
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
None.
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted by the <internalformat> parameter of TexImage2D, CopyTexImage2D,
|
||||
and CompressedTexImage2DARB and the <format> parameter of
|
||||
CompressedTexSubImage2DARB:
|
||||
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
|
||||
COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
|
||||
COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
|
||||
COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
|
||||
|
||||
Additions to Chapter 2 of the OpenGL 1.2.1 Specification (OpenGL Operation)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 3 of the OpenGL 1.2.1 Specification (Rasterization)
|
||||
|
||||
Add to Table 3.16.1: Specific Compressed Internal Formats
|
||||
|
||||
Compressed Internal Format Base Internal Format
|
||||
========================== ====================
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT RGB
|
||||
COMPRESSED_RGBA_S3TC_DXT1_EXT RGBA
|
||||
COMPRESSED_RGBA_S3TC_DXT3_EXT RGBA
|
||||
COMPRESSED_RGBA_S3TC_DXT5_EXT RGBA
|
||||
|
||||
|
||||
Modify Section 3.8.2, Alternate Image Specification
|
||||
|
||||
(add to end of TexSubImage discussion, p.123 -- after edit from the
|
||||
ARB_texture_compression spec)
|
||||
|
||||
If the internal format of the texture image being modified is
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT, the
|
||||
texture is stored using one of the several S3TC compressed texture image
|
||||
formats. Such images are easily edited along 4x4 texel boundaries, so the
|
||||
limitations on TexSubImage2D or CopyTexSubImage2D parameters are relaxed.
|
||||
TexSubImage2D and CopyTexSubImage2D will result in an INVALID_OPERATION
|
||||
error only if one of the following conditions occurs:
|
||||
|
||||
* <width> is not a multiple of four or equal to TEXTURE_WIDTH,
|
||||
unless <xoffset> and <yoffset> are both zero.
|
||||
* <height> is not a multiple of four or equal to TEXTURE_HEIGHT,
|
||||
unless <xoffset> and <yoffset> are both zero.
|
||||
* <xoffset> or <yoffset> is not a multiple of four.
|
||||
|
||||
The contents of any 4x4 block of texels of an S3TC compressed texture
|
||||
image that does not intersect the area being modified are preserved during
|
||||
valid TexSubImage2D and CopyTexSubImage2D calls.
|
||||
|
||||
|
||||
Add to Section 3.8.2, Alternate Image Specification (adding to the end of
|
||||
the CompressedTexImage section introduced by the ARB_texture_compression
|
||||
spec)
|
||||
|
||||
If <internalformat> is COMPRESSED_RGB_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT3_EXT, or
|
||||
COMPRESSED_RGBA_S3TC_DXT5_EXT, the compressed texture is stored using one
|
||||
of several S3TC compressed texture image formats. The S3TC texture
|
||||
compression algorithm supports only 2D images without borders.
|
||||
CompressedTexImage1DARB and CompressedTexImage3DARB produce an
|
||||
INVALID_ENUM error if <internalformat> is an S3TC format.
|
||||
CompressedTexImage2DARB will produce an INVALID_OPERATION error if
|
||||
<border> is non-zero.
|
||||
|
||||
|
||||
Add to Section 3.8.2, Alternate Image Specification (adding to the end of
|
||||
the CompressedTexSubImage section introduced by the
|
||||
ARB_texture_compression spec)
|
||||
|
||||
If the internal format of the texture image being modified is
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT, the
|
||||
texture is stored using one of the several S3TC compressed texture image
|
||||
formats. Since the S3TC texture compression algorithm supports only 2D
|
||||
images, CompressedTexSubImage1DARB and CompressedTexSubImage3DARB produce
|
||||
an INVALID_ENUM error if <format> is an S3TC format. Since S3TC images
|
||||
are easily edited along 4x4 texel boundaries, the limitations on
|
||||
CompressedTexSubImage2D are relaxed. CompressedTexSubImage2D will result
|
||||
in an INVALID_OPERATION error only if one of the following conditions
|
||||
occurs:
|
||||
|
||||
* <width> is not a multiple of four or equal to TEXTURE_WIDTH.
|
||||
* <height> is not a multiple of four or equal to TEXTURE_HEIGHT.
|
||||
* <xoffset> or <yoffset> is not a multiple of four.
|
||||
|
||||
The contents of any 4x4 block of texels of an S3TC compressed texture
|
||||
image that does not intersect the area being modified are preserved during
|
||||
valid TexSubImage2D and CopyTexSubImage2D calls.
|
||||
|
||||
Additions to Chapter 4 of the OpenGL 1.2.1 Specification (Per-Fragment
|
||||
Operations and the Frame Buffer)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special Functions)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and
|
||||
State Requests)
|
||||
|
||||
None.
|
||||
|
||||
Additions to Appendix A of the OpenGL 1.2.1 Specification (Invariance)
|
||||
|
||||
None.
|
||||
|
||||
Additions to the AGL/GLX/WGL Specifications
|
||||
|
||||
None.
|
||||
|
||||
GLX Protocol
|
||||
|
||||
None.
|
||||
|
||||
Errors
|
||||
|
||||
INVALID_ENUM is generated by CompressedTexImage1DARB or
|
||||
CompressedTexImage3DARB if <internalformat> is
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT.
|
||||
|
||||
INVALID_OPERATION is generated by CompressedTexImage2DARB if
|
||||
<internalformat> is COMPRESSED_RGB_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT3_EXT, or
|
||||
COMPRESSED_RGBA_S3TC_DXT5_EXT and <border> is not equal to zero.
|
||||
|
||||
INVALID_ENUM is generated by CompressedTexSubImage1DARB or
|
||||
CompressedTexSubImage3DARB if <format> is COMPRESSED_RGB_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT3_EXT, or
|
||||
COMPRESSED_RGBA_S3TC_DXT5_EXT.
|
||||
|
||||
INVALID_OPERATION is generated by TexSubImage2D CopyTexSubImage2D, or
|
||||
CompressedTexSubImage2D if TEXTURE_INTERNAL_FORMAT is
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT,
|
||||
COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT and any of
|
||||
the following apply: <width> is not a multiple of four or equal to
|
||||
TEXTURE_WIDTH; <height> is not a multiple of four or equal to
|
||||
TEXTURE_HEIGHT; <xoffset> or <yoffset> is not a multiple of four.
|
||||
|
||||
|
||||
The following restrictions from the ARB_texture_compression specification
|
||||
do not apply to S3TC texture formats, since subimage modification is
|
||||
straightforward as long as the subimage is properly aligned.
|
||||
|
||||
DELETE: INVALID_OPERATION is generated by TexSubImage1D, TexSubImage2D,
|
||||
DELETE: TexSubImage3D, CopyTexSubImage1D, CopyTexSubImage2D, or
|
||||
DELETE: CopyTexSubImage3D if the internal format of the texture image is
|
||||
DELETE: compressed and <xoffset>, <yoffset>, or <zoffset> does not equal
|
||||
DELETE: -b, where b is value of TEXTURE_BORDER.
|
||||
|
||||
DELETE: INVALID_VALUE is generated by CompressedTexSubImage1DARB,
|
||||
DELETE: CompressedTexSubImage2DARB, or CompressedTexSubImage3DARB if the
|
||||
DELETE: entire texture image is not being edited: if <xoffset>,
|
||||
DELETE: <yoffset>, or <zoffset> is greater than -b, <xoffset> + <width> is
|
||||
DELETE: less than w+b, <yoffset> + <height> is less than h+b, or <zoffset>
|
||||
DELETE: + <depth> is less than d+b, where b is the value of
|
||||
DELETE: TEXTURE_BORDER, w is the value of TEXTURE_WIDTH, h is the value of
|
||||
DELETE: TEXTURE_HEIGHT, and d is the value of TEXTURE_DEPTH.
|
||||
|
||||
See also errors in the GL_ARB_texture_compression specification.
|
||||
|
||||
New State
|
||||
|
||||
In the "Textures" state table, increment the TEXTURE_INTERNAL_FORMAT
|
||||
subscript for Z by 4 in the "Type" row.
|
||||
|
||||
New Implementation Dependent State
|
||||
|
||||
None
|
||||
|
||||
Appendix
|
||||
|
||||
S3TC Compressed Texture Image Formats
|
||||
|
||||
Compressed texture images stored using the S3TC compressed image formats
|
||||
are represented as a collection of 4x4 texel blocks, where each block
|
||||
contains 64 or 128 bits of texel data. The image is encoded as a normal
|
||||
2D raster image in which each 4x4 block is treated as a single pixel. If
|
||||
an S3TC image has a width or height less than four, the data corresponding
|
||||
to texels outside the image are irrelevant and undefined.
|
||||
|
||||
When an S3TC image with a width of <w>, height of <h>, and block size of
|
||||
<blocksize> (8 or 16 bytes) is decoded, the corresponding image size (in
|
||||
bytes) is:
|
||||
|
||||
ceil(<w>/4) * ceil(<h>/4) * blocksize.
|
||||
|
||||
When decoding an S3TC image, the block containing the texel at offset
|
||||
(<x>, <y>) begins at an offset (in bytes) relative to the base of the
|
||||
image of:
|
||||
|
||||
blocksize * (ceil(<w>/4) * floor(<y>/4) + floor(<x>/4)).
|
||||
|
||||
The data corresponding to a specific texel (<x>, <y>) are extracted from a
|
||||
4x4 texel block using a relative (x,y) value of
|
||||
|
||||
(<x> modulo 4, <y> modulo 4).
|
||||
|
||||
There are four distinct S3TC image formats:
|
||||
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT: Each 4x4 block of texels consists of 64
|
||||
bits of RGB image data.
|
||||
|
||||
Each RGB image data block is encoded as a sequence of 8 bytes, called (in
|
||||
order of increasing address):
|
||||
|
||||
c0_lo, c0_hi, c1_lo, c1_hi, bits_0, bits_1, bits_2, bits_3
|
||||
|
||||
The 8 bytes of the block are decoded into three quantities:
|
||||
|
||||
color0 = c0_lo + c0_hi * 256
|
||||
color1 = c1_lo + c1_hi * 256
|
||||
bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * bits_3))
|
||||
|
||||
color0 and color1 are 16-bit unsigned integers that are unpacked to
|
||||
RGB colors RGB0 and RGB1 as though they were 16-bit packed pixels with
|
||||
a <format> of RGB and a type of UNSIGNED_SHORT_5_6_5.
|
||||
|
||||
bits is a 32-bit unsigned integer, from which a two-bit control code
|
||||
is extracted for a texel at location (x,y) in the block using:
|
||||
|
||||
code(x,y) = bits[2*(4*y+x)+1..2*(4*y+x)+0]
|
||||
|
||||
where bit 31 is the most significant and bit 0 is the least
|
||||
significant bit.
|
||||
|
||||
The RGB color for a texel at location (x,y) in the block is given by:
|
||||
|
||||
RGB0, if color0 > color1 and code(x,y) == 0
|
||||
RGB1, if color0 > color1 and code(x,y) == 1
|
||||
(2*RGB0+RGB1)/3, if color0 > color1 and code(x,y) == 2
|
||||
(RGB0+2*RGB1)/3, if color0 > color1 and code(x,y) == 3
|
||||
|
||||
RGB0, if color0 <= color1 and code(x,y) == 0
|
||||
RGB1, if color0 <= color1 and code(x,y) == 1
|
||||
(RGB0+RGB1)/2, if color0 <= color1 and code(x,y) == 2
|
||||
BLACK, if color0 <= color1 and code(x,y) == 3
|
||||
|
||||
Arithmetic operations are done per component, and BLACK refers to an
|
||||
RGB color where red, green, and blue are all zero.
|
||||
|
||||
Since this image has an RGB format, there is no alpha component and the
|
||||
image is considered fully opaque.
|
||||
|
||||
|
||||
COMPRESSED_RGBA_S3TC_DXT1_EXT: Each 4x4 block of texels consists of 64
|
||||
bits of RGB image data and minimal alpha information. The RGB components
|
||||
of a texel are extracted in the same way as COMPRESSED_RGB_S3TC_DXT1_EXT.
|
||||
|
||||
The alpha component for a texel at location (x,y) in the block is
|
||||
given by:
|
||||
|
||||
0.0, if color0 <= color1 and code(x,y) == 3
|
||||
1.0, otherwise
|
||||
|
||||
IMPORTANT: When encoding an RGBA image into a format using 1-bit
|
||||
alpha, any texels with an alpha component less than 0.5 end up with an
|
||||
alpha of 0.0 and any texels with an alpha component greater than or
|
||||
equal to 0.5 end up with an alpha of 1.0. When encoding an RGBA image
|
||||
into the COMPRESSED_RGBA_S3TC_DXT1_EXT format, the resulting red,
|
||||
green, and blue components of any texels with a final alpha of 0.0
|
||||
will automatically be zero (black). If this behavior is not desired
|
||||
by an application, it should not use COMPRESSED_RGBA_S3TC_DXT1_EXT.
|
||||
This format will never be used when a generic compressed internal
|
||||
format (Table 3.16.2) is specified, although the nearly identical
|
||||
format COMPRESSED_RGB_S3TC_DXT1_EXT (above) may be.
|
||||
|
||||
|
||||
COMPRESSED_RGBA_S3TC_DXT3_EXT: Each 4x4 block of texels consists of 64
|
||||
bits of uncompressed alpha image data followed by 64 bits of RGB image
|
||||
data.
|
||||
|
||||
Each RGB image data block is encoded according to the
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT format, with the exception that the two code
|
||||
bits always use the non-transparent encodings. In other words, they are
|
||||
treated as though color0 > color1, regardless of the actual values of
|
||||
color0 and color1.
|
||||
|
||||
Each alpha image data block is encoded as a sequence of 8 bytes, called
|
||||
(in order of increasing address):
|
||||
|
||||
a0, a1, a2, a3, a4, a5, a6, a7
|
||||
|
||||
The 8 bytes of the block are decoded into one 64-bit integer:
|
||||
|
||||
alpha = a0 + 256 * (a1 + 256 * (a2 + 256 * (a3 + 256 * (a4 +
|
||||
256 * (a5 + 256 * (a6 + 256 * a7))))))
|
||||
|
||||
alpha is a 64-bit unsigned integer, from which a four-bit alpha value
|
||||
is extracted for a texel at location (x,y) in the block using:
|
||||
|
||||
alpha(x,y) = bits[4*(4*y+x)+3..4*(4*y+x)+0]
|
||||
|
||||
where bit 63 is the most significant and bit 0 is the least
|
||||
significant bit.
|
||||
|
||||
The alpha component for a texel at location (x,y) in the block is
|
||||
given by alpha(x,y) / 15.
|
||||
|
||||
|
||||
COMPRESSED_RGBA_S3TC_DXT5_EXT: Each 4x4 block of texels consists of 64
|
||||
bits of compressed alpha image data followed by 64 bits of RGB image data.
|
||||
|
||||
Each RGB image data block is encoded according to the
|
||||
COMPRESSED_RGB_S3TC_DXT1_EXT format, with the exception that the two code
|
||||
bits always use the non-transparent encodings. In other words, they are
|
||||
treated as though color0 > color1, regardless of the actual values of
|
||||
color0 and color1.
|
||||
|
||||
Each alpha image data block is encoded as a sequence of 8 bytes, called
|
||||
(in order of increasing address):
|
||||
|
||||
alpha0, alpha1, bits_0, bits_1, bits_2, bits_3, bits_4, bits_5
|
||||
|
||||
The alpha0 and alpha1 are 8-bit unsigned bytes converted to alpha
|
||||
components by multiplying by 1/255.
|
||||
|
||||
The 6 "bits" bytes of the block are decoded into one 48-bit integer:
|
||||
|
||||
bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
|
||||
256 * (bits_4 + 256 * bits_5))))
|
||||
|
||||
bits is a 48-bit unsigned integer, from which a three-bit control code
|
||||
is extracted for a texel at location (x,y) in the block using:
|
||||
|
||||
code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
|
||||
|
||||
where bit 47 is the most significant and bit 0 is the least
|
||||
significant bit.
|
||||
|
||||
The alpha component for a texel at location (x,y) in the block is
|
||||
given by:
|
||||
|
||||
alpha0, code(x,y) == 0
|
||||
alpha1, code(x,y) == 1
|
||||
|
||||
(6*alpha0 + 1*alpha1)/7, alpha0 > alpha1 and code(x,y) == 2
|
||||
(5*alpha0 + 2*alpha1)/7, alpha0 > alpha1 and code(x,y) == 3
|
||||
(4*alpha0 + 3*alpha1)/7, alpha0 > alpha1 and code(x,y) == 4
|
||||
(3*alpha0 + 4*alpha1)/7, alpha0 > alpha1 and code(x,y) == 5
|
||||
(2*alpha0 + 5*alpha1)/7, alpha0 > alpha1 and code(x,y) == 6
|
||||
(1*alpha0 + 6*alpha1)/7, alpha0 > alpha1 and code(x,y) == 7
|
||||
|
||||
(4*alpha0 + 1*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 2
|
||||
(3*alpha0 + 2*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 3
|
||||
(2*alpha0 + 3*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 4
|
||||
(1*alpha0 + 4*alpha1)/5, alpha0 <= alpha1 and code(x,y) == 5
|
||||
0.0, alpha0 <= alpha1 and code(x,y) == 6
|
||||
1.0, alpha0 <= alpha1 and code(x,y) == 7
|
||||
|
||||
|
||||
Revision History
|
||||
|
||||
1.1, 11/16/01 pbrown: Updated contact info, clarified where texels
|
||||
fall within a single block.
|
||||
|
||||
1.0, 07/07/00 prbrown1: Published final version agreed to by working
|
||||
group members.
|
||||
|
||||
0.9, 06/24/00 prbrown1: Documented that block-aligned TexSubImage calls
|
||||
do not modify existing texels outside the
|
||||
modified blocks. Added caveat to allow for a
|
||||
(0,0)-anchored TexSubImage operation of
|
||||
arbitrary size.
|
||||
|
||||
0.7, 04/11/00 prbrown1: Added issues on DXT1, DXT3, and DXT5 encodings
|
||||
where the MSDN documentation doesn't match what
|
||||
is really done. Added enum values from the
|
||||
extension registry.
|
||||
|
||||
0.4, 03/28/00 prbrown1: Updated to reflect final version of the
|
||||
ARB_texture_compression extension. Allowed
|
||||
block-aligned TexSubImage calls.
|
||||
|
||||
0.3, 03/07/00 prbrown1: Resolved issues pertaining to the format of RGB
|
||||
blocks in the DXT3 and DXT5 formats (they don't
|
||||
ever use the "transparent" encoding). Fixed
|
||||
decoding of DXT1 blocks. Pointed out issue of
|
||||
"transparent" texels in DXT1 encodings having
|
||||
different behaviors for RGB and RGBA internal
|
||||
formats.
|
||||
|
||||
0.2, 02/23/00 prbrown1: Minor revisions; added several issues.
|
||||
|
||||
0.11, 02/17/00 prbrown1: Slight modification to error semantics
|
||||
(INVALID_ENUM instead of INVALID_OPERATION).
|
||||
|
||||
0.1, 02/15/00 prbrown1: Initial revision.
|
39
src/nvtt/squish/vs7/squish.sln
Normal file
39
src/nvtt/squish/vs7/squish.sln
Normal file
@ -0,0 +1,39 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "squish", "squish\squish.vcproj", "{6A8518C3-D81A-4428-BD7F-C37933088AC1}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "squishpng", "squishpng\squishpng.vcproj", "{3BC7CF47-F1C8-4BDA-BE30-92F17B21D2C7}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6A8518C3-D81A-4428-BD7F-C37933088AC1} = {6A8518C3-D81A-4428-BD7F-C37933088AC1}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "squishtest", "squishtest\squishtest.vcproj", "{77A3F26C-A1D6-4535-9E37-7D3DF34E4B4B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6A8518C3-D81A-4428-BD7F-C37933088AC1} = {6A8518C3-D81A-4428-BD7F-C37933088AC1}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug.ActiveCfg = Debug|Win32
|
||||
{6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug.Build.0 = Debug|Win32
|
||||
{6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release.ActiveCfg = Release|Win32
|
||||
{6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release.Build.0 = Release|Win32
|
||||
{3BC7CF47-F1C8-4BDA-BE30-92F17B21D2C7}.Debug.ActiveCfg = Debug|Win32
|
||||
{3BC7CF47-F1C8-4BDA-BE30-92F17B21D2C7}.Debug.Build.0 = Debug|Win32
|
||||
{3BC7CF47-F1C8-4BDA-BE30-92F17B21D2C7}.Release.ActiveCfg = Release|Win32
|
||||
{3BC7CF47-F1C8-4BDA-BE30-92F17B21D2C7}.Release.Build.0 = Release|Win32
|
||||
{77A3F26C-A1D6-4535-9E37-7D3DF34E4B4B}.Debug.ActiveCfg = Debug|Win32
|
||||
{77A3F26C-A1D6-4535-9E37-7D3DF34E4B4B}.Debug.Build.0 = Debug|Win32
|
||||
{77A3F26C-A1D6-4535-9E37-7D3DF34E4B4B}.Release.ActiveCfg = Release|Win32
|
||||
{77A3F26C-A1D6-4535-9E37-7D3DF34E4B4B}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
198
src/nvtt/squish/vs7/squish/squish.vcproj
Normal file
198
src/nvtt/squish/vs7/squish/squish.vcproj
Normal file
@ -0,0 +1,198 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="squish"
|
||||
ProjectGUID="{6A8518C3-D81A-4428-BD7F-C37933088AC1}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\.."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;SQUISH_USE_SSE=1"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
WarnAsError="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/squish.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
AdditionalIncludeDirectories="..\.."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;SQUISH_USE_SSE=1"
|
||||
RuntimeLibrary="2"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
WarnAsError="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/squish.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath="..\..\alpha.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\clusterfit.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\colourblock.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\colourfit.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\colourset.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\maths.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\rangefit.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\singlecolourfit.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\squish.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath="..\..\alpha.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\clusterfit.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\colourblock.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\colourfit.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\colourset.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\config.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\maths.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\rangefit.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simd.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simd_sse.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\simd_ve.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\singlecolourfit.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\singlecolourlookup.inl">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\squish.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
<File
|
||||
RelativePath="..\..\texture_compression_s3tc.txt">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
140
src/nvtt/squish/vs7/squishpng/squishpng.vcproj
Normal file
140
src/nvtt/squish/vs7/squishpng/squishpng.vcproj
Normal file
@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="squishpng"
|
||||
ProjectGUID="{3BC7CF47-F1C8-4BDA-BE30-92F17B21D2C7}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\.."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
WarnAsError="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="libpng13d.lib"
|
||||
OutputFile="$(OutDir)/squishpng.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/squishpng.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\.."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
WarnAsError="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="libpng13.lib"
|
||||
OutputFile="$(OutDir)/squishpng.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath="..\..\extra\squishpng.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
138
src/nvtt/squish/vs7/squishtest/squishtest.vcproj
Normal file
138
src/nvtt/squish/vs7/squishtest/squishtest.vcproj
Normal file
@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="squishtest"
|
||||
ProjectGUID="{77A3F26C-A1D6-4535-9E37-7D3DF34E4B4B}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\.."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
WarnAsError="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/squishtest.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/squishtest.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\.."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="2"
|
||||
ForceConformanceInForLoopScope="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="4"
|
||||
WarnAsError="TRUE"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/squishtest.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath="..\..\extra\squishtest.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
576
src/nvtt/squish/weightedclusterfit.cpp
Normal file
576
src/nvtt/squish/weightedclusterfit.cpp
Normal file
@ -0,0 +1,576 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
Copyright (c) 2006 Ignacio Castano icastano@nvidia.com
|
||||
|
||||
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 "weightedclusterfit.h"
|
||||
#include "colourset.h"
|
||||
#include "colourblock.h"
|
||||
#include <cfloat>
|
||||
|
||||
|
||||
namespace squish {
|
||||
|
||||
WeightedClusterFit::WeightedClusterFit( ColourSet const* colours, int flags ) :
|
||||
ColourFit( colours, flags )
|
||||
{
|
||||
// initialise the best error
|
||||
#if SQUISH_USE_SIMD
|
||||
m_besterror = VEC4_CONST( FLT_MAX );
|
||||
#else
|
||||
m_besterror = FLT_MAX;
|
||||
#endif
|
||||
|
||||
// cache some values
|
||||
int const count = m_colours->GetCount();
|
||||
Vec3 const* values = m_colours->GetPoints();
|
||||
|
||||
// get the covariance matrix
|
||||
Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() );
|
||||
|
||||
// compute the principle component
|
||||
Vec3 principle = ComputePrincipleComponent( covariance );
|
||||
|
||||
// build the list of values
|
||||
float dps[16];
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
dps[i] = Dot( values[i], principle );
|
||||
m_order[i] = i;
|
||||
}
|
||||
|
||||
// stable sort
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j )
|
||||
{
|
||||
std::swap( dps[j], dps[j - 1] );
|
||||
std::swap( m_order[j], m_order[j - 1] );
|
||||
}
|
||||
}
|
||||
|
||||
// weight all the points
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 const* unweighted = m_colours->GetPointsSimd();
|
||||
Vec4 const* weights = m_colours->GetWeightsSimd();
|
||||
m_xxsum = VEC4_CONST( 0.0f );
|
||||
m_xsum = VEC4_CONST( 0.0f );
|
||||
#else
|
||||
Vec3 const* unweighted = m_colours->GetPoints();
|
||||
float const* weights = m_colours->GetWeights();
|
||||
m_xxsum = Vec3( 0.0f );
|
||||
m_xsum = Vec3( 0.0f );
|
||||
m_wsum = 0.0f;
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
int p = m_order[i];
|
||||
m_weighted[i] = weights[p] * unweighted[p];
|
||||
m_xxsum += m_weighted[i] * m_weighted[i];
|
||||
m_xsum += m_weighted[i];
|
||||
#if !SQUISH_USE_SIMD
|
||||
m_weights[i] = weights[p];
|
||||
m_wsum += m_weights[i];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WeightedClusterFit::setMetric(float r, float g, float b)
|
||||
{
|
||||
#if SQUISH_USE_SIMD
|
||||
m_metric = Vec4(r, g, b, 0);
|
||||
#else
|
||||
m_metric = Vec3(r, g, b);
|
||||
#endif
|
||||
}
|
||||
|
||||
float WeightedClusterFit::bestError() const
|
||||
{
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 x = m_xxsum * m_metric;
|
||||
Vec4 error = m_besterror + x.SplatX() + x.SplatY() + x.SplatZ();
|
||||
return error.GetVec3().X();
|
||||
#else
|
||||
return m_besterror + Dot(m_xxsum, m_metric);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if SQUISH_USE_SIMD
|
||||
|
||||
void WeightedClusterFit::Compress3( void* block )
|
||||
{
|
||||
Vec4 const one = VEC4_CONST(1.0f);
|
||||
Vec4 const zero = VEC4_CONST(0.0f);
|
||||
Vec4 const half(0.5f, 0.5f, 0.5f, 0.25f);
|
||||
Vec4 const two = VEC4_CONST(2.0);
|
||||
|
||||
// declare variables
|
||||
Vec4 beststart = VEC4_CONST( 0.0f );
|
||||
Vec4 bestend = VEC4_CONST( 0.0f );
|
||||
Vec4 besterror = VEC4_CONST( FLT_MAX );
|
||||
|
||||
Vec4 x0 = zero;
|
||||
|
||||
int b0 = 0, b1 = 0;
|
||||
|
||||
// check all possible clusters for this total order
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
Vec4 x1 = zero;
|
||||
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
Vec4 const x2 = m_xsum - x1 - x0;
|
||||
|
||||
//Vec3 const alphax_sum = x0 + x1 * 0.5f;
|
||||
//float const alpha2_sum = w0 + w1 * 0.25f;
|
||||
Vec4 const alphax_sum = MultiplyAdd(x1, half, x0); // alphax_sum, alpha2_sum
|
||||
Vec4 const alpha2_sum = alphax_sum.SplatW();
|
||||
|
||||
//Vec3 const betax_sum = x2 + x1 * 0.5f;
|
||||
//float const beta2_sum = w2 + w1 * 0.25f;
|
||||
Vec4 const betax_sum = MultiplyAdd(x1, half, x2); // betax_sum, beta2_sum
|
||||
Vec4 const beta2_sum = betax_sum.SplatW();
|
||||
|
||||
//float const alphabeta_sum = w1 * 0.25f;
|
||||
Vec4 const alphabeta_sum = (x1 * half).SplatW(); // alphabeta_sum
|
||||
|
||||
// float const factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);
|
||||
Vec4 const factor = Reciprocal( NegativeMultiplySubtract(alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum) );
|
||||
|
||||
Vec4 a = NegativeMultiplySubtract(betax_sum, alphabeta_sum, alphax_sum*beta2_sum) * factor;
|
||||
Vec4 b = NegativeMultiplySubtract(alphax_sum, alphabeta_sum, betax_sum*alpha2_sum) * factor;
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
|
||||
Vec4 const gridrcp( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f, 0.0f );
|
||||
a = Truncate( MultiplyAdd( grid, a, half ) ) * gridrcp;
|
||||
b = Truncate( MultiplyAdd( grid, b, half ) ) * gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec4 e1 = MultiplyAdd( a, alphax_sum, b*betax_sum );
|
||||
Vec4 e2 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
|
||||
Vec4 e3 = MultiplyAdd( a*b*alphabeta_sum - e1, two, e2 );
|
||||
|
||||
// apply the metric to the error term
|
||||
Vec4 e4 = e3 * m_metric;
|
||||
Vec4 error = e4.SplatX() + e4.SplatY() + e4.SplatZ();
|
||||
|
||||
// keep the solution if it wins
|
||||
if( CompareAnyLessThan( error, besterror ) )
|
||||
{
|
||||
besterror = error;
|
||||
beststart = a;
|
||||
bestend = b;
|
||||
b0 = c0;
|
||||
b1 = c1;
|
||||
}
|
||||
|
||||
x1 += m_weighted[c0+c1];
|
||||
}
|
||||
|
||||
x0 += m_weighted[c0];
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
if( CompareAnyLessThan( besterror, m_besterror ) )
|
||||
{
|
||||
// compute indices from cluster sizes.
|
||||
u8 bestindices[16];
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < b0; i++) {
|
||||
bestindices[i] = 0;
|
||||
}
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices[i] = 2;
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 ordered[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
ordered[m_order[i]] = bestindices[i];
|
||||
|
||||
// save the block
|
||||
WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), ordered, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
void WeightedClusterFit::Compress4( void* block )
|
||||
{
|
||||
Vec4 const one = VEC4_CONST(1.0f);
|
||||
Vec4 const zero = VEC4_CONST(0.0f);
|
||||
Vec4 const half = VEC4_CONST(0.5f);
|
||||
Vec4 const two = VEC4_CONST(2.0);
|
||||
Vec4 const onethird( 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/9.0f );
|
||||
Vec4 const twothirds( 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, 4.0f/9.0f );
|
||||
|
||||
// declare variables
|
||||
Vec4 beststart = VEC4_CONST( 0.0f );
|
||||
Vec4 bestend = VEC4_CONST( 0.0f );
|
||||
Vec4 besterror = VEC4_CONST( FLT_MAX );
|
||||
|
||||
Vec4 x0 = zero;
|
||||
int b0 = 0, b1 = 0, b2 = 0;
|
||||
|
||||
// check all possible clusters for this total order
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
Vec4 x1 = zero;
|
||||
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
Vec4 x2 = zero;
|
||||
|
||||
for( int c2 = 0; c2 <= 16-c0-c1; c2++)
|
||||
{
|
||||
Vec4 const x3 = m_xsum - x2 - x1 - x0;
|
||||
|
||||
//Vec3 const alphax_sum = x0 + x1 * (2.0f / 3.0f) + x2 * (1.0f / 3.0f);
|
||||
//float const alpha2_sum = w0 + w1 * (4.0f/9.0f) + w2 * (1.0f/9.0f);
|
||||
Vec4 const alphax_sum = x0 + MultiplyAdd(x1, twothirds, x2 * onethird); // alphax_sum, alpha2_sum
|
||||
Vec4 const alpha2_sum = alphax_sum.SplatW();
|
||||
|
||||
//Vec3 const betax_sum = x3 + x2 * (2.0f / 3.0f) + x1 * (1.0f / 3.0f);
|
||||
//float const beta2_sum = w3 + w2 * (4.0f/9.0f) + w1 * (1.0f/9.0f);
|
||||
Vec4 const betax_sum = x3 + MultiplyAdd(x2, twothirds, x1 * onethird); // betax_sum, beta2_sum
|
||||
Vec4 const beta2_sum = betax_sum.SplatW();
|
||||
|
||||
//float const alphabeta_sum = w1 * (2.0f/9.0f) + w2 * (2.0f/9.0f);
|
||||
Vec4 const alphabeta_sum = two * (x1 * onethird + x2 * onethird).SplatW(); // alphabeta_sum
|
||||
|
||||
// float const factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);
|
||||
Vec4 const factor = Reciprocal( NegativeMultiplySubtract(alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum) );
|
||||
|
||||
Vec4 a = NegativeMultiplySubtract(betax_sum, alphabeta_sum, alphax_sum*beta2_sum) * factor;
|
||||
Vec4 b = NegativeMultiplySubtract(alphax_sum, alphabeta_sum, betax_sum*alpha2_sum) * factor;
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
|
||||
Vec4 const gridrcp( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f, 0.0f );
|
||||
a = Truncate( MultiplyAdd( grid, a, half ) ) * gridrcp;
|
||||
b = Truncate( MultiplyAdd( grid, b, half ) ) * gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec4 e1 = MultiplyAdd( a, alphax_sum, b*betax_sum );
|
||||
Vec4 e2 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
|
||||
Vec4 e3 = MultiplyAdd( a*b*alphabeta_sum - e1, two, e2 );
|
||||
|
||||
// apply the metric to the error term
|
||||
Vec4 e4 = e3 * m_metric;
|
||||
Vec4 error = e4.SplatX() + e4.SplatY() + e4.SplatZ();
|
||||
|
||||
// keep the solution if it wins
|
||||
if( CompareAnyLessThan( error, besterror ) )
|
||||
{
|
||||
besterror = error;
|
||||
beststart = a;
|
||||
bestend = b;
|
||||
b0 = c0;
|
||||
b1 = c1;
|
||||
b2 = c2;
|
||||
}
|
||||
|
||||
x2 += m_weighted[c0+c1+c2];
|
||||
}
|
||||
|
||||
x1 += m_weighted[c0+c1];
|
||||
}
|
||||
|
||||
x0 += m_weighted[c0];
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
if( CompareAnyLessThan( besterror, m_besterror ) )
|
||||
{
|
||||
// compute indices from cluster sizes.
|
||||
u8 bestindices[16];
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < b0; i++) {
|
||||
bestindices[i] = 0;
|
||||
}
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices[i] = 2;
|
||||
}
|
||||
for(; i < b0+b1+b2; i++) {
|
||||
bestindices[i] = 3;
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 ordered[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
ordered[m_order[i]] = bestindices[i];
|
||||
|
||||
// save the block
|
||||
WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), ordered, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void WeightedClusterFit::Compress3( void* block )
|
||||
{
|
||||
// declare variables
|
||||
Vec3 beststart( 0.0f );
|
||||
Vec3 bestend( 0.0f );
|
||||
float besterror = FLT_MAX;
|
||||
|
||||
Vec3 x0(0.0f);
|
||||
float w0 = 0.0f;
|
||||
|
||||
int b0 = 0, b1 = 0;
|
||||
|
||||
// check all possible clusters for this total order
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
Vec3 x1(0.0f);
|
||||
float w1 = 0.0f;
|
||||
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
float w2 = m_wsum - w0 - w1;
|
||||
|
||||
// These factors could be entirely precomputed.
|
||||
float const alpha2_sum = w0 + w1 * 0.25f;
|
||||
float const beta2_sum = w2 + w1 * 0.25f;
|
||||
float const alphabeta_sum = w1 * 0.25f;
|
||||
float const factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);
|
||||
|
||||
Vec3 const alphax_sum = x0 + x1 * 0.5f;
|
||||
Vec3 const betax_sum = m_xsum - alphax_sum;
|
||||
|
||||
Vec3 a = (alphax_sum*beta2_sum - betax_sum*alphabeta_sum) * factor;
|
||||
Vec3 b = (betax_sum*alpha2_sum - alphax_sum*alphabeta_sum) * factor;
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
Vec3 const one( 1.0f );
|
||||
Vec3 const zero( 0.0f );
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
Vec3 const grid( 31.0f, 63.0f, 31.0f );
|
||||
Vec3 const gridrcp( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f );
|
||||
Vec3 const half( 0.5f );
|
||||
a = Floor( grid*a + half )*gridrcp;
|
||||
b = Floor( grid*b + half )*gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec3 e1 = a*a*alpha2_sum + b*b*beta2_sum + 2.0f*( a*b*alphabeta_sum - a*alphax_sum - b*betax_sum );
|
||||
|
||||
// apply the metric to the error term
|
||||
float error = Dot( e1, m_metric );
|
||||
|
||||
// keep the solution if it wins
|
||||
if( error < besterror )
|
||||
{
|
||||
besterror = error;
|
||||
beststart = a;
|
||||
bestend = b;
|
||||
b0 = c0;
|
||||
b1 = c1;
|
||||
}
|
||||
|
||||
x1 += m_weighted[c0+c1];
|
||||
w1 += m_weights[c0+c1];
|
||||
}
|
||||
|
||||
x0 += m_weighted[c0];
|
||||
w0 += m_weights[c0];
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
if( besterror < m_besterror )
|
||||
{
|
||||
// compute indices from cluster sizes.
|
||||
u8 bestindices[16];
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < b0; i++) {
|
||||
bestindices[i] = 0;
|
||||
}
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices[i] = 2;
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 ordered[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
ordered[m_order[i]] = bestindices[i];
|
||||
|
||||
// save the block
|
||||
WriteColourBlock3( beststart, bestend, ordered, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
void WeightedClusterFit::Compress4( void* block )
|
||||
{
|
||||
// declare variables
|
||||
Vec3 beststart( 0.0f );
|
||||
Vec3 bestend( 0.0f );
|
||||
float besterror = FLT_MAX;
|
||||
|
||||
Vec3 x0(0.0f);
|
||||
float w0 = 0.0f;
|
||||
int b0 = 0, b1 = 0, b2 = 0;
|
||||
int i = 0;
|
||||
|
||||
// check all possible clusters for this total order
|
||||
for( int c0 = 0; c0 <= 16; c0++)
|
||||
{
|
||||
Vec3 x1(0.0f);
|
||||
float w1 = 0.0f;
|
||||
|
||||
for( int c1 = 0; c1 <= 16-c0; c1++)
|
||||
{
|
||||
Vec3 x2(0.0f);
|
||||
float w2 = 0.0f;
|
||||
|
||||
for( int c2 = 0; c2 <= 16-c0-c1; c2++)
|
||||
{
|
||||
float w3 = m_wsum - w0 - w1 - w2;
|
||||
|
||||
float const alpha2_sum = w0 + w1 * (4.0f/9.0f) + w2 * (1.0f/9.0f);
|
||||
float const beta2_sum = w3 + w2 * (4.0f/9.0f) + w1 * (1.0f/9.0f);
|
||||
float const alphabeta_sum = (w1 + w2) * (2.0f/9.0f);
|
||||
float const factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum);
|
||||
|
||||
Vec3 const alphax_sum = x0 + x1 * (2.0f / 3.0f) + x2 * (1.0f / 3.0f);
|
||||
Vec3 const betax_sum = m_xsum - alphax_sum;
|
||||
|
||||
Vec3 a = ( alphax_sum*beta2_sum - betax_sum*alphabeta_sum )*factor;
|
||||
Vec3 b = ( betax_sum*alpha2_sum - alphax_sum*alphabeta_sum )*factor;
|
||||
|
||||
// clamp the output to [0, 1]
|
||||
Vec3 const one( 1.0f );
|
||||
Vec3 const zero( 0.0f );
|
||||
a = Min( one, Max( zero, a ) );
|
||||
b = Min( one, Max( zero, b ) );
|
||||
|
||||
// clamp to the grid
|
||||
Vec3 const grid( 31.0f, 63.0f, 31.0f );
|
||||
Vec3 const gridrcp( 0.03227752766457f, 0.01583151765563f, 0.03227752766457f );
|
||||
Vec3 const half( 0.5f );
|
||||
a = Floor( grid*a + half )*gridrcp;
|
||||
b = Floor( grid*b + half )*gridrcp;
|
||||
|
||||
// compute the error
|
||||
Vec3 e1 = a*a*alpha2_sum + b*b*beta2_sum + 2.0f*( a*b*alphabeta_sum - a*alphax_sum - b*betax_sum );
|
||||
|
||||
// apply the metric to the error term
|
||||
float error = Dot( e1, m_metric );
|
||||
|
||||
// keep the solution if it wins
|
||||
if( error < besterror )
|
||||
{
|
||||
besterror = error;
|
||||
beststart = a;
|
||||
bestend = b;
|
||||
b0 = c0;
|
||||
b1 = c1;
|
||||
b2 = c2;
|
||||
}
|
||||
|
||||
x2 += m_weighted[c0+c1+c2];
|
||||
w2 += m_weights[c0+c1+c2];
|
||||
}
|
||||
|
||||
x1 += m_weighted[c0+c1];
|
||||
w1 += m_weights[c0+c1];
|
||||
}
|
||||
|
||||
x0 += m_weighted[c0];
|
||||
w0 += m_weights[c0];
|
||||
}
|
||||
|
||||
// save the block if necessary
|
||||
if( besterror < m_besterror )
|
||||
{
|
||||
// compute indices from cluster sizes.
|
||||
u8 bestindices[16];
|
||||
{
|
||||
int i = 0;
|
||||
for(; i < b0; i++) {
|
||||
bestindices[i] = 0;
|
||||
}
|
||||
for(; i < b0+b1; i++) {
|
||||
bestindices[i] = 2;
|
||||
}
|
||||
for(; i < b0+b1+b2; i++) {
|
||||
bestindices[i] = 3;
|
||||
}
|
||||
for(; i < 16; i++) {
|
||||
bestindices[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remap the indices
|
||||
u8 ordered[16];
|
||||
for( int i = 0; i < 16; ++i )
|
||||
ordered[m_order[i]] = bestindices[i];
|
||||
|
||||
// save the block
|
||||
WriteColourBlock4( beststart, bestend, ordered, block );
|
||||
|
||||
// save the error
|
||||
m_besterror = besterror;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace squish
|
76
src/nvtt/squish/weightedclusterfit.h
Normal file
76
src/nvtt/squish/weightedclusterfit.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
|
||||
Copyright (c) 2006 Ignacio Castano icastano@nvidia.com
|
||||
|
||||
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.
|
||||
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef SQUISH_WEIGHTEDCLUSTERFIT_H
|
||||
#define SQUISH_WEIGHTEDCLUSTERFIT_H
|
||||
|
||||
#include "squish.h"
|
||||
#include "maths.h"
|
||||
#include "simd.h"
|
||||
#include "colourfit.h"
|
||||
|
||||
namespace squish {
|
||||
|
||||
class WeightedClusterFit : public ColourFit
|
||||
{
|
||||
public:
|
||||
WeightedClusterFit( ColourSet const* colours, int flags );
|
||||
|
||||
void setMetric(float r, float g, float b);
|
||||
float bestError() const;
|
||||
|
||||
static void doPrecomputation();
|
||||
|
||||
// Make them public
|
||||
virtual void Compress3( void* block );
|
||||
virtual void Compress4( void* block );
|
||||
|
||||
private:
|
||||
|
||||
Vec3 m_principle;
|
||||
|
||||
#if SQUISH_USE_SIMD
|
||||
Vec4 m_weighted[16];
|
||||
Vec4 m_metric;
|
||||
Vec4 m_xxsum;
|
||||
Vec4 m_xsum;
|
||||
Vec4 m_besterror;
|
||||
#else
|
||||
Vec3 m_weighted[16];
|
||||
float m_weights[16];
|
||||
Vec3 m_metric;
|
||||
Vec3 m_xxsum;
|
||||
Vec3 m_xsum;
|
||||
float m_wsum;
|
||||
float m_besterror;
|
||||
#endif
|
||||
|
||||
int m_order[16];
|
||||
};
|
||||
|
||||
} // namespace squish
|
||||
|
||||
#endif // ndef SQUISH_WEIGHTEDCLUSTERFIT_H
|
Reference in New Issue
Block a user