pax_global_header00006660000000000000000000000064117344165610014522gustar00rootroot0000000000000052 comment=a83288c462e7b359cd629dcd2df2c384af27a8eb nvidia-texture-tools-2.0.8-1+dfsg/000077500000000000000000000000001173441656100167145ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/CMakeLists.txt000066400000000000000000000013141173441656100214530ustar00rootroot00000000000000CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0) PROJECT(NV) ENABLE_TESTING() SET(NV_CMAKE_DIR "${NV_SOURCE_DIR}/cmake") SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${NV_CMAKE_DIR}") IF(WIN32) SET(GNUWIN32 "${NV_SOURCE_DIR}/gnuwin32") SET(CMAKE_INCLUDE_PATH "${GNUWIN32}/include") SET(CMAKE_LIBRARY_PATH "${GNUWIN32}/lib") ENDIF(WIN32) INCLUDE(${NV_CMAKE_DIR}/OptimalOptions.cmake) MESSAGE(STATUS "Setting optimal options") MESSAGE(STATUS " Processor: ${NV_SYSTEM_PROCESSOR}") MESSAGE(STATUS " Compiler Flags: ${CMAKE_CXX_FLAGS}") IF(NVTT_SHARED) SET(NVCORE_SHARED TRUE) SET(NVMATH_SHARED TRUE) SET(NVIMAGE_SHARED TRUE) ENDIF(NVTT_SHARED) ADD_SUBDIRECTORY(src) IF(WIN32) ADD_SUBDIRECTORY(gnuwin32) ENDIF(WIN32) nvidia-texture-tools-2.0.8-1+dfsg/ChangeLog000066400000000000000000000104601173441656100204670ustar00rootroot00000000000000NVIDIA Texture Tools version 2.0.8 * Fix float to fixed image conversion. Patch provided by Alex Pfaffe. Fixes issue 121. * ColorBlock::isSingleColor compares only RGB channels. Fixes issue 115. * Fix cmake build in msvc. Fixes issue 111. * Better estimate principal component. Fixes issue 120. NVIDIA Texture Tools version 2.0.7 * Output correct exit codes. Fixes issue 92. * Fix thread-safety errors. Fixes issue 90. * Add SIMD power method. Fixes issue 94. * Interact better with applications that already use CUDA. * Faster CPU compression. NVIDIA Texture Tools version 2.0.6 * Fix dll version checking. * Detect CUDA 2.1 and future CUDA versions correctly. * Print CUDA detection message in nvcompress. * Select the fastest CUDA device. * Compile squish with -fPIC. Fixes issue 74. * Fix warnings under gcc 4.3.2. * Fix nvzoom option typo by Frank Richter. Fixes issue 81. * Do not use CUDA to compress small mipmaps. Fixes issue 76. * Compute mipmaps of semi-transparent images correctly. * Shutdown CUDA properly. Fixes issue 83. * Fix pixel format converions. Fixes issue 87. * Update single color compression tables. Fixes issue 85. NVIDIA Texture Tools version 2.0.5 * Fix error in single color compressor. Fixes issue 66. * Detect mismatch between CUDA runtime and driver, and disable CUDA in that case. * Fix cmake files when compiling NVTT as a shared library. * When linking nvtt dynamically on unix, link all libraries dynamically. * Select fastest CUDA device. NVIDIA Texture Tools version 2.0.4 * Fix error in RGB format output; reported by jonsoh. See issue 49. * Added support RGB format dithering by jonsoh. Fixes issue 50 and 51. * Prevent infinite loop in indexMirror when width equal 1. Fixes issue 65. * Implement general scale filter, including upsampling. NVIDIA Texture Tools version 2.0.3 * More accurate DXT3 compressor. Fixes issue 38. * Remove legacy compressors. Fix issue 34. * Check for single color in all compressors. Fixes issue 43. * Fix error in fast downsample filter, reported by Noel Llopis. NVIDIA Texture Tools version 2.0.2 * Fix copy ctor error reported by Richard Sim. * Fix indexMirror error reported by Chris Lambert. * Fix vc8 post build command, reported by Richard Sim. * Fix RGBA modes with less than 32 bpp by Viktor Linder. * Fix alpha decompression by Amorilia. See issue 40. * Avoid default-initialized constructors for POD types, reported by Jim Tilander. * Add single color compresor for DXT1a. * Set swizzle code to ATI2 files. See issue 41. NVIDIA Texture Tools version 2.0.1 * Fix memory leaks. * Pre-allocate device memory for CUDA compressor. * Add single color compressor. Thanks to Amir Ebrahimi. * Better CUDA error checking. NVIDIA Texture Tools version 2.0.0 * Fixed PSNR formula in nvimgdiff. * Added support for arbitrary RGB formats. * Add support for DXT1a. Solves issue 1. * Refactor and improve compression quality of fast compressors. * Add cmake scripts to detect processor and chose compiler options. * Fix normal map decompression. * Evaluate angular deviation error for normal maps in nvimgdiff. * Fix DXT1 compression with custom color metrics. * Fix error in normal map generation from heightmap mipmaps. * Fix errors in estimateSize. * Fix errors when maxLevel is used. * Enable the use of BC5 not just for normal maps. * Add mirror wrapping mode, use by default. * Implement polyphase filters. Solves issue 3. * Add box and triangle filter sampling. * Refactor nvtt public interface. * Add resizing input options (setMaxExtents, setRoundMode). Solves issue 12. * Plain C and C# wrappers. Solves issue 22. NVIDIA Texture Tools version 0.9.4 * Added support for input DDS files, including cube maps. * Added support for input PSD files. * Added nvdecompress tool. * Added nvimgdiff tool. * Added nvddsinfo tool. * CUDA compressor 22% faster. * DXT3 & DXT5 CUDA compressors. * Faster DXT5n CPU compressor. * Many bug fixes. NVIDIA Texture Tools version 0.9.3 * Fix non power of two textures. * Fix estimateSize with rgb format. * Fix error in cuda compressor block limit. NVIDIA Texture Tools version 0.9.2 * Improved alpha compression. * Improved fast DXT1 compression. * Documentation and release notes. NVIDIA Texture Tools version 0.9.1 * Bug fix release. NVIDIA Texture Tools version 0.9.0 * Private beta prerelease. nvidia-texture-tools-2.0.8-1+dfsg/NVIDIA_Texture_Tools_LICENSE.txt000066400000000000000000000021731173441656100244740ustar00rootroot00000000000000NVIDIA Texture Tools 2.0 is licensed under the MIT license. Copyright (c) 2007 NVIDIA Corporation 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. nvidia-texture-tools-2.0.8-1+dfsg/NVIDIA_Texture_Tools_README.txt000066400000000000000000000125521173441656100243510ustar00rootroot00000000000000-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- NVIDIA Texture Tools README.txt Version 2.0 -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- TABLE OF CONTENTS -------------------------------------------------------------------------------- I. Instructions II. Contents III. Compilation Instructions IV. Using NVIDIA Texture Tools in your own applications V. Known Issues VI. Frequently Asked Questions -------------------------------------------------------------------------------- I. Introduction -------------------------------------------------------------------------------- This is our first alpha release of our new Texture Tools. The main highlights of this release are support for all DX10 texture formats, higher speed and improved compression quality. In addition to that it also comes with a hardware accelerated compressor that uses CUDA to compress blocks in parallel on the GPU and runs around 10 times faster than the CPU counterpart. You can obtain CUDA from our developer site at: http://developer.nvidia.com/object/cuda.html The source code of the Texture Tools is being released under the terms of the MIT license. II. Contents -------------------------------------------------------------------------------- This release contains only the source code of the texture compression library and an example commandline application that shows its use. III. Compilation Instructions -------------------------------------------------------------------------------- The compression library and the example can be compiled with Visual Studio 8 on Windows using the following solution file: project\vc8\nvtt.sln On most other platforms you can also use cmake. For more information about cmake, visit: http://www.cmake.org/ On unix systems you can use the standard build procedure (assuming cmake is installed on your system): $ ./configure $ make $ sudo make install IV. Using NVIDIA Texture Tools -------------------------------------------------------------------------------- To use the NVIDIA Texture Tools in your own applications you just have to include the following header file: src/nvimage/nvtt/nvtt.h And include the nvtt library in your projects. The following file contains a simple example that shows how to use the library: src/nvimage/nvtt/compress.cpp The usage of the commandline tool is the following: $ nvcompress [options] infile [outfile] where 'infile' is and TGA, PNG, PSD, DDS or JPG file, 'outfile' is a DDS file and 'options' is one or more of the following: Input options: -color The input image is a color map (default). -normal The input image is a normal map. -tonormal Convert input to normal map. -clamp Clamp wrapping mode (default). -repeat Repeat wrapping mode. -nomips Disable mipmap generation. Compression options: -fast Fast compression. -nocuda Do not use cuda compressor. -rgb RGBA format -bc1 BC1 format (DXT1) -bc2 BC2 format (DXT3) -bc3 BC3 format (DXT5) -bc3n BC3 normal map format (DXT5n/RXGB) -bc4 BC4 format (ATI1) -bc5 BC5 format (3Dc/ATI2) In order to run the compiled example on a PC that doesn't have Microsoft Visual Studio 2003 installed, you will have to install the Microsoft Visual Studio 2003 redistributable package that you can download at: http://go.microsoft.com/fwlink/?linkid=65127&clcid=0x409 V. Known Issues -------------------------------------------------------------------------------- None so far. Please send suggestions and bug reports to: TextureTools@nvidia.com or report them at: http://code.google.com/p/nvidia-texture-tools/issues/list VI. Frequently Asked Questions -------------------------------------------------------------------------------- - Do the NVIDIA Texture Tools work on OSX? It currently compiles and runs properly, but it has not been tested extensively. In particular there may be endiannes errors in the code. - Do the NVIDIA Texture Tools work on Linux? Yes. - Do the NVIDIA Texture Tools work on Vista? Yes, but note that CUDA is not supported on Vista yet, so the tool is not hardware accelerated. - Is CUDA required? No. The Visual Studio solution file contains a configuration that allows you to compile the texture tools without CUDA support. The cmake scripts automatically detect the CUDA installation and use it only when available. - Where can I get CUDA? http://developer.nvidia.com/object/cuda.html - Why is feature XYZ not supported? In order to keep the code small and reduce maintenance costs we have limited the features available in our new texture tools. We also have open sourced the code, so that people can modify it and add their own favourite features. - Can I use the NVIDIA Texture Tools in my commercial application? Yes, the NVIDIA Texture Tools are licensed under the MIT license. - Can I use the NVIDIA Texture Tools in my GPL application? Yes, the MIT license is compatible with the GPL and LGPL licenses. nvidia-texture-tools-2.0.8-1+dfsg/VERSION000066400000000000000000000000061173441656100177600ustar00rootroot000000000000002.0.8 nvidia-texture-tools-2.0.8-1+dfsg/cmake/000077500000000000000000000000001173441656100177745ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/cmake/DetermineProcessor.cmake000066400000000000000000000015711173441656100246160ustar00rootroot00000000000000 # Assume i586 by default. SET(NV_SYSTEM_PROCESSOR "i586") IF(UNIX) FIND_PROGRAM(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin ) IF(CMAKE_UNAME) EXEC_PROGRAM(uname ARGS -p OUTPUT_VARIABLE NV_SYSTEM_PROCESSOR RETURN_VALUE val) IF("${val}" GREATER 0 OR NV_SYSTEM_PROCESSOR STREQUAL "unknown") EXEC_PROGRAM(uname ARGS -m OUTPUT_VARIABLE NV_SYSTEM_PROCESSOR RETURN_VALUE val) ENDIF("${val}" GREATER 0 OR NV_SYSTEM_PROCESSOR STREQUAL "unknown") # processor may have double quote in the name, and that needs to be removed STRING(REGEX REPLACE "\"" "" NV_SYSTEM_PROCESSOR "${NV_SYSTEM_PROCESSOR}") STRING(REGEX REPLACE "/" "_" NV_SYSTEM_PROCESSOR "${NV_SYSTEM_PROCESSOR}") ENDIF(CMAKE_UNAME) # Get extended processor information with: # `cat /proc/cpuinfo` ELSE(UNIX) IF(WIN32) SET (NV_SYSTEM_PROCESSOR "$ENV{PROCESSOR_ARCHITECTURE}") ENDIF(WIN32) ENDIF(UNIX) nvidia-texture-tools-2.0.8-1+dfsg/cmake/FindCUDA.cmake000066400000000000000000000073031173441656100223160ustar00rootroot00000000000000# # Try to find CUDA compiler, runtime libraries, and include path. # Once done this will define # # CUDA_FOUND # CUDA_INCLUDE_PATH # CUDA_RUNTIME_LIBRARY # CUDA_COMPILER # # It will also define the following macro: # # WRAP_CUDA # IF (WIN32) FIND_PROGRAM (CUDA_COMPILER nvcc.exe $ENV{CUDA_BIN_PATH} DOC "The CUDA Compiler") ELSE(WIN32) FIND_PROGRAM (CUDA_COMPILER nvcc $ENV{CUDA_BIN_PATH} /usr/local/cuda/bin DOC "The CUDA Compiler") ENDIF(WIN32) IF (CUDA_COMPILER) GET_FILENAME_COMPONENT (CUDA_COMPILER_DIR ${CUDA_COMPILER} PATH) GET_FILENAME_COMPONENT (CUDA_COMPILER_SUPER_DIR ${CUDA_COMPILER_DIR} PATH) ELSE (CUDA_COMPILER) SET (CUDA_COMPILER_DIR .) SET (CUDA_COMPILER_SUPER_DIR ..) ENDIF (CUDA_COMPILER) FIND_PATH (CUDA_INCLUDE_PATH cuda_runtime.h $ENV{CUDA_INC_PATH} ${CUDA_COMPILER_SUPER_DIR}/include ${CUDA_COMPILER_DIR} DOC "The directory where CUDA headers reside") FIND_LIBRARY (CUDA_RUNTIME_LIBRARY NAMES cudart PATHS $ENV{CUDA_LIB_PATH} ${CUDA_COMPILER_SUPER_DIR}/lib ${CUDA_COMPILER_DIR} DOC "The CUDA runtime library") IF (CUDA_INCLUDE_PATH AND CUDA_RUNTIME_LIBRARY) SET (CUDA_FOUND TRUE) ELSE (CUDA_INCLUDE_PATH AND CUDA_RUNTIME_LIBRARY) SET (CUDA_FOUND FALSE) ENDIF (CUDA_INCLUDE_PATH AND CUDA_RUNTIME_LIBRARY) SET (CUDA_LIBRARIES ${CUDA_RUNTIME_LIBRARY}) MARK_AS_ADVANCED (CUDA_FOUND CUDA_COMPILER CUDA_RUNTIME_LIBRARY) #SET(CUDA_OPTIONS "-ncfe") SET(CUDA_OPTIONS "--host-compilation=C") IF (CUDA_EMULATION) SET (CUDA_OPTIONS "${CUDA_OPTIONS} -deviceemu") ENDIF (CUDA_EMULATION) # Get include directories. MACRO(GET_CUDA_INC_DIRS _cuda_INC_DIRS) SET(${_cuda_INC_DIRS}) GET_DIRECTORY_PROPERTY(_inc_DIRS INCLUDE_DIRECTORIES) FOREACH(_current ${_inc_DIRS}) SET(${_cuda_INC_DIRS} ${${_cuda_INC_DIRS}} "-I" ${_current}) ENDFOREACH(_current ${_inc_DIRS}) SET(${_cuda_INC_DIRS} ${${_cuda_INC_DIRS}} "-I" ${CUDA_INCLUDE_PATH}) # IF (CMAKE_SYTEM_INCLUDE_PATH) # SET(${_cuda_INC_DIRS} ${${_cuda_INC_DIRS}} "-I" ${CMAKE_SYSTEM_INCLUDE_PATH}) # ENDIF (CMAKE_SYTEM_INCLUDE_PATH) # IF (CMAKE_INCLUDE_PATH) # SET(${_cuda_INC_DIRS} ${${_cuda_INC_DIRS}} "-I" ${CMAKE_INCLUDE_PATH}) # ENDIF (CMAKE_INCLUDE_PATH) ENDMACRO(GET_CUDA_INC_DIRS) # Get file dependencies. MACRO (GET_CUFILE_DEPENDENCIES dependencies file) GET_FILENAME_COMPONENT(filepath ${file} PATH) # parse file for dependencies FILE(READ "${file}" CONTENTS) #STRING(REGEX MATCHALL "#[ \t]*include[ \t]+[<\"][^>\"]*" DEPS "${CONTENTS}") STRING(REGEX MATCHALL "#[ \t]*include[ \t]+\"[^\"]*" DEPS "${CONTENTS}") SET(${dependencies}) FOREACH(DEP ${DEPS}) STRING(REGEX REPLACE "#[ \t]*include[ \t]+\"" "" DEP "${DEP}") FIND_PATH(PATH_OF_${DEP} ${DEP} ${filepath}) IF(NOT ${PATH_OF_${DEP}} STREQUAL PATH_OF_${DEP}-NOTFOUND) #MESSAGE("${file} : ${PATH_OF_${DEP}}/${DEP}") SET(${dependencies} ${${dependencies}} ${PATH_OF_${DEP}}/${DEP}) ENDIF(NOT ${PATH_OF_${DEP}} STREQUAL PATH_OF_${DEP}-NOTFOUND) ENDFOREACH(DEP) ENDMACRO (GET_CUFILE_DEPENDENCIES) # WRAP_CUDA(outfile ...) MACRO (WRAP_CUDA outfiles) GET_CUDA_INC_DIRS(cuda_includes) #MESSAGE(${cuda_includes}) FOREACH (CUFILE ${ARGN}) GET_FILENAME_COMPONENT (CUFILE ${CUFILE} ABSOLUTE) GET_FILENAME_COMPONENT (CFILE ${CUFILE} NAME_WE) SET (CFILE ${CMAKE_CURRENT_BINARY_DIR}/${CFILE}.gen.c) GET_CUFILE_DEPENDENCIES(CUDEPS ${CUFILE}) #MESSAGE("${CUDEPS}") ADD_CUSTOM_COMMAND ( OUTPUT ${CFILE} COMMAND ${CUDA_COMPILER} ARGS -cuda ${cuda_includes} ${CUDA_OPTIONS} -o ${CFILE} ${CUFILE} MAIN_DEPENDENCY ${CUFILE} DEPENDS ${CUDEPS}) #MACRO_ADD_FILE_DEPENDENCIES(${CUFILE} ${CFILE}) SET (${outfiles} ${${outfiles}} ${CFILE}) ENDFOREACH (CUFILE) SET_SOURCE_FILES_PROPERTIES(${outfiles} PROPERTIES GENERATED 1) ENDMACRO (WRAP_CUDA) nvidia-texture-tools-2.0.8-1+dfsg/cmake/FindCg.cmake000066400000000000000000000076231173441656100221400ustar00rootroot00000000000000# # Try to find NVIDIA's Cg compiler, runtime libraries, and include path. # Once done this will define # # CG_FOUND =system has NVIDIA Cg and it can be used. # CG_INCLUDE_PATH = directory where cg.h resides # CG_LIBRARY = full path to libCg.so (Cg.DLL on win32) # CG_GL_LIBRARY = full path to libCgGL.so (CgGL.dll on win32) # CG_COMPILER = full path to cgc (cgc.exe on win32) # # On OSX default to using the framework version of Cg. IF (APPLE) INCLUDE(${CMAKE_ROOT}/Modules/CMakeFindFrameworks.cmake) SET(CG_FRAMEWORK_INCLUDES) CMAKE_FIND_FRAMEWORKS(Cg) IF (Cg_FRAMEWORKS) FOREACH(dir ${Cg_FRAMEWORKS}) SET(CG_FRAMEWORK_INCLUDES ${CG_FRAMEWORK_INCLUDES} ${dir}/Headers ${dir}/PrivateHeaders) ENDFOREACH(dir) # Find the include dir FIND_PATH(CG_INCLUDE_PATH cg.h ${CG_FRAMEWORK_INCLUDES} ) # Since we are using Cg framework, we must link to it. # Note, we use weak linking, so that it works even when Cg is not available. SET(CG_LIBRARY "-weak_framework Cg" CACHE STRING "Cg library") SET(CG_GL_LIBRARY "-weak_framework Cg" CACHE STRING "Cg GL library") ENDIF (Cg_FRAMEWORKS) FIND_PROGRAM(CG_COMPILER cgc /usr/bin /usr/local/bin DOC "The Cg compiler" ) ELSE (APPLE) IF (WIN32) FIND_PROGRAM( CG_COMPILER cgc $ENV{CG_BIN_PATH} $ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/bin $ENV{PROGRAMFILES}/Cg ${PROJECT_SOURCE_DIR}/../Cg DOC "The Cg Compiler" ) IF (CG_COMPILER) GET_FILENAME_COMPONENT(CG_COMPILER_DIR ${CG_COMPILER} PATH) GET_FILENAME_COMPONENT(CG_COMPILER_SUPER_DIR ${CG_COMPILER_DIR} PATH) ELSE (CG_COMPILER) SET (CG_COMPILER_DIR .) SET (CG_COMPILER_SUPER_DIR ..) ENDIF (CG_COMPILER) FIND_PATH( CG_INCLUDE_PATH Cg/cg.h $ENV{CG_INC_PATH} $ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/include $ENV{PROGRAMFILES}/Cg ${PROJECT_SOURCE_DIR}/../Cg ${CG_COMPILER_SUPER_DIR}/include ${CG_COMPILER_DIR} DOC "The directory where Cg/cg.h resides" ) FIND_LIBRARY( CG_LIBRARY NAMES Cg PATHS $ENV{CG_LIB_PATH} $ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/lib $ENV{PROGRAMFILES}/Cg ${PROJECT_SOURCE_DIR}/../Cg ${CG_COMPILER_SUPER_DIR}/lib ${CG_COMPILER_DIR} DOC "The Cg runtime library" ) FIND_LIBRARY( CG_GL_LIBRARY NAMES CgGL PATHS $ENV{PROGRAMFILES}/NVIDIA\ Corporation/Cg/lib $ENV{PROGRAMFILES}/Cg ${PROJECT_SOURCE_DIR}/../Cg ${CG_COMPILER_SUPER_DIR}/lib ${CG_COMPILER_DIR} DOC "The Cg runtime library" ) ELSE (WIN32) FIND_PROGRAM( CG_COMPILER cgc /usr/bin /usr/local/bin DOC "The Cg Compiler" ) GET_FILENAME_COMPONENT(CG_COMPILER_DIR "${CG_COMPILER}" PATH) GET_FILENAME_COMPONENT(CG_COMPILER_SUPER_DIR "${CG_COMPILER_DIR}" PATH) FIND_PATH( CG_INCLUDE_PATH Cg/cg.h /usr/include /usr/local/include ${CG_COMPILER_SUPER_DIR}/include DOC "The directory where Cg/cg.h resides" ) FIND_LIBRARY( CG_LIBRARY Cg PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib ${CG_COMPILER_SUPER_DIR}/lib64 ${CG_COMPILER_SUPER_DIR}/lib DOC "The Cg runtime library" ) SET(CG_LIBRARY ${CG_LIBRARY} -lpthread) FIND_LIBRARY( CG_GL_LIBRARY CgGL PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib ${CG_COMPILER_SUPER_DIR}/lib64 ${CG_COMPILER_SUPER_DIR}/lib DOC "The Cg runtime library" ) ENDIF (WIN32) ENDIF (APPLE) IF (CG_INCLUDE_PATH) SET( CG_FOUND 1 CACHE STRING "Set to 1 if CG is found, 0 otherwise") ELSE (CG_INCLUDE_PATH) SET( CG_FOUND 0 CACHE STRING "Set to 1 if CG is found, 0 otherwise") ENDIF (CG_INCLUDE_PATH) MARK_AS_ADVANCED( CG_FOUND ) nvidia-texture-tools-2.0.8-1+dfsg/cmake/FindDirectX.cmake000066400000000000000000000020151173441656100231370ustar00rootroot00000000000000 IF (WIN32) FIND_PATH(DX9_INCLUDE_PATH d3d9.h PATHS "$ENV{DXSDK_DIR}/Include" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK/Include" DOC "The directory where D3D9.h resides") FIND_PATH(DX10_INCLUDE_PATH D3D10.h PATHS "$ENV{DXSDK_DIR}/Include" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK/Include" DOC "The directory where D3D10.h resides") FIND_LIBRARY(D3D10_LIBRARY d3d10.lib PATHS "$ENV{DXSDK_DIR}/Lib/x86" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK/Lib/x86" DOC "The directory where d3d10.lib resides") FIND_LIBRARY(D3DX10_LIBRARY d3dx10.lib PATHS "$ENV{DXSDK_DIR}/Lib/x86" "$ENV{PROGRAMFILES}/Microsoft DirectX SDK/Lib/x86" DOC "The directory where d3dx10.lib resides") SET(DX10_LIBRARIES ${D3D10_LIBRARY} ${D3DX10_LIBRARY}) ENDIF (WIN32) IF (DX10_INCLUDE_PATH) SET( DX10_FOUND 1 CACHE STRING "Set to 1 if CG is found, 0 otherwise") ELSE (DX10_INCLUDE_PATH) SET( DX10_FOUND 0 CACHE STRING "Set to 1 if CG is found, 0 otherwise") ENDIF (DX10_INCLUDE_PATH) MARK_AS_ADVANCED( DX10_FOUND ) nvidia-texture-tools-2.0.8-1+dfsg/cmake/FindGLEW.cmake000066400000000000000000000021441173441656100223360ustar00rootroot00000000000000# # Try to find GLEW library and include path. # Once done this will define # # GLEW_FOUND # GLEW_INCLUDE_PATH # GLEW_LIBRARY # IF (WIN32) FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h $ENV{PROGRAMFILES}/GLEW/include ${PROJECT_SOURCE_DIR}/src/nvgl/glew/include DOC "The directory where GL/glew.h resides") FIND_LIBRARY( GLEW_LIBRARY NAMES glew GLEW glew32 glew32s PATHS $ENV{PROGRAMFILES}/GLEW/lib ${PROJECT_SOURCE_DIR}/src/nvgl/glew/bin ${PROJECT_SOURCE_DIR}/src/nvgl/glew/lib DOC "The GLEW library") ELSE (WIN32) FIND_PATH( GLEW_INCLUDE_PATH GL/glew.h /usr/include /usr/local/include /sw/include /opt/local/include DOC "The directory where GL/glew.h resides") FIND_LIBRARY( GLEW_LIBRARY NAMES GLEW glew PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /sw/lib /opt/local/lib DOC "The GLEW library") ENDIF (WIN32) IF (GLEW_INCLUDE_PATH) SET( GLEW_FOUND 1 CACHE STRING "Set to 1 if GLEW is found, 0 otherwise") ELSE (GLEW_INCLUDE_PATH) SET( GLEW_FOUND 0 CACHE STRING "Set to 1 if GLEW is found, 0 otherwise") ENDIF (GLEW_INCLUDE_PATH) MARK_AS_ADVANCED( GLEW_FOUND ) nvidia-texture-tools-2.0.8-1+dfsg/cmake/FindGLUT.cmake000066400000000000000000000060211173441656100223510ustar00rootroot00000000000000# - try to find glut library and include files # GLUT_INCLUDE_DIR, where to find GL/glut.h, etc. # GLUT_LIBRARIES, the libraries to link against # GLUT_FOUND, If false, do not try to use GLUT. # Also defined, but not for general use are: # GLUT_glut_LIBRARY = the full path to the glut library. # GLUT_Xmu_LIBRARY = the full path to the Xmu library. # GLUT_Xi_LIBRARY = the full path to the Xi Library. IF (WIN32) IF(CYGWIN) FIND_PATH( GLUT_INCLUDE_DIR GL/glut.h /usr/include ) FIND_LIBRARY( GLUT_glut_LIBRARY glut32 ${OPENGL_LIBRARY_DIR} /usr/lib /usr/lib/w32api /usr/local/lib /usr/X11R6/lib ) ELSE(CYGWIN) # FIND_PATH( GLUT_INCLUDE_DIR GL/glut.h # ${GLUT_ROOT_PATH}/include # ) # FIND_LIBRARY( GLUT_glut_LIBRARY glut32 # ${GLUT_ROOT_PATH}/lib # ${OPENGL_LIBRARY_DIR} # ) FIND_PATH( GLUT_INCLUDE_DIR GL/glut.h ${GLUT_ROOT_PATH}/include ${PROJECT_SOURCE_DIR}/src/nvgl/glut/include DOC "The directory where GL/glut.h resides") FIND_LIBRARY( GLUT_glut_LIBRARY NAMES glut GLUT glut32 glut32s PATHS ${GLUT_ROOT_PATH}/lib ${PROJECT_SOURCE_DIR}/src/nvgl/glut/bin ${PROJECT_SOURCE_DIR}/src/nvgl/glut/lib ${OPENGL_LIBRARY_DIR} DOC "The GLUT library") ENDIF(CYGWIN) ELSE (WIN32) IF (APPLE) # These values for Apple could probably do with improvement. FIND_PATH( GLUT_INCLUDE_DIR glut.h /System/Library/Frameworks/GLUT.framework/Versions/A/Headers ${OPENGL_LIBRARY_DIR} ) SET(GLUT_glut_LIBRARY "-framework Glut" CACHE STRING "GLUT library for OSX") SET(GLUT_cocoa_LIBRARY "-framework Cocoa" CACHE STRING "Cocoa framework for OSX") ELSE (APPLE) FIND_PATH( GLUT_INCLUDE_DIR GL/glut.h /usr/include /usr/include/GL /usr/local/include /usr/openwin/share/include /usr/openwin/include /usr/X11R6/include /usr/include/X11 /opt/graphics/OpenGL/include /opt/graphics/OpenGL/contrib/libglut ) FIND_LIBRARY( GLUT_glut_LIBRARY glut /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib ) FIND_LIBRARY( GLUT_Xi_LIBRARY Xi /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib ) FIND_LIBRARY( GLUT_Xmu_LIBRARY Xmu /usr/lib /usr/local/lib /usr/openwin/lib /usr/X11R6/lib ) ENDIF (APPLE) ENDIF (WIN32) SET( GLUT_FOUND "NO" ) IF(GLUT_INCLUDE_DIR) IF(GLUT_glut_LIBRARY) # Is -lXi and -lXmu required on all platforms that have it? # If not, we need some way to figure out what platform we are on. SET( GLUT_LIBRARIES ${GLUT_glut_LIBRARY} ${GLUT_Xmu_LIBRARY} ${GLUT_Xi_LIBRARY} ${GLUT_cocoa_LIBRARY} ) SET( GLUT_FOUND "YES" ) #The following deprecated settings are for backwards compatibility with CMake1.4 SET (GLUT_LIBRARY ${GLUT_LIBRARIES}) SET (GLUT_INCLUDE_PATH ${GLUT_INCLUDE_DIR}) ENDIF(GLUT_glut_LIBRARY) ENDIF(GLUT_INCLUDE_DIR) MARK_AS_ADVANCED( GLUT_INCLUDE_DIR GLUT_glut_LIBRARY GLUT_Xmu_LIBRARY GLUT_Xi_LIBRARY ) nvidia-texture-tools-2.0.8-1+dfsg/cmake/FindMaya.cmake000066400000000000000000000027471173441656100225000ustar00rootroot00000000000000 IF (WIN32) # Maya plugins can only be compiled with msvc IF (MSVC) FIND_PATH(MAYA_INCLUDE_PATH maya/MTypes.h PATHS "$ENV{PROGRAMFILES}/Autodesk/Maya8.5/include" "$ENV{MAYA_LOCATION}/include" DOC "The directory where MTypes.h resides") # Find maya version! FIND_LIBRARY(MAYA_FOUNDATION_LIBRARY Foundation PATHS "$ENV{PROGRAMFILES}/Autodesk/Maya8.5/lib" "$ENV{MAYA_LOCATION}/lib" DOC "The directory where Foundation.lib resides") FIND_LIBRARY(MAYA_OPENMAYA_LIBRARY OpenMaya PATHS "$ENV{PROGRAMFILES}/Autodesk/Maya8.5/lib" "$ENV{MAYA_LOCATION}/lib" DOC "The directory where OpenMaya.lib resides") FIND_LIBRARY(MAYA_OPENMAYAANIM_LIBRARY OpenMayaAnim PATHS "$ENV{PROGRAMFILES}/Autodesk/Maya8.5/lib" "$ENV{MAYA_LOCATION}/lib" DOC "The directory where OpenMayaAnim.lib resides") SET(MAYA_LIBRARIES ${MAYA_FOUNDATION_LIBRARY} ${MAYA_OPENMAYA_LIBRARY} ${MAYA_OPENMAYAANIM_LIBRARY}) SET(MAYA_EXTENSION ".mll") ENDIF (MSVC) ELSE (WIN32) # On linux, check gcc version. # OSX and Linux FIND_PATH(MAYA_INCLUDE_PATH maya/MTypes.h PATHS /usr/autodesk/maya/include $ENV{MAYA_LOCATION}/include DOC "The directory where MTypes.h resides") # TODO ENDIF (WIN32) IF (MAYA_INCLUDE_PATH) SET( MAYA_FOUND 1 CACHE STRING "Set to 1 if Maya is found, 0 otherwise") ELSE (MAYA_INCLUDE_PATH) SET( MAYA_FOUND 0 CACHE STRING "Set to 1 if Maya is found, 0 otherwise") ENDIF (MAYA_INCLUDE_PATH) MARK_AS_ADVANCED( MAYA_FOUND ) nvidia-texture-tools-2.0.8-1+dfsg/cmake/FindOpenEXR.cmake000066400000000000000000000041771173441656100230700ustar00rootroot00000000000000# # Try to find OpenEXR's libraries, and include path. # Once done this will define: # # OPENEXR_FOUND = OpenEXR found. # OPENEXR_INCLUDE_PATHS = OpenEXR include directories. # OPENEXR_LIBRARIES = libraries that are needed to use OpenEXR. # INCLUDE(FindZLIB) IF(ZLIB_FOUND) SET(LIBRARY_PATHS /usr/lib /usr/local/lib /sw/lib /opt/local/lib $ENV{PROGRAM_FILES}/OpenEXR/lib/static) FIND_PATH(OPENEXR_INCLUDE_PATH ImfRgbaFile.h PATH_SUFFIXES OpenEXR /usr/include /usr/local/include /sw/include /opt/local/include) FIND_LIBRARY(OPENEXR_HALF_LIBRARY NAMES Half PATHS ${LIBRARY_PATHS}) FIND_LIBRARY(OPENEXR_IEX_LIBRARY NAMES Iex PATHS ${LIBRARY_PATHS}) FIND_LIBRARY(OPENEXR_IMATH_LIBRARY NAMES Imath PATHS ${LIBRARY_PATHS}) FIND_LIBRARY(OPENEXR_ILMIMF_LIBRARY NAMES IlmImf PATHS ${LIBRARY_PATHS}) FIND_LIBRARY(OPENEXR_ILMTHREAD_LIBRARY NAMES IlmThread PATHS ${LIBRARY_PATHS}) ENDIF(ZLIB_FOUND) #MESSAGE(STATUS ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ZLIB_LIBRARY}) IF (OPENEXR_INCLUDE_PATH AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY) SET(OPENEXR_FOUND TRUE) SET(OPENEXR_INCLUDE_PATHS ${OPENEXR_INCLUDE_PATH} CACHE STRING "The include paths needed to use OpenEXR") SET(OPENEXR_LIBRARIES ${OPENEXR_IMATH_LIBRARY} ${OPENEXR_ILMIMF_LIBRARY} ${OPENEXR_IEX_LIBRARY} ${OPENEXR_HALF_LIBRARY} ${OPENEXR_ILMTHREAD_LIBRARY} ${ZLIB_LIBRARY} CACHE STRING "The libraries needed to use OpenEXR") ENDIF (OPENEXR_INCLUDE_PATH AND OPENEXR_IMATH_LIBRARY AND OPENEXR_ILMIMF_LIBRARY AND OPENEXR_IEX_LIBRARY AND OPENEXR_HALF_LIBRARY) IF(OPENEXR_FOUND) IF(NOT OPENEXR_FIND_QUIETLY) MESSAGE(STATUS "Found OpenEXR: ${OPENEXR_ILMIMF_LIBRARY}") ENDIF(NOT OPENEXR_FIND_QUIETLY) ELSE(OPENEXR_FOUND) IF(OPENEXR_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find OpenEXR library") ENDIF(OPENEXR_FIND_REQUIRED) ENDIF(OPENEXR_FOUND) MARK_AS_ADVANCED( OPENEXR_INCLUDE_PATHS OPENEXR_LIBRARIES OPENEXR_ILMIMF_LIBRARY OPENEXR_IMATH_LIBRARY OPENEXR_IEX_LIBRARY OPENEXR_HALF_LIBRARY) nvidia-texture-tools-2.0.8-1+dfsg/cmake/OptimalOptions.cmake000066400000000000000000000034251173441656100237630ustar00rootroot00000000000000 INCLUDE(${NV_CMAKE_DIR}/DetermineProcessor.cmake) # Set optimal options for gcc: IF(CMAKE_COMPILER_IS_GNUCXX) IF(NV_SYSTEM_PROCESSOR STREQUAL "i586") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i586") ENDIF(NV_SYSTEM_PROCESSOR STREQUAL "i586") IF(NV_SYSTEM_PROCESSOR STREQUAL "i686") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=i686") #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse -mtune=i686 -msse3") #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium4") ENDIF(NV_SYSTEM_PROCESSOR STREQUAL "i686") IF(NV_SYSTEM_PROCESSOR STREQUAL "x86_64") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=athlon64") #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=athlon64 -msse3") ENDIF(NV_SYSTEM_PROCESSOR STREQUAL "x86_64") IF(NV_SYSTEM_PROCESSOR STREQUAL "powerpc") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=powerpc -maltivec -mabi=altivec -mpowerpc-gfxopt") # ibook G4: #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=7450 -mtune=7450 -maltivec -mabi=altivec -mpowerpc-gfxopt") ENDIF(NV_SYSTEM_PROCESSOR STREQUAL "powerpc") ENDIF(CMAKE_COMPILER_IS_GNUCXX) IF(MSVC) # @@ Some of these might only be available in VC8. # Code generation flags. # SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /arch:SSE2 /fp:fast") # SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:SSE2 /fp:fast") # Optimization flags. SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} /O2 /Ob2 /Oi /Ot /Oy /GL") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /O2 /Ob2 /Oi /Ot /Oy /GL") SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") SET(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /LTCG") # Definitions. ADD_DEFINITIONS(-D__SSE2__ -D__SSE__ -D__MMX__) ENDIF(MSVC) nvidia-texture-tools-2.0.8-1+dfsg/configure000077500000000000000000000030721173441656100206250ustar00rootroot00000000000000#!/usr/bin/env sh BOLD="\033[1m" RED="\033[91m" GREEN="\033[92m" YELLOW="\033[93m" CYAN="\033[96m" NORMAL="\033[0m" # Make sure cmake is available. if command -v cmake >/dev/null 2>&1; then CMAKE=cmake else echo "Error - cmake is not available!" exit 2 fi help=false build="Debug" # release prefix=/usr/local # Parse the args for i in "$@" do case $i in --help ) help=true ;; --debug ) build="Debug" ;; --release ) build="Release" ;; --prefix=* ) prefix="${i#--prefix=}" ;; --prefix=* ) prefix="${i#--prefix=}" ;; * ) echo "Unrecognised argument $i" ;; esac done if [ "$help" = "true" ] then echo "-----------------------------------------------" echo "nvidia-texture-tools "`cat VERSION`" configuration script" echo "-----------------------------------------------" echo echo "--help Show this message." echo "--debug Configure debug build." echo "--release Configure release build." echo "--prefix=path Installation prefix." echo "--include=path Include path." echo "--lib=path Library path." exit 0 fi echo "-- Configuring nvidia-texture-tools "`cat VERSION` mkdir -p ./build cd ./build $CMAKE .. -DNVTT_SHARED=1 -DCMAKE_BUILD_TYPE=$build -DCMAKE_INSTALL_PREFIX=$prefix -G "Unix Makefiles" || exit 1 cd .. echo "" echo -e "Your configure completed "$GREEN"successfully"$NORMAL", now type "$BOLD"make"$NORMAL echo "" cat > Makefile << EOF all: @make --no-print-directory -C build/ install: @make install --no-print-directory -C build/ clean: @make clean --no-print-directory -C build/ distclean: @rm -Rf build/ EOF nvidia-texture-tools-2.0.8-1+dfsg/src/000077500000000000000000000000001173441656100175035ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/CMakeLists.txt000066400000000000000000000063541173441656100222530ustar00rootroot00000000000000 SUBDIRS(nvcore) SUBDIRS(nvmath) SUBDIRS(nvimage) SUBDIRS(nvtt) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) # OpenGL INCLUDE(FindOpenGL) IF(OPENGL_FOUND) MESSAGE(STATUS "Looking for OpenGL - found") ELSE(OPENGL_FOUND) MESSAGE(STATUS "Looking for OpenGL - not found") ENDIF(OPENGL_FOUND) # GLUT INCLUDE(${NV_CMAKE_DIR}/FindGLUT.cmake) #INCLUDE(FindGLUT) IF(GLUT_FOUND) MESSAGE(STATUS "Looking for GLUT - found") ELSE(GLUT_FOUND) MESSAGE(STATUS "Looking for GLUT - not found") ENDIF(GLUT_FOUND) # DirectX INCLUDE(${NV_CMAKE_DIR}/FindDirectX.cmake) IF(DX10_FOUND) MESSAGE(STATUS "Looking for DirectX - found") ELSE(DX10_FOUND) MESSAGE(STATUS "Looking for DirectX - not found") ENDIF(DX10_FOUND) # GLEW INCLUDE(${NV_CMAKE_DIR}/FindGLEW.cmake) IF(GLEW_FOUND) MESSAGE(STATUS "Looking for GLEW - found") ELSE(GLEW_FOUND) MESSAGE(STATUS "Looking for GLEW - not found") ENDIF(GLEW_FOUND) # Cg INCLUDE(${NV_CMAKE_DIR}/FindCg.cmake) IF(CG_FOUND) MESSAGE(STATUS "Looking for Cg - found") ELSE(CG_FOUND) MESSAGE(STATUS "Looking for Cg - not found") ENDIF(CG_FOUND) # CUDA INCLUDE(${NV_CMAKE_DIR}/FindCUDA.cmake) IF(CUDA_FOUND) SET(HAVE_CUDA ${CUDA_FOUND} CACHE BOOL "Set to TRUE if CUDA is found, FALSE otherwise") MESSAGE(STATUS "Looking for CUDA - found") ELSE(CUDA_FOUND) MESSAGE(STATUS "Looking for CUDA - not found") ENDIF(CUDA_FOUND) # Maya INCLUDE(${NV_CMAKE_DIR}/FindMaya.cmake) IF(MAYA_FOUND) SET(HAVE_MAYA ${MAYA_FOUND} CACHE BOOL "Set to TRUE if Maya is found, FALSE otherwise") MESSAGE(STATUS "Looking for Maya - found") ELSE(MAYA_FOUND) MESSAGE(STATUS "Looking for Maya - not found") ENDIF(MAYA_FOUND) # JPEG INCLUDE(FindJPEG) IF(JPEG_FOUND) SET(HAVE_JPEG ${JPEG_FOUND} CACHE BOOL "Set to TRUE if JPEG is found, FALSE otherwise") MESSAGE(STATUS "Looking for JPEG - found") ELSE(JPEG_FOUND) MESSAGE(STATUS "Looking for JPEG - not found") ENDIF(JPEG_FOUND) # PNG INCLUDE(FindPNG) IF(PNG_FOUND) SET(HAVE_PNG ${PNG_FOUND} CACHE BOOL "Set to TRUE if PNG is found, FALSE otherwise") MESSAGE(STATUS "Looking for PNG - found") ELSE(PNG_FOUND) MESSAGE(STATUS "Looking for PNG - not found") ENDIF(PNG_FOUND) # TIFF INCLUDE(FindTIFF) IF(TIFF_FOUND) SET(HAVE_TIFF ${TIFF_FOUND} CACHE BOOL "Set to TRUE if TIFF is found, FALSE otherwise") MESSAGE(STATUS "Looking for TIFF - found") ELSE(TIFF_FOUND) MESSAGE(STATUS "Looking for TIFF - not found") ENDIF(TIFF_FOUND) # OpenEXR INCLUDE(${NV_CMAKE_DIR}/FindOpenEXR.cmake) IF(OPENEXR_FOUND) SET(HAVE_OPENEXR ${OPENEXR_FOUND} CACHE BOOL "Set to TRUE if OpenEXR is found, FALSE otherwise") MESSAGE(STATUS "Looking for OpenEXR - found") ELSE(OPENEXR_FOUND) MESSAGE(STATUS "Looking for OpenEXR - not found") ENDIF(OPENEXR_FOUND) # Qt FIND_PACKAGE(Qt4) # Threads FIND_PACKAGE(Threads REQUIRED) MESSAGE(STATUS "Use thread library: ${CMAKE_THREAD_LIBS_INIT}") # configuration file INCLUDE(CheckIncludeFiles) CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILES(stdarg.h HAVE_STDARG_H) CHECK_INCLUDE_FILES(signal.h HAVE_SIGNAL_H) CHECK_INCLUDE_FILES(execinfo.h HAVE_EXECINFO_H) CHECK_INCLUDE_FILES(malloc.h HAVE_MALLOC_H) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/nvconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/nvconfig.h) #INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/nvconfig.h DESTINATION include) nvidia-texture-tools-2.0.8-1+dfsg/src/nvconfig.h.in000066400000000000000000000004721173441656100220750ustar00rootroot00000000000000#ifndef NV_CONFIG #define NV_CONFIG #cmakedefine HAVE_UNISTD_H #cmakedefine HAVE_STDARG_H #cmakedefine HAVE_SIGNAL_H #cmakedefine HAVE_EXECINFO_H #cmakedefine HAVE_MALLOC_H #cmakedefine HAVE_PNG #cmakedefine HAVE_JPEG #cmakedefine HAVE_TIFF #cmakedefine HAVE_OPENEXR #cmakedefine HAVE_MAYA #endif // NV_CONFIG nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/000077500000000000000000000000001173441656100207775ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/BitArray.h000066400000000000000000000055041173441656100226710ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_BITARRAY_H #define NV_CORE_BITARRAY_H #include #include namespace nv { /// Count the bits of @a x. inline uint bitsSet(uint8 x) { uint count = 0; for(; x != 0; x >>= 1) { count += (x & 1); } return count; } /// Count the bits of @a x. inline uint bitsSet(uint32 x, int bits) { uint count = 0; for(; x != 0 && bits != 0; x >>= 1, bits--) { count += (x & 1); } return count; } /// Simple bit array. class BitArray { public: /// Default ctor. BitArray() {} /// Ctor with initial m_size. BitArray(uint sz) { resize(sz); } /// Get array m_size. uint size() const { return m_size; } /// Clear array m_size. void clear() { resize(0); } /// Set array m_size. void resize(uint sz) { m_size = sz; m_bitArray.resize( (m_size + 7) >> 3 ); } /// Get bit. bool bitAt(uint b) const { nvDebugCheck( b < m_size ); return (m_bitArray[b >> 3] & (1 << (b & 7))) != 0; } /// Set a bit. void setBitAt(uint b) { nvDebugCheck( b < m_size ); m_bitArray[b >> 3] |= (1 << (b & 7)); } /// Clear a bit. void clearBitAt( uint b ) { nvDebugCheck( b < m_size ); m_bitArray[b >> 3] &= ~(1 << (b & 7)); } /// Clear all the bits. void clearAll() { memset(m_bitArray.unsecureBuffer(), 0, m_bitArray.size()); } /// Set all the bits. void setAll() { memset(m_bitArray.unsecureBuffer(), 0xFF, m_bitArray.size()); } /// Toggle all the bits. void toggleAll() { const uint byte_num = m_bitArray.size(); for(uint b = 0; b < byte_num; b++) { m_bitArray[b] ^= 0xFF; } } /// Get a byte of the bit array. const uint8 & byteAt(uint index) const { return m_bitArray[index]; } /// Set the given byte of the byte array. void setByteAt(uint index, uint8 b) { m_bitArray[index] = b; } /// Count the number of bits set. uint countSetBits() const { const uint num = m_bitArray.size(); if( num == 0 ) { return 0; } uint count = 0; for(uint i = 0; i < num - 1; i++) { count += bitsSet(m_bitArray[i]); } count += bitsSet(m_bitArray[num-1], m_size & 0x7); //piDebugCheck(count + countClearBits() == m_size); return count; } /// Count the number of bits clear. uint countClearBits() const { const uint num = m_bitArray.size(); if( num == 0 ) { return 0; } uint count = 0; for(uint i = 0; i < num - 1; i++) { count += bitsSet(~m_bitArray[i]); } count += bitsSet(~m_bitArray[num-1], m_size & 0x7); //piDebugCheck(count + countSetBits() == m_size); return count; } friend void swap(BitArray & a, BitArray & b) { swap(a.m_size, b.m_size); swap(a.m_bitArray, b.m_bitArray); } private: /// Number of bits stored. uint m_size; /// Array of bits. Array m_bitArray; }; } // nv namespace #endif // _PI_CORE_BITARRAY_H_ nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/CMakeLists.txt000066400000000000000000000013721173441656100235420ustar00rootroot00000000000000PROJECT(nvcore) ADD_SUBDIRECTORY(poshlib) SET(CORE_SRCS nvcore.h Ptr.h BitArray.h Memory.h Memory.cpp Debug.h Debug.cpp Containers.h StrLib.h StrLib.cpp Stream.h StdStream.h TextReader.h TextReader.cpp TextWriter.h TextWriter.cpp Radix.h Radix.cpp Library.h Library.cpp) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) # targets ADD_DEFINITIONS(-DNVCORE_EXPORTS) IF(UNIX) SET(LIBS ${LIBS} ${CMAKE_DL_LIBS}) ENDIF(UNIX) IF(NVCORE_SHARED) ADD_DEFINITIONS(-DNVCORE_SHARED=1) ADD_LIBRARY(nvcore SHARED ${CORE_SRCS}) ELSE(NVCORE_SHARED) ADD_LIBRARY(nvcore ${CORE_SRCS}) ENDIF(NVCORE_SHARED) TARGET_LINK_LIBRARIES(nvcore ${LIBS}) INSTALL(TARGETS nvcore RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib/static) nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Containers.h000066400000000000000000000561601173441656100232650ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_CONTAINER_H #define NV_CORE_CONTAINER_H /* These containers are based on Thatcher Ulrich containers, donated to the Public Domain. I've also borrowed some ideas from the Qt toolkit, specially the cool foreach iterator. TODO Do not use memmove in insert & remove, use copy ctors instead. */ // nvcore #include #include #include #include // memmove #include // for placement new #if NV_CC_GNUC // If typeof is available: #define NV_FOREACH(i, container) \ typedef typeof(container) NV_STRING_JOIN2(cont,__LINE__); \ for(NV_STRING_JOIN2(cont,__LINE__)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i)) /* #define NV_FOREACH(i, container) \ for(typename typeof(container)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i)) */ #else // If typeof not available: struct PseudoIndexWrapper { template PseudoIndexWrapper(const T & container) { nvStaticCheck(sizeof(typename T::PseudoIndex) <= sizeof(memory)); new (memory) typename T::PseudoIndex(container.start()); } // PseudoIndex cannot have a dtor! template typename T::PseudoIndex & operator()(const T * container) { return *reinterpret_cast(memory); } template const typename T::PseudoIndex & operator()(const T * container) const { return *reinterpret_cast(memory); } uint8 memory[4]; // Increase the size if we have bigger enumerators. }; #define NV_FOREACH(i, container) \ for(PseudoIndexWrapper i(container); !(container).isDone(i(&(container))); (container).advance(i(&(container)))) #endif // Declare foreach keyword. #if !defined NV_NO_USE_KEYWORDS # define foreach NV_FOREACH #endif namespace nv { // Templates /// Return the maximum of two values. template inline const T & max(const T & a, const T & b) { //return std::max(a, b); if( a < b ) { return b; } return a; } /// Return the minimum of two values. template inline const T & min(const T & a, const T & b) { //return std::min(a, b); if( b < a ) { return b; } return a; } /// Clamp between two values. template inline const T & clamp(const T & x, const T & a, const T & b) { return min(max(x, a), b); } /// Swap two values. template inline void swap(T & a, T & b) { //return std::swap(a, b); T temp = a; a = b; b = temp; } template struct hash { inline uint sdbm_hash(const void * data_in, uint size, uint h = 5381) { const uint8 * data = (const uint8 *) data_in; uint i = 0; while (i < size) { h = (h << 16) + (h << 6) - h + (uint) data[i++]; } return h; } uint operator()(const Key & k) { return sdbm_hash(&k, sizeof(Key)); } }; template <> struct hash { uint operator()(int x) const { return x; } }; template <> struct hash { uint operator()(uint x) const { return x; } }; /// Delete all the elements of a container. template void deleteAll(T & container) { for(typename T::PseudoIndex i = container.start(); !container.isDone(i); container.advance(i)) { delete container[i]; } } /** Return the next power of two. * @see http://graphics.stanford.edu/~seander/bithacks.html * @warning Behaviour for 0 is undefined. * @note isPowerOfTwo(x) == true -> nextPowerOfTwo(x) == x * @note nextPowerOfTwo(x) = 2 << log2(x-1) */ inline uint nextPowerOfTwo( uint x ) { nvDebugCheck( x != 0 ); #if 1 // On modern CPUs this is as fast as using the bsr instruction. x--; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; return x+1; #else uint p = 1; while( x > p ) { p += p; } return p; #endif } /// Return true if @a n is a power of two. inline bool isPowerOfTwo( uint n ) { return (n & (n-1)) == 0; } /// Simple iterator interface. template struct Iterator { virtual void advance(); virtual bool isDone(); virtual T current(); }; /** * Replacement for std::vector that is easier to debug and provides * some nice foreach enumerators. */ template class NVCORE_CLASS Array { public: /// Ctor. Array() : m_buffer(NULL), m_size(0), m_buffer_size(0) { } /// Copy ctor. Array( const Array & a ) : m_buffer(NULL), m_size(0), m_buffer_size(0) { copy(a.m_buffer, a.m_size); } /// Ctor that initializes the vector with the given elements. Array( const T * ptr, int num ) : m_buffer(NULL), m_size(0), m_buffer_size(0) { copy(ptr, num); } /// Allocate array. explicit Array(uint capacity) : m_buffer(NULL), m_size(0), m_buffer_size(0) { allocate(capacity); } /// Dtor. ~Array() { clear(); allocate(0); } /// Const and save vector access. const T & operator[]( uint index ) const { nvDebugCheck(index < m_size); return m_buffer[index]; } /// Safe vector access. T & operator[] ( uint index ) { nvDebugCheck(index < m_size); return m_buffer[index]; } /// Get vector size. uint size() const { return m_size; } /// Get vector size. uint count() const { return m_size; } /// Get const vector pointer. const T * buffer() const { return m_buffer; } /// Get vector pointer. T * unsecureBuffer() { return m_buffer; } /// Is vector empty. bool isEmpty() const { return m_size == 0; } /// Is a null vector. bool isNull() const { return m_buffer == NULL; } /// Push an element at the end of the vector. void push_back( const T & val ) { uint new_size = m_size + 1; if (new_size > m_buffer_size) { const T copy(val); // create a copy in case value is inside of this array. resize(new_size); m_buffer[new_size-1] = copy; } else { m_size = new_size; new(m_buffer+new_size-1) T(val); } } void pushBack( const T & val ) { push_back(val); } void append( const T & val ) { push_back(val); } /// Qt like push operator. Array & operator<< ( T & t ) { push_back(t); return *this; } /// Pop and return element at the end of the vector. void pop_back() { nvDebugCheck( m_size > 0 ); resize( m_size - 1 ); } void popBack() { pop_back(); } /// Get back element. const T & back() const { nvDebugCheck( m_size > 0 ); return m_buffer[m_size-1]; } /// Get back element. T & back() { nvDebugCheck( m_size > 0 ); return m_buffer[m_size-1]; } /// Get front element. const T & front() const { nvDebugCheck( m_size > 0 ); return m_buffer[0]; } /// Get front element. T & front() { nvDebugCheck( m_size > 0 ); return m_buffer[0]; } /// Check if the given element is contained in the array. bool contains(const T & e) const { for (uint i = 0; i < m_size; i++) { if (m_buffer[i] == e) return true; } return false; } /// Remove the element at the given index. This is an expensive operation! void removeAt( uint index ) { nvCheck(index >= 0 && index < m_size); if( m_size == 1 ) { clear(); } else { m_buffer[index].~T(); memmove( m_buffer+index, m_buffer+index+1, sizeof(T) * (m_size - 1 - index) ); m_size--; } } /// Remove the first instance of the given element. void remove(const T & element) { for(PseudoIndex i = start(); !isDone(i); advance(i)) { removeAt(i); break; } } /// Insert the given element at the given index shifting all the elements up. void insertAt( uint index, const T & val = T() ) { nvCheck( index >= 0 && index <= m_size ); resize( m_size + 1 ); if( index < m_size - 1 ) { memmove( m_buffer+index+1, m_buffer+index, sizeof(T) * (m_size - 1 - index) ); } // Copy-construct into the newly opened slot. new(m_buffer+index) T(val); } /// Append the given data to our vector. void append(const Array & other) { append(other.m_buffer, other.m_size); } /// Append the given data to our vector. void append(const T other[], uint count) { if( count > 0 ) { const uint old_size = m_size; resize(m_size + count); // Must use operator=() to copy elements, in case of side effects (e.g. ref-counting). for( uint i = 0; i < count; i++ ) { m_buffer[old_size + i] = other[i]; } } } /// Remove the given element by replacing it with the last one. void replaceWithLast(uint index) { nvDebugCheck( index < m_size ); m_buffer[index] = back(); (m_buffer+m_size-1)->~T(); m_size--; } /// Resize the vector preserving existing elements. void resize(uint new_size) { uint i; uint old_size = m_size; m_size = new_size; // Destruct old elements (if we're shrinking). for( i = new_size; i < old_size; i++ ) { (m_buffer+i)->~T(); // Explicit call to the destructor } if( m_size == 0 ) { //Allocate(0); // Don't shrink automatically. } else if( m_size <= m_buffer_size/* && m_size > m_buffer_size >> 1*/) { // don't compact yet. nvDebugCheck(m_buffer != NULL); } else { uint new_buffer_size; if( m_buffer_size == 0 ) { // first allocation new_buffer_size = m_size; } else { // growing new_buffer_size = m_size + (m_size >> 2); } allocate( new_buffer_size ); } // Call default constructors for( i = old_size; i < new_size; i++ ) { new(m_buffer+i) T; // placement new } } /// Resize the vector preserving existing elements and initializing the /// new ones with the given value. void resize( uint new_size, const T &elem ) { uint i; uint old_size = m_size; m_size = new_size; // Destruct old elements (if we're shrinking). for( i = new_size; i < old_size; i++ ) { (m_buffer+i)->~T(); // Explicit call to the destructor } if( m_size == 0 ) { //Allocate(0); // Don't shrink automatically. } else if( m_size <= m_buffer_size && m_size > m_buffer_size >> 1 ) { // don't compact yet. } else { uint new_buffer_size; if( m_buffer_size == 0 ) { // first allocation new_buffer_size = m_size; } else { // growing new_buffer_size = m_size + (m_size >> 2); } allocate( new_buffer_size ); } // Call copy constructors for( i = old_size; i < new_size; i++ ) { new(m_buffer+i) T( elem ); // placement new } } /// Tighten the memory used by the container. void tighten() { // TODO Reallocate only if worth. } /// Clear the buffer. void clear() { resize(0); } /// Shrink the allocated vector. void shrink() { if( m_size < m_buffer_size ) { allocate(m_size); } } /// Preallocate space. void reserve(uint desired_size) { if( desired_size > m_buffer_size ) { allocate( desired_size ); } } /// Copy memory to our vector. Resizes the vector if needed. void copy( const T * ptr, uint num ) { resize( num ); for(uint i = 0; i < m_size; i++) { m_buffer[i] = ptr[i]; } } /// Assignment operator. void operator=( const Array & a ) { copy( a.m_buffer, a.m_size ); } /* /// Array serialization. friend Stream & operator<< ( Stream & s, Array & p ) { if( s.isLoading() ) { uint size; s << size; p.resize( size ); } else { s << p.m_size; } for( uint i = 0; i < p.m_size; i++ ) { s << p.m_buffer[i]; } return s; } */ // Array enumerator. typedef uint PseudoIndex; PseudoIndex start() const { return 0; } bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); return i == this->m_size; }; void advance(PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); i++; } #if NV_CC_MSVC T & operator[]( const PseudoIndexWrapper & i ) { return m_buffer[i(this)]; } const T & operator[]( const PseudoIndexWrapper & i ) const { return m_buffer[i(this)]; } #endif /// Swap the members of this vector and the given vector. friend void swap(Array & a, Array & b) { swap(a.m_buffer, b.m_buffer); swap(a.m_size, b.m_size); swap(a.m_buffer_size, b.m_buffer_size); } private: /// Change buffer size. void allocate( uint rsize ) { m_buffer_size = rsize; // free the buffer. if( m_buffer_size == 0 ) { if( m_buffer ) { mem::free( m_buffer ); m_buffer = NULL; } } // realloc the buffer else { if( m_buffer ) m_buffer = (T *) mem::realloc( m_buffer, sizeof(T) * m_buffer_size ); else m_buffer = (T *) mem::malloc( sizeof(T) * m_buffer_size ); } } private: T * m_buffer; uint m_size; uint m_buffer_size; }; /** Thatcher Ulrich's hash table. * * Hash table, linear probing, internal chaining. One * interesting/nice thing about this implementation is that the table * itself is a flat chunk of memory containing no pointers, only * relative indices. If the key and value types of the hash contain * no pointers, then the hash can be serialized using raw IO. Could * come in handy. * * Never shrinks, unless you explicitly clear() it. Expands on * demand, though. For best results, if you know roughly how big your * table will be, default it to that size when you create it. */ template > class NVCORE_CLASS HashMap { NV_FORBID_COPY(HashMap) public: /// Default ctor. HashMap() : entry_count(0), size_mask(-1), table(NULL) { } /// Ctor with size hint. explicit HashMap(int size_hint) : entry_count(0), size_mask(-1), table(NULL) { setCapacity(size_hint); } /// Dtor. ~HashMap() { clear(); } /// Set a new or existing value under the key, to the value. void set(const T& key, const U& value) { int index = findIndex(key); if (index >= 0) { E(index).value = value; return; } // Entry under key doesn't exist. add(key, value); } /// Add a new value to the hash table, under the specified key. void add(const T& key, const U& value) { nvCheck(findIndex(key) == -1); checkExpand(); nvCheck(table != NULL); entry_count++; const uint hash_value = hash_functor()(key); const int index = hash_value & size_mask; Entry * natural_entry = &(E(index)); if (natural_entry->isEmpty()) { // Put the new entry in. new (natural_entry) Entry(key, value, -1, hash_value); } else { // Find a blank spot. int blank_index = index; for (;;) { blank_index = (blank_index + 1) & size_mask; if (E(blank_index).isEmpty()) break; // found it } Entry * blank_entry = &E(blank_index); if (int(natural_entry->hash_value & size_mask) == index) { // Collision. Link into this chain. // Move existing list head. new (blank_entry) Entry(*natural_entry); // placement new, copy ctor // Put the new info in the natural entry. natural_entry->key = key; natural_entry->value = value; natural_entry->next_in_chain = blank_index; natural_entry->hash_value = hash_value; } else { // Existing entry does not naturally // belong in this slot. Existing // entry must be moved. // Find natural location of collided element (i.e. root of chain) int collided_index = natural_entry->hash_value & size_mask; for (;;) { Entry * e = &E(collided_index); if (e->next_in_chain == index) { // Here's where we need to splice. new (blank_entry) Entry(*natural_entry); e->next_in_chain = blank_index; break; } collided_index = e->next_in_chain; nvCheck(collided_index >= 0 && collided_index <= size_mask); } // Put the new data in the natural entry. natural_entry->key = key; natural_entry->value = value; natural_entry->hash_value = hash_value; natural_entry->next_in_chain = -1; } } } /// Remove the first value under the specified key. bool remove(const T& key) { if (table == NULL) { return false; } int index = findIndex(key); if (index < 0) { return false; } Entry * entry = &E(index); if( entry->isEndOfChain() ) { entry->clear(); } else { // Get next entry. Entry & next_entry = E(entry->next_in_chain); // Copy next entry in this place. new (entry) Entry(next_entry); next_entry.clear(); } entry_count--; return true; } /// Remove all entries from the hash table. void clear() { if (table != NULL) { // Delete the entries. for (int i = 0, n = size_mask; i <= n; i++) { Entry * e = &E(i); if (e->isEmpty() == false) { e->clear(); } } mem::free(table); table = NULL; entry_count = 0; size_mask = -1; } } /// Returns true if the hash is empty. bool isEmpty() const { return table == NULL || entry_count == 0; } /** Retrieve the value under the given key. * * If there's no value under the key, then return false and leave * *value alone. * * If there is a value, return true, and set *value to the entry's * value. * * If value == NULL, return true or false according to the * presence of the key, but don't touch *value. */ bool get(const T& key, U* value = NULL) const { int index = findIndex(key); if (index >= 0) { if (value) { *value = E(index).value; // take care with side-effects! } return true; } return false; } /// Determine if the given key is contained in the hash. bool contains(const T & key) const { return get(key); } /// Number of entries in the hash. int size() const { return entry_count; } /// Number of entries in the hash. int count() const { return size(); } /** * Resize the hash table to fit one more entry. Often this * doesn't involve any action. */ void checkExpand() { if (table == NULL) { // Initial creation of table. Make a minimum-sized table. setRawCapacity(16); } else if (entry_count * 3 > (size_mask + 1) * 2) { // Table is more than 2/3rds full. Expand. setRawCapacity(entry_count * 2); } } /// Hint the bucket count to >= n. void resize(int n) { // Not really sure what this means in relation to // STLport's hash_map... they say they "increase the // bucket count to at least n" -- but does that mean // their real capacity after resize(n) is more like // n*2 (since they do linked-list chaining within // buckets?). setCapacity(n); } /** * Size the hash so that it can comfortably contain the given * number of elements. If the hash already contains more * elements than new_size, then this may be a no-op. */ void setCapacity(int new_size) { int new_raw_size = (new_size * 3) / 2; if (new_raw_size < size()) { return; } setRawCapacity(new_raw_size); } /// Behaves much like std::pair. struct Entry { int next_in_chain; // internal chaining for collisions uint hash_value; // avoids recomputing. Worthwhile? T key; U value; Entry() : next_in_chain(-2) {} Entry(const Entry& e) : next_in_chain(e.next_in_chain), hash_value(e.hash_value), key(e.key), value(e.value) { } Entry(const T& k, const U& v, int next, int hash) : next_in_chain(next), hash_value(hash), key(k), value(v) { } bool isEmpty() const { return next_in_chain == -2; } bool isEndOfChain() const { return next_in_chain == -1; } void clear() { key.~T(); // placement delete value.~U(); // placement delete next_in_chain = -2; } }; // HashMap enumerator. typedef int PseudoIndex; PseudoIndex start() const { PseudoIndex i = 0; findNext(i); return i; } bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= size_mask+1); return i == size_mask+1; }; void advance(PseudoIndex & i) const { nvDebugCheck(i <= size_mask+1); i++; findNext(i); } #if NV_CC_GNUC Entry & operator[]( const PseudoIndex & i ) { return E(i); } const Entry & operator[]( const PseudoIndex & i ) const { return E(i); } #elif NV_CC_MSVC Entry & operator[]( const PseudoIndexWrapper & i ) { return E(i(this)); } const Entry & operator[]( const PseudoIndexWrapper & i ) const { return E(i(this)); } #endif private: // Find the index of the matching entry. If no match, then return -1. int findIndex(const T& key) const { if (table == NULL) return -1; uint hash_value = hash_functor()(key); int index = hash_value & size_mask; const Entry * e = &E(index); if (e->isEmpty()) return -1; if (int(e->hash_value & size_mask) != index) return -1; // occupied by a collider for (;;) { nvCheck((e->hash_value & size_mask) == (hash_value & size_mask)); if (e->hash_value == hash_value && e->key == key) { // Found it. return index; } nvDebugCheck(! (e->key == key)); // keys are equal, but hash differs! // Keep looking through the chain. index = e->next_in_chain; if (index == -1) break; // end of chain nvCheck(index >= 0 && index <= size_mask); e = &E(index); nvCheck(e->isEmpty() == false); } return -1; } // Helpers. Entry & E(int index) { nvDebugCheck(table != NULL); nvDebugCheck(index >= 0 && index <= size_mask); return table[index]; } const Entry & E(int index) const { nvDebugCheck(table != NULL); nvDebugCheck(index >= 0 && index <= size_mask); return table[index]; } /** * Resize the hash table to the given size (Rehash the * contents of the current table). The arg is the number of * hash table entries, not the number of elements we should * actually contain (which will be less than this). */ void setRawCapacity(int new_size) { if (new_size <= 0) { // Special case. clear(); return; } // Force new_size to be a power of two. new_size = nextPowerOfTwo(new_size); HashMap new_hash; new_hash.table = (Entry *) mem::malloc(sizeof(Entry) * new_size); nvDebugCheck(new_hash.table != NULL); new_hash.entry_count = 0; new_hash.size_mask = new_size - 1; for (int i = 0; i < new_size; i++) { new_hash.E(i).next_in_chain = -2; // mark empty } // Copy stuff to new_hash if (table != NULL) { for (int i = 0, n = size_mask; i <= n; i++) { Entry * e = &E(i); if (e->isEmpty() == false) { // Insert old entry into new hash. new_hash.add(e->key, e->value); e->clear(); // placement delete of old element } } // Delete our old data buffer. mem::free(table); } // Steal new_hash's data. entry_count = new_hash.entry_count; size_mask = new_hash.size_mask; table = new_hash.table; new_hash.entry_count = 0; new_hash.size_mask = -1; new_hash.table = NULL; } // Move the enumerator to the next valid element. void findNext(PseudoIndex & i) const { while (i <= size_mask && E(i).isEmpty()) { i++; } } int entry_count; int size_mask; Entry * table; }; } // nv namespace #endif // NV_CORE_CONTAINER_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Debug.cpp000066400000000000000000000314511173441656100225350ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include // Extern #if NV_OS_WIN32 //&& NV_CC_MSVC # define WIN32_LEAN_AND_MEAN # define VC_EXTRALEAN # include # include # if NV_CC_MSVC # include # if _MSC_VER < 1300 # define DECLSPEC_DEPRECATED // VC6: change this path to your Platform SDK headers # include // must be XP version of file // include "M:\\dev7\\vs\\devtools\\common\\win32sdk\\include\\dbghelp.h" # else // VC7: ships with updated headers # include # endif # endif #endif #if !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) # include #endif #if NV_OS_LINUX && defined(HAVE_EXECINFO_H) # include // backtrace # if NV_CC_GNUC // defined(HAVE_CXXABI_H) # include # endif #endif #if NV_OS_DARWIN # include // getpid # include # include // sysctl # include # undef HAVE_EXECINFO_H # if defined(HAVE_EXECINFO_H) // only after OSX 10.5 # include // backtrace # if NV_CC_GNUC // defined(HAVE_CXXABI_H) # include # endif # endif #endif #include // std::runtime_error #undef assert // defined on mingw using namespace nv; namespace { static MessageHandler * s_message_handler = NULL; static AssertHandler * s_assert_handler = NULL; static bool s_sig_handler_enabled = false; #if NV_OS_WIN32 && NV_CC_MSVC // Old exception filter. static LPTOP_LEVEL_EXCEPTION_FILTER s_old_exception_filter = NULL; #elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) // Old signal handlers. struct sigaction s_old_sigsegv; struct sigaction s_old_sigtrap; struct sigaction s_old_sigfpe; struct sigaction s_old_sigbus; #endif #if NV_OS_WIN32 && NV_CC_MSVC // TODO write minidump static LONG WINAPI nvTopLevelFilter( struct _EXCEPTION_POINTERS * pExceptionInfo) { NV_UNUSED(pExceptionInfo); /* BOOL (WINAPI * Dump) (HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, PMINIDUMP_EXCEPTION_INFORMATION, PMINIDUMP_USER_STREAM_INFORMATION, PMINIDUMP_CALLBACK_INFORMATION ); AutoString dbghelp_path(512); getcwd(dbghelp_path, 512); dbghelp_path.Append("\\DbgHelp.dll"); nvTranslatePath(dbghelp_path); PiLibrary DbgHelp_lib(dbghelp_path, true); if( !DbgHelp_lib.IsValid() ) { nvDebug("*** 'DbgHelp.dll' not found.\n"); return EXCEPTION_CONTINUE_SEARCH; } if( !DbgHelp_lib.BindSymbol( (void **)&Dump, "MiniDumpWriteDump" ) ) { nvDebug("*** 'DbgHelp.dll' too old.\n"); return EXCEPTION_CONTINUE_SEARCH; } // create the file HANDLE hFile = ::CreateFile( "nv.dmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { nvDebug("*** Failed to create dump file.\n"); return EXCEPTION_CONTINUE_SEARCH; } _MINIDUMP_EXCEPTION_INFORMATION ExInfo; ExInfo.ThreadId = ::GetCurrentThreadId(); ExInfo.ExceptionPointers = pExceptionInfo; ExInfo.ClientPointers = NULL; // write the dump bool ok = Dump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL )!=0; ::CloseHandle(hFile); if( !ok ) { nvDebug("*** Failed to save dump file.\n"); return EXCEPTION_CONTINUE_SEARCH; } nvDebug("--- Dump file saved.\n"); */ return EXCEPTION_CONTINUE_SEARCH; } #elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) // NV_OS_LINUX || NV_OS_DARWIN #if defined(HAVE_EXECINFO_H) // NV_OS_LINUX static bool nvHasStackTrace() { #if NV_OS_DARWIN return backtrace != NULL; #else return true; #endif } static void nvPrintStackTrace(void * trace[], int size, int start=0) { char ** string_array = backtrace_symbols(trace, size); nvDebug( "\nDumping stacktrace:\n" ); for(int i = start; i < size-1; i++ ) { # if NV_CC_GNUC // defined(HAVE_CXXABI_H) char * begin = strchr(string_array[i], '('); char * end = strchr(string_array[i], '+'); if( begin != 0 && begin < end ) { int stat; *end = '\0'; *begin = '\0'; char * module = string_array[i]; char * name = abi::__cxa_demangle(begin+1, 0, 0, &stat); if( name == NULL || begin[1] != '_' || begin[2] != 'Z' ) { nvDebug( " In: [%s] '%s'\n", module, begin+1 ); } else { nvDebug( " In: [%s] '%s'\n", module, name ); } free(name); } else { nvDebug( " In: '%s'\n", string_array[i] ); } # else nvDebug( " In: '%s'\n", string_array[i] ); # endif } nvDebug("\n"); free(string_array); } #endif // defined(HAVE_EXECINFO_H) static void * callerAddress(void * secret) { # if NV_OS_DARWIN # if defined(_STRUCT_MCONTEXT) # if NV_CPU_PPC ucontext_t * ucp = (ucontext_t *)secret; return (void *) ucp->uc_mcontext->__ss.__srr0; # elif NV_CPU_X86 ucontext_t * ucp = (ucontext_t *)secret; return (void *) ucp->uc_mcontext->__ss.__eip; # endif # else # if NV_CPU_PPC ucontext_t * ucp = (ucontext_t *)secret; return (void *) ucp->uc_mcontext->ss.srr0; # elif NV_CPU_X86 ucontext_t * ucp = (ucontext_t *)secret; return (void *) ucp->uc_mcontext->ss.eip; # endif # endif # else # if NV_CPU_X86_64 // #define REG_RIP REG_INDEX(rip) // seems to be 16 ucontext_t * ucp = (ucontext_t *)secret; return (void *)ucp->uc_mcontext.gregs[REG_RIP]; # elif NV_CPU_X86 ucontext_t * ucp = (ucontext_t *)secret; return (void *)ucp->uc_mcontext.gregs[14/*REG_EIP*/]; # elif NV_CPU_PPC ucontext_t * ucp = (ucontext_t *)secret; return (void *) ucp->uc_mcontext.regs->nip; # endif # endif // How to obtain the instruction pointers in different platforms, from mlton's source code. // http://mlton.org/ // OpenBSD && NetBSD // ucp->sc_eip // FreeBSD: // ucp->uc_mcontext.mc_eip // HPUX: // ucp->uc_link // Solaris: // ucp->uc_mcontext.gregs[REG_PC] // Linux hppa: // uc->uc_mcontext.sc_iaoq[0] & ~0x3UL // Linux sparc: // ((struct sigcontext*) secret)->sigc_regs.tpc // Linux sparc64: // ((struct sigcontext*) secret)->si_regs.pc // potentially correct for other archs: // Linux alpha: ucp->m_context.sc_pc // Linux arm: ucp->m_context.ctx.arm_pc // Linux ia64: ucp->m_context.sc_ip & ~0x3UL // Linux mips: ucp->m_context.sc_pc // Linux s390: ucp->m_context.sregs->regs.psw.addr } static void nvSigHandler(int sig, siginfo_t *info, void *secret) { void * pnt = callerAddress(secret); // Do something useful with siginfo_t if (sig == SIGSEGV) { if (pnt != NULL) nvDebug("Got signal %d, faulty address is %p, from %p\n", sig, info->si_addr, pnt); else nvDebug("Got signal %d, faulty address is %p\n", sig, info->si_addr); } else if(sig == SIGTRAP) { nvDebug("Breakpoint hit.\n"); } else { nvDebug("Got signal %d\n", sig); } # if defined(HAVE_EXECINFO_H) if (nvHasStackTrace()) // in case of weak linking { void * trace[64]; int size = backtrace(trace, 64); if (pnt != NULL) { // Overwrite sigaction with caller's address. trace[1] = pnt; } nvPrintStackTrace(trace, size, 1); } # endif // defined(HAVE_EXECINFO_H) exit(0); } #endif // defined(HAVE_SIGNAL_H) #if NV_OS_WIN32 //&& NV_CC_MSVC /** Win32 asset handler. */ struct Win32AssertHandler : public AssertHandler { // Code from Daniel Vogel. static bool isDebuggerPresent() { bool result = false; HINSTANCE kern_lib = LoadLibraryExA( "kernel32.dll", NULL, 0 ); if( kern_lib ) { FARPROC lIsDebuggerPresent = GetProcAddress( kern_lib, "IsDebuggerPresent" ); if( lIsDebuggerPresent && lIsDebuggerPresent() ) { result = true; } FreeLibrary( kern_lib ); } return result; } // Flush the message queue. This is necessary for the message box to show up. static void flushMessageQueue() { MSG msg; while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { if( msg.message == WM_QUIT ) break; TranslateMessage( &msg ); DispatchMessage( &msg ); } } // Assert handler method. virtual int assert( const char * exp, const char * file, int line, const char * func/*=NULL*/ ) { int ret = NV_ABORT_EXIT; StringBuilder error_string; if( func != NULL ) { error_string.format( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line ); nvDebug( error_string ); } else { error_string.format( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line ); nvDebug( error_string ); } #if _DEBUG if( isDebuggerPresent() ) { return NV_ABORT_DEBUG; } flushMessageQueue(); int action = MessageBoxA(NULL, error_string, "Assertion failed", MB_ABORTRETRYIGNORE|MB_ICONERROR); switch( action ) { case IDRETRY: ret = NV_ABORT_DEBUG; break; case IDIGNORE: ret = NV_ABORT_IGNORE; break; case IDABORT: default: ret = NV_ABORT_EXIT; break; } /*if( _CrtDbgReport( _CRT_ASSERT, file, line, module, exp ) == 1 ) { return NV_ABORT_DEBUG; }*/ #endif if( ret == NV_ABORT_EXIT ) { // Exit cleanly. throw std::runtime_error("Assertion failed"); } return ret; } }; #else /** Unix asset handler. */ struct UnixAssertHandler : public AssertHandler { bool isDebuggerPresent() { # if NV_OS_DARWIN int mib[4]; struct kinfo_proc info; size_t size; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = getpid(); size = sizeof(info); info.kp_proc.p_flag = 0; sysctl(mib,4,&info,&size,NULL,0); return ((info.kp_proc.p_flag & P_TRACED) == P_TRACED); # else // if ppid != sid, some process spawned our app, probably a debugger. return getsid(getpid()) != getppid(); # endif } // Assert handler method. virtual int assert(const char * exp, const char * file, int line, const char * func) { if( func != NULL ) { nvDebug( "*** Assertion failed: %s\n On file: %s\n On function: %s\n On line: %d\n ", exp, file, func, line ); } else { nvDebug( "*** Assertion failed: %s\n On file: %s\n On line: %d\n ", exp, file, line ); } # if _DEBUG if( isDebuggerPresent() ) { return NV_ABORT_DEBUG; } # endif # if defined(HAVE_EXECINFO_H) if (nvHasStackTrace()) { void * trace[64]; int size = backtrace(trace, 64); nvPrintStackTrace(trace, size, 2); } # endif // Exit cleanly. throw std::runtime_error("Assertion failed"); } }; #endif } // namespace /// Handle assertion through the asset handler. int nvAbort(const char * exp, const char * file, int line, const char * func) { #if NV_OS_WIN32 //&& NV_CC_MSVC static Win32AssertHandler s_default_assert_handler; #else static UnixAssertHandler s_default_assert_handler; #endif if( s_assert_handler != NULL ) { return s_assert_handler->assert( exp, file, line, func ); } else { return s_default_assert_handler.assert( exp, file, line, func ); } } /// Shows a message through the message handler. void NV_CDECL nvDebug(const char *msg, ...) { va_list arg; va_start(arg,msg); if( s_message_handler != NULL ) { s_message_handler->log( msg, arg ); } va_end(arg); } /// Dump debug info. void debug::dumpInfo() { #if !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) && defined(HAVE_EXECINFO_H) if (nvHasStackTrace()) { void * trace[64]; int size = backtrace(trace, 64); nvPrintStackTrace(trace, size, 1); } #endif } /// Set the debug message handler. void debug::setMessageHandler(MessageHandler * message_handler) { s_message_handler = message_handler; } /// Reset the debug message handler. void debug::resetMessageHandler() { s_message_handler = NULL; } /// Set the assert handler. void debug::setAssertHandler(AssertHandler * assert_handler) { s_assert_handler = assert_handler; } /// Reset the assert handler. void debug::resetAssertHandler() { s_assert_handler = NULL; } /// Enable signal handler. void debug::enableSigHandler() { nvCheck(s_sig_handler_enabled != true); s_sig_handler_enabled = true; #if NV_OS_WIN32 && NV_CC_MSVC s_old_exception_filter = ::SetUnhandledExceptionFilter( nvTopLevelFilter ); #elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) // Install our signal handler struct sigaction sa; sa.sa_sigaction = nvSigHandler; sigemptyset (&sa.sa_mask); sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO; sigaction(SIGSEGV, &sa, &s_old_sigsegv); sigaction(SIGTRAP, &sa, &s_old_sigtrap); sigaction(SIGFPE, &sa, &s_old_sigfpe); sigaction(SIGBUS, &sa, &s_old_sigbus); #endif } /// Disable signal handler. void debug::disableSigHandler() { nvCheck(s_sig_handler_enabled == true); s_sig_handler_enabled = false; #if NV_OS_WIN32 && NV_CC_MSVC ::SetUnhandledExceptionFilter( s_old_exception_filter ); s_old_exception_filter = NULL; #elif !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) sigaction(SIGSEGV, &s_old_sigsegv, NULL); sigaction(SIGTRAP, &s_old_sigtrap, NULL); sigaction(SIGFPE, &s_old_sigfpe, NULL); sigaction(SIGBUS, &s_old_sigbus, NULL); #endif } nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Debug.h000066400000000000000000000066431173441656100222070ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_DEBUG_H #define NV_CORE_DEBUG_H #include #if defined(HAVE_STDARG_H) # include // va_list #endif #define NV_ABORT_DEBUG 1 #define NV_ABORT_IGNORE 2 #define NV_ABORT_EXIT 3 #undef assert // avoid conflicts with assert method. #define nvNoAssert(exp) \ do { \ (void)sizeof(exp); \ } while(0) #if NV_NO_ASSERT # define nvAssert(exp) nvNoAssert(exp) # define nvCheck(exp) nvNoAssert(exp) # define nvDebugAssert(exp) nvNoAssert(exp) # define nvDebugCheck(exp) nvNoAssert(exp) # define nvDebugBreak() nvNoAssert(0) #else // NV_NO_ASSERT # if NV_CC_MSVC // @@ Does this work in msvc-6 and earlier? // @@ Do I have to include ? # define nvDebugBreak() __debugbreak() // define nvDebugBreak() __asm int 3 # elif NV_CC_GNUC && NV_CPU_PPC && NV_OS_DARWIN # define nvDebugBreak() __asm__ volatile ("trap"); # elif NV_CC_GNUC && NV_CPU_X86 && NV_OS_DARWIN # define nvDebugBreak() __asm__ volatile ("int3"); # elif NV_CC_GNUC && NV_CPU_X86 # define nvDebugBreak() __asm__ ( "int %0" : :"I"(3) ) # else # include # define nvDebugBreak() raise(SIGTRAP); // define nvDebugBreak() *((int *)(0)) = 0 # endif # define nvAssertMacro(exp) \ do { \ if(!(exp)) { \ if( nvAbort(#exp, __FILE__, __LINE__, __FUNC__) == NV_ABORT_DEBUG ) { \ nvDebugBreak(); \ } \ } \ } while(false) # define nvAssert(exp) nvAssertMacro(exp) # define nvCheck(exp) nvAssertMacro(exp) # if defined(_DEBUG) # define nvDebugAssert(exp) nvAssertMacro(exp) # define nvDebugCheck(exp) nvAssertMacro(exp) # else // _DEBUG # define nvDebugAssert(exp) nvNoAssert(exp) # define nvDebugCheck(exp) nvNoAssert(exp) # endif // _DEBUG #endif // NV_NO_ASSERT // Use nvAssume for very simple expresions only: nvAssume(0), nvAssume(value == true), etc. #if defined(_DEBUG) # if NV_CC_MSVC # define nvAssume(exp) __assume(exp) # else # define nvAssume(exp) nvCheck(exp) # endif #else # define nvAssume(exp) nvCheck(exp) #endif #define nvError(x) nvAbort(x, __FILE__, __LINE__, __FUNC__) #define nvWarning(x) nvDebug("*** Warning %s/%d: %s\n", __FILE__, __LINE__, (x)) #if PI_CC_MSVC // @@ I'm not sure it's a good idea to use the default static assert. # define nvStaticCheck(x) _STATIC_ASSERT(x) #else # define nvStaticCheck(x) typedef char NV_DO_STRING_JOIN2(__static_assert_,__LINE__)[(x)] // define nvStaticCheck(x) switch(0) { case 0: case x:; } #endif NVCORE_API int nvAbort(const char *exp, const char *file, int line, const char * func = 0); NVCORE_API void NV_CDECL nvDebug( const char *msg, ... ) __attribute__((format (printf, 1, 2))); namespace nv { /** Message handler interface. */ struct MessageHandler { virtual void log(const char * str, va_list arg) = 0; virtual ~MessageHandler() {} }; /** Assert handler interface. */ struct AssertHandler { virtual int assert(const char *exp, const char *file, int line, const char *func = 0) = 0; virtual ~AssertHandler() {} }; namespace debug { NVCORE_API void dumpInfo(); // These functions are not thread safe. NVCORE_API void setMessageHandler( MessageHandler * messageHandler ); NVCORE_API void resetMessageHandler(); NVCORE_API void setAssertHandler( AssertHandler * assertHanlder ); NVCORE_API void resetAssertHandler(); NVCORE_API void enableSigHandler(); NVCORE_API void disableSigHandler(); } } // nv namespace #endif // NV_CORE_DEBUG_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/DefsGnucDarwin.h000066400000000000000000000025161173441656100240170ustar00rootroot00000000000000#ifndef NV_CORE_H #error "Do not include this file directly." #endif #include // uint8_t, int8_t, ... // Function linkage #define DLL_IMPORT #if __GNUC__ >= 4 # define DLL_EXPORT __attribute__((visibility("default"))) # define DLL_EXPORT_CLASS DLL_EXPORT #else # define DLL_EXPORT # define DLL_EXPORT_CLASS #endif // Function calling modes #if NV_CPU_X86 # define NV_CDECL __attribute__((cdecl)) # define NV_STDCALL __attribute__((stdcall)) #else # define NV_CDECL # define NV_STDCALL #endif #define NV_FASTCALL __attribute__((fastcall)) #define NV_FORCEINLINE __attribute__((always_inline)) #define NV_DEPRECATED __attribute__((deprecated)) #if __GNUC__ > 2 #define NV_PURE __attribute__((pure)) #define NV_CONST __attribute__((const)) #else #define NV_PURE #define NV_CONST #endif // Define __FUNC__ properly. #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__ # else # define __FUNC__ "" # endif #else # define __FUNC__ __PRETTY_FUNCTION__ #endif #define restrict __restrict__ // Type definitions typedef uint8_t uint8; typedef int8_t int8; typedef uint16_t uint16; typedef int16_t int16; typedef uint32_t uint32; typedef int32_t int32; typedef uint64_t uint64; typedef int64_t int64; // Aliases typedef uint32 uint; nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/DefsGnucLinux.h000066400000000000000000000025651173441656100236760ustar00rootroot00000000000000#ifndef NV_CORE_H #error "Do not include this file directly." #endif // Function linkage #define DLL_IMPORT #if __GNUC__ >= 4 # define DLL_EXPORT __attribute__((visibility("default"))) # define DLL_EXPORT_CLASS DLL_EXPORT #else # define DLL_EXPORT # define DLL_EXPORT_CLASS #endif // Function calling modes #if NV_CPU_X86 # define NV_CDECL __attribute__((cdecl)) # define NV_STDCALL __attribute__((stdcall)) #else # define NV_CDECL # define NV_STDCALL #endif #define NV_FASTCALL __attribute__((fastcall)) #define NV_FORCEINLINE __attribute__((always_inline)) #define NV_DEPRECATED __attribute__((deprecated)) #if __GNUC__ > 2 #define NV_PURE __attribute__((pure)) #define NV_CONST __attribute__((const)) #else #define NV_PURE #define NV_CONST #endif // Define __FUNC__ properly. #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__ # else # define __FUNC__ "" # endif #else # define __FUNC__ __PRETTY_FUNCTION__ #endif #define restrict __restrict__ // Type definitions typedef unsigned char uint8; typedef signed char int8; typedef unsigned short uint16; typedef signed short int16; typedef unsigned int uint32; typedef signed int int32; typedef unsigned long long uint64; typedef signed long long int64; // Aliases typedef uint32 uint; nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/DefsGnucWin32.h000066400000000000000000000023461173441656100234760ustar00rootroot00000000000000#ifndef NV_CORE_H #error "Do not include this file directly." #endif // Function linkage #define DLL_IMPORT __declspec(dllimport) #define DLL_EXPORT __declspec(dllexport) #define DLL_EXPORT_CLASS DLL_EXPORT // Function calling modes #if NV_CPU_X86 # define NV_CDECL __attribute__((cdecl)) # define NV_STDCALL __attribute__((stdcall)) #else # define NV_CDECL # define NV_STDCALL #endif #define NV_FASTCALL __attribute__((fastcall)) #define NV_FORCEINLINE __attribute__((always_inline)) #define NV_DEPRECATED __attribute__((deprecated)) #if __GNUC__ > 2 #define NV_PURE __attribute__((pure)) #define NV_CONST __attribute__((const)) #else #define NV_PURE #define NV_CONST #endif // Define __FUNC__ properly. #if __STDC_VERSION__ < 199901L # if __GNUC__ >= 2 # define __FUNC__ __PRETTY_FUNCTION__ // __FUNCTION__ # else # define __FUNC__ "" # endif #else # define __FUNC__ __PRETTY_FUNCTION__ #endif #define restrict __restrict__ // Type definitions typedef unsigned char uint8; typedef signed char int8; typedef unsigned short uint16; typedef signed short int16; typedef unsigned int uint32; typedef signed int int32; typedef unsigned long long uint64; typedef signed long long int64; // Aliases typedef uint32 uint; nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/DefsVcWin32.h000066400000000000000000000042601173441656100231470ustar00rootroot00000000000000#ifndef NV_CORE_H #error "Do not include this file directly." #endif // Function linkage #define DLL_IMPORT __declspec(dllimport) #define DLL_EXPORT __declspec(dllexport) #define DLL_EXPORT_CLASS DLL_EXPORT // Function calling modes #define NV_CDECL __cdecl #define NV_STDCALL __stdcall #define NV_FASTCALL __fastcall #define NV_FORCEINLINE __forceinline #define NV_DEPRECATED #define NV_PURE #define NV_CONST // Set standard function names. #define snprintf _snprintf #if _MSC_VER < 1500 # define vsnprintf _vsnprintf #endif #define vsscanf _vsscanf #define chdir _chdir #define getcwd _getcwd #define va_copy(a, b) a = b #if !defined restrict #define restrict #endif // Ignore gcc attributes. #define __attribute__(X) #if !defined __FUNC__ #define __FUNC__ __FUNCTION__ #endif // Type definitions typedef unsigned char uint8; typedef signed char int8; typedef unsigned short uint16; typedef signed short int16; typedef unsigned int uint32; typedef signed int int32; typedef unsigned __int64 uint64; typedef signed __int64 int64; // Aliases typedef uint32 uint; // Unwanted VC++ warnings to disable. /* #pragma warning(disable : 4244) // conversion to float, possible loss of data #pragma warning(disable : 4245) // conversion from 'enum ' to 'unsigned long', signed/unsigned mismatch #pragma warning(disable : 4100) // unreferenced formal parameter #pragma warning(disable : 4514) // unreferenced inline function has been removed #pragma warning(disable : 4710) // inline function not expanded #pragma warning(disable : 4127) // Conditional expression is constant #pragma warning(disable : 4305) // truncation from 'const double' to 'float' #pragma warning(disable : 4505) // unreferenced local function has been removed #pragma warning(disable : 4702) // unreachable code in inline expanded function #pragma warning(disable : 4711) // function selected for automatic inlining #pragma warning(disable : 4725) // Pentium fdiv bug #pragma warning(disable : 4786) // Identifier was truncated and cannot be debugged. #pragma warning(disable : 4675) // resolved overload was found by argument-dependent lookup */ nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Library.cpp000066400000000000000000000012171173441656100231100ustar00rootroot00000000000000 #include "Library.h" #include "Debug.h" #if NV_OS_WIN32 #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #include #else #include #endif void * nvLoadLibrary(const char * name) { #if NV_OS_WIN32 return (void *)LoadLibraryExA( name, NULL, 0 ); #else return dlopen(name, RTLD_LAZY); #endif } void nvUnloadLibrary(void * handle) { nvDebugCheck(handle != NULL); #if NV_OS_WIN32 FreeLibrary((HMODULE)handle); #else dlclose(handle); #endif } void * nvBindSymbol(void * handle, const char * symbol) { #if NV_OS_WIN32 return (void *)GetProcAddress((HMODULE)handle, symbol); #else return (void *)dlsym(handle, symbol); #endif } nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Library.h000066400000000000000000000015431173441656100225570ustar00rootroot00000000000000// This code is in the public domain -- castano@gmail.com #ifndef NV_CORE_LIBRARY_H #define NV_CORE_LIBRARY_H #include #if NV_OS_WIN32 #define LIBRARY_NAME(name) #name ".dll" #elif NV_OS_DARWIN #define NV_LIBRARY_NAME(name) "lib" #name ".dylib" #else #define NV_LIBRARY_NAME(name) "lib" #name ".so" #endif NVCORE_API void * nvLoadLibrary(const char * name); NVCORE_API void nvUnloadLibrary(void * lib); NVCORE_API void * nvBindSymbol(void * lib, const char * symbol); class NVCORE_CLASS Library { public: Library(const char * name) { handle = nvLoadLibrary(name); } ~Library() { if (isValid()) { nvUnloadLibrary(handle); } } bool isValid() const { return handle != NULL; } void * bindSymbol(const char * symbol) { return nvBindSymbol(handle, symbol); } private: void * handle; }; #endif // NV_CORE_LIBRARY_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Memory.cpp000066400000000000000000000010631173441656100227530ustar00rootroot00000000000000 #include "Memory.h" #include "Debug.h" //#if HAVE_MALLOC_H //#include //#endif #include using namespace nv; void * nv::mem::malloc(size_t size) { return ::malloc(size); } void * nv::mem::malloc(size_t size, const char * file, int line) { NV_UNUSED(file); NV_UNUSED(line); return ::malloc(size); } void nv::mem::free(const void * ptr) { ::free(const_cast(ptr)); } void * nv::mem::realloc(void * ptr, size_t size) { nvDebugCheck(ptr != NULL || size != 0); // undefined realloc behavior. return ::realloc(ptr, size); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Memory.h000066400000000000000000000145731173441656100224320ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_MEMORY_H #define NV_CORE_MEMORY_H #include #include // malloc(), realloc() and free() #include // size_t #include // new and delete // Custom memory allocator namespace nv { namespace mem { NVCORE_API void * malloc(size_t size); NVCORE_API void * malloc(size_t size, const char * file, int line); NVCORE_API void free(const void * ptr); NVCORE_API void * realloc(void * ptr, size_t size); } // mem namespace } // nv namespace // Override new/delete inline void * operator new (size_t size) throw() { return nv::mem::malloc(size); } inline void operator delete (void *p) throw() { nv::mem::free(p); } inline void * operator new [] (size_t size) throw() { return nv::mem::malloc(size); } inline void operator delete [] (void * p) throw() { nv::mem::free(p); } /* #ifdef _DEBUG #define new new(__FILE__, __LINE__) #define malloc(i) malloc(i, __FILE__, __LINE__) #endif */ #if 0 /* File: main.cpp Version: 1.0 Abstract: Overrides the C++ 'operator new' and 'operator delete'. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Computer, Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Copyright © 2006 Apple Computer, Inc., All Rights Reserved */ /* This sample shows how to override the C++ global 'new' and 'delete' operators. */ #include #include #include #include #include /* Some variables and code to make the example do something. */ namespace { unsigned long long gNewCounter; // number of times 'new' was called unsigned long long gDeleteCounter; // number of times 'delete' was called void printCounters() // print the counters above { std::cout << "new was called " << gNewCounter << " times and delete was called " << gDeleteCounter << " times\n"; } } /* These are the overridden new and delete routines. Most applications will want to override at least these four versions of new/delete if they override any of them. In Mac OS, it's not necessary to override the array versions of operator new and delete if all they would do is call the non-array versions; the C++ standard library, as an extension to the C++ standard, does this for you. Developers should consult the section [lib.support.dynamic] in the C++ standard to see the requirements on the generic operators new and delete; the system may expect that your overridden operators meet all these requirements. Your operators may be called by the system, even early in start-up before constructors have been executed. */ void* operator new(std::size_t sz) throw (std::bad_alloc) { void *result = std::malloc (sz == 0 ? 1 : sz); if (result == NULL) throw std::bad_alloc(); gNewCounter++; return result; } void operator delete(void* p) throw() { if (p == NULL) return; std::free (p); gDeleteCounter++; } /* These are the 'nothrow' versions of the above operators. The system version will try to call a std::new_handler if they fail, but your overriding versions are not required to do this. */ void* operator new(std::size_t sz, const std::nothrow_t&) throw() { try { void * result = ::operator new (sz); // calls our overridden operator new return result; } catch (std::bad_alloc &) { return NULL; } } void operator delete(void* p, const std::nothrow_t&) throw() { ::operator delete (p); } /* Bug 4067110 is that if your program has no weak symbols at all, the linker will not set the WEAK_DEFINES bit in the Mach-O header and as a result the new and delete operators above won't be seen by system libraries. This is mostly a problem for test programs and small examples, since almost all real C++ programs complicated enough to override new and delete will have at least one weak symbol. However, this is a small example, so: */ void __attribute__((weak, visibility("default"))) workaroundFor4067110 () { } /* This is a simple test program that causes the runtime library to call new and delete. */ int main() { atexit (printCounters); try { std::locale example("does_not_exist"); } catch (std::runtime_error &x) { } return 0; } #endif // 0 #endif // NV_CORE_MEMORY_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Prefetch.h000066400000000000000000000010201173441656100227010ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_PREFETCH_H #define NV_CORE_PREFETCH_H #include // nvPrefetch #if NV_CC_GNUC #define nvPrefetch(ptr) __builtin_prefetch(ptr) #elif NV_CC_MSVC #if NV_CPU_X86 __forceinline void nvPrefetch(const void * mem) { __asm mov ecx, mem __asm prefetcht0 [ecx]; // __asm prefetchnta [ecx]; } #endif // NV_CPU_X86 #else // NV_CC_MSVC // do nothing in other case. #define nvPrefetch(ptr) #endif // NV_CC_MSVC #endif // NV_CORE_PREFETCH_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Ptr.h000066400000000000000000000146721173441656100217270ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_PTR_H #define NV_CORE_PTR_H #include #include #include // NULL namespace nv { /** Simple auto pointer template class. * * This is very similar to the standard auto_ptr class, but with some * additional limitations to make its use less error prone: * - Copy constructor and assignment operator are disabled. * - reset method is removed. * * The semantics of the standard auto_ptr are not clear and change depending * on the std implementation. For a discussion of the problems of auto_ptr read: * http://www.awprofessional.com/content/images/020163371X/autoptrupdate\auto_ptr_update.html */ template class AutoPtr { NV_FORBID_COPY(AutoPtr); NV_FORBID_HEAPALLOC(); public: /// Default ctor. AutoPtr() : m_ptr(NULL) { } /// Ctor. explicit AutoPtr( T * p ) : m_ptr(p) { } /** Dtor. Deletes owned pointer. */ ~AutoPtr() { delete m_ptr; m_ptr = NULL; } /** Delete owned pointer and assign new one. */ void operator=( T * p ) { if (p != m_ptr) { delete m_ptr; m_ptr = p; } } /** Member access. */ T * operator -> () const { nvDebugCheck(m_ptr != NULL); return m_ptr; } /** Get reference. */ T & operator*() const { nvDebugCheck(m_ptr != NULL); return *m_ptr; } /** Get pointer. */ T * ptr() const { return m_ptr; } /** Relinquish ownership of the underlying pointer and returns that pointer. */ T * release() { T * tmp = m_ptr; m_ptr = NULL; return tmp; } /** Const pointer equal comparation. */ friend bool operator == (const AutoPtr & ap, const T * const p) { return (ap.ptr() == p); } /** Const pointer nequal comparation. */ friend bool operator != (const AutoPtr & ap, const T * const p) { return (ap.ptr() != p); } /** Const pointer equal comparation. */ friend bool operator == (const T * const p, const AutoPtr & ap) { return (ap.ptr() == p); } /** Const pointer nequal comparation. */ friend bool operator != (const T * const p, const AutoPtr & ap) { return (ap.ptr() != p); } private: T * m_ptr; }; #if 0 /** Reference counted base class to be used with Pointer. * * The only requirement of the Pointer class is that the RefCounted class implements the * addRef and release methods. */ class RefCounted { NV_FORBID_COPY(RefCounted); public: /// Ctor. RefCounted() : m_count(0), m_weak_proxy(NULL) { s_total_obj_count++; } /// Virtual dtor. virtual ~RefCounted() { nvCheck( m_count == 0 ); nvCheck( s_total_obj_count > 0 ); s_total_obj_count--; } /// Increase reference count. uint addRef() const { s_total_ref_count++; m_count++; return m_count; } /// Decrease reference count and remove when 0. uint release() const { nvCheck( m_count > 0 ); s_total_ref_count--; m_count--; if( m_count == 0 ) { releaseWeakProxy(); delete this; return 0; } return m_count; } /// Get weak proxy. WeakProxy * getWeakProxy() const { if (m_weak_proxy == NULL) { m_weak_proxy = new WeakProxy; m_weak_proxy->AddRef(); } return m_weak_proxy; } /// Release the weak proxy. void releaseWeakProxy() const { if (m_weak_proxy != NULL) { m_weak_proxy->NotifyObjectDied(); m_weak_proxy->Release(); m_weak_proxy = NULL; } } /** @name Debug methods: */ //@{ /// Get reference count. int refCount() const { return m_count; } /// Get total number of objects. static int totalObjectCount() { return s_total_obj_count; } /// Get total number of references. static int totalReferenceCount() { return s_total_ref_count; } //@} private: NVCORE_API static int s_total_ref_count; NVCORE_API static int s_total_obj_count; mutable int m_count; mutable WeakProxy * weak_proxy; }; #endif /// Smart pointer template class. template class Pointer { public: // BaseClass must implement addRef() and release(). typedef Pointer ThisType; /// Default ctor. Pointer() : m_ptr(NULL) { } /** Other type assignment. */ template Pointer( const Pointer & tc ) { m_ptr = static_cast( tc.ptr() ); if( m_ptr ) { m_ptr->addRef(); } } /** Copy ctor. */ Pointer( const ThisType & bc ) { m_ptr = bc.ptr(); if( m_ptr ) { m_ptr->addRef(); } } /** Copy cast ctor. Pointer(NULL) is valid. */ explicit Pointer( BaseClass * bc ) { m_ptr = bc; if( m_ptr ) { m_ptr->addRef(); } } /** Dtor. */ ~Pointer() { set(NULL); } /** @name Accessors: */ //@{ /** -> operator. */ BaseClass * operator -> () const { nvCheck( m_ptr != NULL ); return m_ptr; } /** * operator. */ BaseClass & operator*() const { nvCheck( m_ptr != NULL ); return *m_ptr; } /** Get pointer. */ BaseClass * ptr() const { return m_ptr; } //@} /** @name Mutators: */ //@{ /** Other type assignment. */ template void operator = ( const Pointer & tc ) { set( static_cast(tc.ptr()) ); } /** This type assignment. */ void operator = ( const ThisType & bc ) { set( bc.ptr() ); } /** Pointer assignment. */ void operator = ( BaseClass * bc ) { set( bc ); } //@} /** @name Comparators: */ //@{ /** Other type equal comparation. */ template bool operator == ( const Pointer & other ) const { return m_ptr == other.ptr(); } /** This type equal comparation. */ bool operator == ( const ThisType & bc ) const { return m_ptr == bc.ptr(); } /** Const pointer equal comparation. */ bool operator == ( const BaseClass * const bc ) const { return m_ptr == bc; } /** Other type not equal comparation. */ template bool operator != ( const Pointer & other ) const { return m_ptr != other.ptr(); } /** Other type not equal comparation. */ bool operator != ( const ThisType & bc ) const { return m_ptr != bc.ptr(); } /** Const pointer not equal comparation. */ bool operator != (const BaseClass * const bc) const { return m_ptr != bc; } /** This type lower than comparation. */ bool operator < (const ThisType & p) const { return m_ptr < p.ptr(); } //@} private: /** Set this pointer. */ void set( BaseClass * p ) { if( m_ptr != p ) { if( m_ptr ) m_ptr->release(); if( p ) p->addRef(); m_ptr = p; } } private: BaseClass * m_ptr; }; } // nv namespace #endif // NV_CORE_PTR_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Radix.cpp000066400000000000000000000433731173441656100225640ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Contains source code from the article "Radix Sort Revisited". * \file Radix.cpp * \author Pierre Terdiman * \date April, 4, 2000 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Revisited Radix Sort. * This is my new radix routine: * - it uses indices and doesn't recopy the values anymore, hence wasting less ram * - it creates all the histograms in one run instead of four * - it sorts words faster than dwords and bytes faster than words * - it correctly sorts negative floating-point values by patching the offsets * - it automatically takes advantage of temporal coherence * - multiple keys support is a side effect of temporal coherence * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway] * * History: * - 08.15.98: very first version * - 04.04.00: recoded for the radix article * - 12.xx.00: code lifting * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here) * - 10.11.01: added local ram support * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting...... * * \class RadixSort * \author Pierre Terdiman * \version 1.3 * \date August, 15, 1998 */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* To do: - add an offset parameter between two input values (avoid some data recopy sometimes) - unroll ? asm ? */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Header #include #include // memset //using namespace IceCore; #define DELETEARRAY(a) { delete [] a; a = NULL; } #define CHECKALLOC(a) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Constructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RadixSort::RadixSort() : mCurrentSize(0), mPreviousSize(0), mIndices(NULL), mIndices2(NULL), mTotalCalls(0), mNbHits(0) { #ifndef RADIX_LOCAL_RAM // Allocate input-independent ram mHistogram = new uint32[256*4]; mOffset = new uint32[256]; #endif // Initialize indices resetIndices(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Destructor. */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RadixSort::~RadixSort() { // Release everything #ifndef RADIX_LOCAL_RAM DELETEARRAY(mOffset); DELETEARRAY(mHistogram); #endif DELETEARRAY(mIndices2); DELETEARRAY(mIndices); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Resizes the inner lists. * \param nb [in] new size (number of dwords) * \return true if success */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// bool RadixSort::resize(uint32 nb) { // Free previously used ram DELETEARRAY(mIndices2); DELETEARRAY(mIndices); // Get some fresh one mIndices = new uint32[nb]; CHECKALLOC(mIndices); mIndices2 = new uint32[nb]; CHECKALLOC(mIndices2); mCurrentSize = nb; // Initialize indices so that the input buffer is read in sequential order resetIndices(); return true; } #define CHECK_RESIZE(n) \ if(n!=mPreviousSize) \ { \ if(n>mCurrentSize) resize(n); \ else resetIndices(); \ mPreviousSize = n; \ } #define CREATE_HISTOGRAMS(type, buffer) \ /* Clear counters */ \ memset(mHistogram, 0, 256*4*sizeof(uint32)); \ \ /* Prepare for temporal coherence */ \ type PrevVal = (type)buffer[mIndices[0]]; \ bool AlreadySorted = true; /* Optimism... */ \ uint32* Indices = mIndices; \ \ /* Prepare to count */ \ uint8* p = (uint8*)input; \ uint8* pe = &p[nb*4]; \ uint32* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \ uint32* h1= &mHistogram[256]; /* Histogram for second pass */ \ uint32* h2= &mHistogram[512]; /* Histogram for third pass */ \ uint32* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \ \ while(p!=pe) \ { \ /* Read input buffer in previous sorted order */ \ type Val = (type)buffer[*Indices++]; \ /* Check whether already sorted or not */ \ if(Val>24; // Radix byte, same as above. AND is useless here (uint32). // ### cmp to be killed. Not good. Later. if(Radix<128) mIndices2[mOffset[Radix]++] = mIndices[i]; // Number is positive, same as above else mIndices2[--mOffset[Radix]] = mIndices[i]; // Number is negative, flip the sorting order } // Swap pointers for next pass. Valid indices - the most recent ones - are in mIndices after the swap. uint32* Tmp = mIndices; mIndices = mIndices2; mIndices2 = Tmp; } else { // The pass is useless, yet we still have to reverse the order of current list if all values are negative. if(UniqueVal>=128) { for(i=0;i #define RADIX_LOCAL_RAM class NVCORE_API RadixSort { NV_FORBID_COPY(RadixSort); public: // Constructor/Destructor RadixSort(); ~RadixSort(); // Sorting methods RadixSort & sort(const uint32* input, uint32 nb, bool signedvalues=true); RadixSort & sort(const float* input, uint32 nb); //! Access to results. mIndices is a list of indices in sorted order, i.e. in the order you may further process your data inline uint32 * indices() const { return mIndices; } //! mIndices2 gets trashed on calling the sort routine, but otherwise you can recycle it the way you want. inline uint32 * recyclable() const { return mIndices2; } // Stats uint32 usedRam() const; //! Returns the total number of calls to the radix sorter. inline uint32 totalCalls() const { return mTotalCalls; } //! Returns the number of premature exits due to temporal coherence. inline uint32 hits() const { return mNbHits; } private: #ifndef RADIX_LOCAL_RAM uint32* mHistogram; //!< Counters for each byte uint32* mOffset; //!< Offsets (nearly a cumulative distribution function) #endif uint32 mCurrentSize; //!< Current size of the indices list uint32 mPreviousSize; //!< Size involved in previous call uint32* mIndices; //!< Two lists, swapped each pass uint32* mIndices2; // Stats uint32 mTotalCalls; uint32 mNbHits; // Internal methods bool resize(uint32 nb); void resetIndices(); }; #endif // NV_CORE_RADIXSORT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/StdStream.h000066400000000000000000000134701173441656100230630ustar00rootroot00000000000000#ifndef NV_STDSTREAM_H #define NV_STDSTREAM_H #include #include // fopen #include // memcpy #include // std::exception namespace nv { // Portable version of fopen. inline FILE * fileOpen(const char * fileName, const char * mode) { nvCheck(fileName != NULL); #if NV_CC_MSVC && _MSC_VER >= 1400 FILE * fp; if (fopen_s(&fp, fileName, mode) == 0) { return fp; } return NULL; #else return fopen(fileName, mode); #endif } /// Base stdio stream. class NVCORE_CLASS StdStream : public Stream { NV_FORBID_COPY(StdStream); public: /// Ctor. StdStream( FILE * fp, bool autoclose=true ) : m_fp(fp), m_autoclose(autoclose) { } /// Dtor. virtual ~StdStream() { if( m_fp != NULL && m_autoclose ) { fclose( m_fp ); } } /** @name Stream implementation. */ //@{ virtual void seek( uint pos ) { nvDebugCheck(m_fp != NULL); nvDebugCheck(pos < size()); fseek(m_fp, pos, SEEK_SET); } virtual uint tell() const { nvDebugCheck(m_fp != NULL); return ftell(m_fp); } virtual uint size() const { nvDebugCheck(m_fp != NULL); uint pos = ftell(m_fp); fseek(m_fp, 0, SEEK_END); uint end = ftell(m_fp); fseek(m_fp, pos, SEEK_SET); return end; } virtual bool isError() const { return m_fp == NULL || ferror( m_fp ) != 0; } virtual void clearError() { nvDebugCheck(m_fp != NULL); clearerr(m_fp); } virtual bool isAtEnd() const { nvDebugCheck(m_fp != NULL); return feof( m_fp ) != 0; } /// Always true. virtual bool isSeekable() const { return true; } //@} protected: FILE * m_fp; bool m_autoclose; }; /// Standard output stream. class NVCORE_CLASS StdOutputStream : public StdStream { NV_FORBID_COPY(StdOutputStream); public: /// Construct stream by file name. StdOutputStream( const char * name ) : StdStream(fileOpen(name, "wb")) { } /// Construct stream by file handle. StdOutputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose) { } /** @name Stream implementation. */ //@{ /// Write data. virtual uint serialize( void * data, uint len ) { nvDebugCheck(data != NULL); nvDebugCheck(m_fp != NULL); return (uint)fwrite(data, 1, len, m_fp); } virtual bool isLoading() const { return false; } virtual bool isSaving() const { return true; } //@} }; /// Standard input stream. class NVCORE_CLASS StdInputStream : public StdStream { NV_FORBID_COPY(StdInputStream); public: /// Construct stream by file name. StdInputStream( const char * name ) : StdStream(fileOpen(name, "rb")) { } /// Construct stream by file handle. StdInputStream( FILE * fp, bool autoclose=true ) : StdStream(fp, autoclose) { } /** @name Stream implementation. */ //@{ /// Read data. virtual uint serialize( void * data, uint len ) { nvDebugCheck(data != NULL); nvDebugCheck(m_fp != NULL); return (uint)fread(data, 1, len, m_fp); } virtual bool isLoading() const { return true; } virtual bool isSaving() const { return false; } //@} }; /// Memory input stream. class NVCORE_CLASS MemoryInputStream : public Stream { NV_FORBID_COPY(MemoryInputStream); public: /// Ctor. MemoryInputStream( const uint8 * mem, uint size ) : m_mem(mem), m_ptr(mem), m_size(size) { } /** @name Stream implementation. */ //@{ /// Read data. virtual uint serialize( void * data, uint len ) { nvDebugCheck(data != NULL); nvDebugCheck(!isError()); uint left = m_size - tell(); if (len > left) len = left; memcpy( data, m_ptr, len ); m_ptr += len; return len; } virtual void seek( uint pos ) { nvDebugCheck(!isError()); m_ptr = m_mem + pos; nvDebugCheck(!isError()); } virtual uint tell() const { nvDebugCheck(m_ptr >= m_mem); return uint(m_ptr - m_mem); } virtual uint size() const { return m_size; } virtual bool isError() const { return m_mem == NULL || m_ptr > m_mem + m_size || m_ptr < m_mem; } virtual void clearError() { // Nothing to do. } virtual bool isAtEnd() const { return m_ptr == m_mem + m_size; } /// Always true. virtual bool isSeekable() const { return true; } virtual bool isLoading() const { return true; } virtual bool isSaving() const { return false; } //@} private: const uint8 * m_mem; const uint8 * m_ptr; uint m_size; }; /// Protected input stream. class NVCORE_CLASS ProtectedStream : public Stream { NV_FORBID_COPY(ProtectedStream); public: /// Ctor. ProtectedStream( Stream & s ) : m_s(&s), m_autodelete(false) { } /// Ctor. ProtectedStream( Stream * s, bool autodelete = true ) : m_s(s), m_autodelete(autodelete) { nvDebugCheck(m_s != NULL); } /// Dtor. virtual ~ProtectedStream() { if( m_autodelete ) { delete m_s; } } /** @name Stream implementation. */ //@{ /// Read data. virtual uint serialize( void * data, uint len ) { nvDebugCheck(data != NULL); len = m_s->serialize( data, len ); if( m_s->isError() ) { throw std::exception(); } return len; } virtual void seek( uint pos ) { m_s->seek( pos ); if( m_s->isError() ) { throw std::exception(); } } virtual uint tell() const { return m_s->tell(); } virtual uint size() const { return m_s->size(); } virtual bool isError() const { return m_s->isError(); } virtual void clearError() { m_s->clearError(); } virtual bool isAtEnd() const { return m_s->isAtEnd(); } virtual bool isSeekable() const { return m_s->isSeekable(); } virtual bool isLoading() const { return m_s->isLoading(); } virtual bool isSaving() const { return m_s->isSaving(); } //@} private: Stream * const m_s; bool const m_autodelete; }; } // nv namespace #endif // NV_STDSTREAM_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/StrLib.cpp000066400000000000000000000251351173441656100227100ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include // log #include // vsnprintf #if NV_CC_MSVC #include // vsnprintf #endif #if NV_OS_WIN32 #define NV_PATH_SEPARATOR '\\' #else #define NV_PATH_SEPARATOR '/' #endif using namespace nv; namespace { static char * strAlloc(uint size) { return static_cast(mem::malloc(size)); } static char * strReAlloc(char * str, uint size) { return static_cast(mem::realloc(str, size)); } static void strFree(const char * str) { return mem::free(const_cast(str)); } /*static char * strDup( const char * str ) { nvDebugCheck( str != NULL ); uint len = uint(strlen( str ) + 1); char * dup = strAlloc( len ); memcpy( dup, str, len ); return dup; }*/ // helper function for integer to string conversion. static char * i2a( uint i, char *a, uint r ) { if( i / r > 0 ) { a = i2a( i / r, a, r ); } *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % r]; return a + 1; } // Locale independent functions. static inline char toUpper( char c ) { return (c<'a' || c>'z') ? (c) : (c+'A'-'a'); } static inline char toLower( char c ) { return (c<'A' || c>'Z') ? (c) : (c+'a'-'A'); } static inline bool isAlpha( char c ) { return (c>='a' && c<='z') || (c>='A' && c<='Z'); } static inline bool isDigit( char c ) { return c>='0' && c<='9'; } static inline bool isAlnum( char c ) { return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'); } } int nv::strCmp(const char * s1, const char * s2) { nvDebugCheck(s1 != NULL); nvDebugCheck(s2 != NULL); return strcmp(s1, s2); } int nv::strCaseCmp(const char * s1, const char * s2) { nvDebugCheck(s1 != NULL); nvDebugCheck(s1 != NULL); #if NV_CC_MSVC return _stricmp(s1, s2); #else return strcasecmp(s1, s2); #endif } void nv::strCpy(char * dst, int size, const char * src) { nvDebugCheck(dst != NULL); nvDebugCheck(src != NULL); #if NV_CC_MSVC && _MSC_VER >= 1400 strcpy_s(dst, size, src); #else NV_UNUSED(size); strcpy(dst, src); #endif } void nv::strCpy(char * dst, int size, const char * src, int len) { nvDebugCheck(dst != NULL); nvDebugCheck(src != NULL); #if NV_CC_MSVC && _MSC_VER >= 1400 strncpy_s(dst, size, src, len); #else NV_UNUSED(size); strncpy(dst, src, len); #endif } void nv::strCat(char * dst, int size, const char * src) { nvDebugCheck(dst != NULL); nvDebugCheck(src != NULL); #if NV_CC_MSVC && _MSC_VER >= 1400 strcat_s(dst, size, src); #else NV_UNUSED(size); strcat(dst, src); #endif } /** Pattern matching routine. I don't remember where did I get this. */ bool nv::strMatch(const char * str, const char * pat) { nvDebugCheck(str != NULL); nvDebugCheck(pat != NULL); char c2; while (true) { if (*pat==0) { if (*str==0) return true; else return false; } if ((*str==0) && (*pat!='*')) return false; if (*pat=='*') { pat++; if (*pat==0) return true; while (true) { if (strMatch(str, pat)) return true; if (*str==0) return false; str++; } } if (*pat=='?') goto match; if (*pat=='[') { pat++; while (true) { if ((*pat==']') || (*pat==0)) return false; if (*pat==*str) break; if (pat[1] == '-') { c2 = pat[2]; if (c2==0) return false; if ((*pat<=*str) && (c2>=*str)) break; if ((*pat>=*str) && (c2<=*str)) break; pat+=2; } pat++; } while (*pat!=']') { if (*pat==0) { pat--; break; } pat++; } goto match; } if (*pat == NV_PATH_SEPARATOR) { pat++; if (*pat==0) return false; } if (*pat!=*str) return false; match: pat++; str++; } } /** Empty string. */ StringBuilder::StringBuilder() : m_size(0), m_str(NULL) { } /** Preallocate space. */ StringBuilder::StringBuilder( int size_hint ) : m_size(size_hint) { nvDebugCheck(m_size > 0); m_str = strAlloc(m_size); *m_str = '\0'; } /** Copy ctor. */ StringBuilder::StringBuilder( const StringBuilder & s ) : m_size(0), m_str(NULL) { copy(s); } /** Copy string. */ StringBuilder::StringBuilder( const char * s ) : m_size(0), m_str(NULL) { copy(s); } /** Delete the string. */ StringBuilder::~StringBuilder() { m_size = 0; strFree(m_str); m_str = NULL; } /** Format a string safely. */ StringBuilder & StringBuilder::format( const char * fmt, ... ) { nvDebugCheck(fmt != NULL); va_list arg; va_start( arg, fmt ); format( fmt, arg ); va_end( arg ); return *this; } /** Format a string safely. */ StringBuilder & StringBuilder::format( const char * fmt, va_list arg ) { nvDebugCheck(fmt != NULL); if( m_size == 0 ) { m_size = 64; m_str = strAlloc( m_size ); } va_list tmp; va_copy(tmp, arg); #if NV_CC_MSVC && _MSC_VER >= 1400 int n = vsnprintf_s(m_str, m_size, _TRUNCATE, fmt, tmp); #else int n = vsnprintf(m_str, m_size, fmt, tmp); #endif va_end(tmp); while( n < 0 || n >= int(m_size) ) { if( n > -1 ) { m_size = n + 1; } else { m_size *= 2; } m_str = strReAlloc(m_str, m_size); va_copy(tmp, arg); #if NV_CC_MSVC && _MSC_VER >= 1400 n = vsnprintf_s(m_str, m_size, _TRUNCATE, fmt, tmp); #else n = vsnprintf(m_str, m_size, fmt, tmp); #endif va_end(tmp); } nvDebugCheck(n < int(m_size)); // Make sure it's null terminated. nvDebugCheck(m_str[n] == '\0'); //str[n] = '\0'; return *this; } /** Append a string. */ StringBuilder & StringBuilder::append( const char * s ) { nvDebugCheck(s != NULL); const uint slen = uint(strlen( s )); if( m_str == NULL ) { m_size = slen + 1; m_str = strAlloc(m_size); strCpy( m_str, m_size, s ); } else { const uint len = uint(strlen( m_str )); if( m_size < len + slen + 1 ) { m_size = len + slen + 1; m_str = strReAlloc(m_str, m_size); } strCat( m_str, m_size, s ); } return *this; } /** Append a formatted string. */ StringBuilder & StringBuilder::appendFormat( const char * format, ... ) { nvDebugCheck( format != NULL ); va_list arg; va_start( arg, format ); appendFormat( format, arg ); va_end( arg ); return *this; } /** Append a formatted string. */ StringBuilder & StringBuilder::appendFormat( const char * format, va_list arg ) { nvDebugCheck( format != NULL ); va_list tmp; va_copy(tmp, arg); StringBuilder tmp_str; tmp_str.format( format, tmp ); append( tmp_str ); va_end(tmp); return *this; } /** Convert number to string in the given base. */ StringBuilder & StringBuilder::number( int i, int base ) { nvCheck( base >= 2 ); nvCheck( base <= 36 ); // @@ This needs to be done correctly. // length = floor(log(i, base)); uint len = uint(log(float(i)) / log(float(base)) + 2); // one more if negative reserve(len); if( i < 0 ) { *m_str = '-'; *i2a(uint(-i), m_str+1, base) = 0; } else { *i2a(i, m_str, base) = 0; } return *this; } /** Convert number to string in the given base. */ StringBuilder & StringBuilder::number( uint i, int base ) { nvCheck( base >= 2 ); nvCheck( base <= 36 ); // @@ This needs to be done correctly. // length = floor(log(i, base)); uint len = uint(log(float(i)) / log(float(base)) - 0.5f + 1); reserve(len); *i2a(i, m_str, base) = 0; return *this; } /** Resize the string preserving the contents. */ StringBuilder & StringBuilder::reserve( uint size_hint ) { nvCheck(size_hint != 0); if( size_hint > m_size ) { m_str = strReAlloc(m_str, size_hint); m_size = size_hint; } return *this; } /** Copy a string safely. */ StringBuilder & StringBuilder::copy( const char * s ) { nvCheck( s != NULL ); uint str_size = uint(strlen( s )) + 1; reserve(str_size); strCpy( m_str, str_size, s ); return *this; } /** Copy an StringBuilder. */ StringBuilder & StringBuilder::copy( const StringBuilder & s ) { if( s.m_str == NULL ) { nvCheck( s.m_size == 0 ); m_size = 0; strFree( m_str ); m_str = NULL; } else { reserve( s.m_size ); strCpy( m_str, s.m_size, s.m_str ); } return *this; } /** Reset the string. */ void StringBuilder::reset() { m_size = 0; strFree( m_str ); m_str = NULL; } /// Get the file name from a path. const char * Path::fileName() const { return fileName(m_str); } /// Get the extension from a file path. const char * Path::extension() const { return extension(m_str); } /// Toggles path separators (ie. \\ into /). void Path::translatePath() { nvCheck( m_str != NULL ); for(int i = 0; ; i++) { if( m_str[i] == '\0' ) break; #if NV_PATH_SEPARATOR == '/' if( m_str[i] == '\\' ) m_str[i] = NV_PATH_SEPARATOR; #else if( m_str[i] == '/' ) m_str[i] = NV_PATH_SEPARATOR; #endif } } /** * Strip the file name from a path. * @warning path cannot end with '/' o '\\', can't it? */ void Path::stripFileName() { nvCheck( m_str != NULL ); int length = (int)strlen(m_str) - 1; while (length > 0 && m_str[length] != '/' && m_str[length] != '\\'){ length--; } if( length ) { m_str[length+1] = 0; } else { m_str[0] = 0; } } /// Strip the extension from a path name. void Path::stripExtension() { nvCheck( m_str != NULL ); int length = (int)strlen(m_str) - 1; while( length > 0 && m_str[length] != '.' ) { length--; if( m_str[length] == NV_PATH_SEPARATOR ) { return; // no extension } } if( length ) { m_str[length] = 0; } } /// Get the path separator. // static char Path::separator() { return NV_PATH_SEPARATOR; } // static const char * Path::fileName(const char * str) { nvCheck( str != NULL ); int length = (int)strlen(str) - 1; while( length >= 0 && str[length] != separator() ) { length--; } return &str[length+1]; } // static const char * Path::extension(const char * str) { nvCheck( str != NULL ); int length, l; l = length = (int)strlen( str ); while( length > 0 && str[length] != '.' ) { length--; if( str[length] == separator() ) { return &str[l]; // no extension } } if( length == 0 ) { return &str[l]; } return &str[length]; } /// Clone this string String String::clone() const { String str(data); return str; } void String::setString(const char * str) { if (str == NULL) { data = NULL; } else { allocString( str ); addRef(); } } void String::setString(const char * str, int length) { nvDebugCheck(str != NULL); allocString(str, length); addRef(); } void String::setString(const StringBuilder & str) { if (str.str() == NULL) { data = NULL; } else { allocString(str); addRef(); } } nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/StrLib.h000066400000000000000000000172501173441656100223540ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_STRING_H #define NV_CORE_STRING_H #include #include // swap #include // strlen, strcmp, etc. namespace nv { uint strHash(const char * str, uint h) NV_PURE; /// String hash based on Bernstein's hash. inline uint strHash(const char * data, uint h = 5381) { uint i = 0; while(data[i] != 0) { h = (33 * h) ^ uint(data[i]); i++; } return h; } template <> struct hash { uint operator()(const char * str) const { return strHash(str); } }; NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE; NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE; NVCORE_API void strCpy(char * dst, int size, const char * src); NVCORE_API void strCpy(char * dst, int size, const char * src, int len); NVCORE_API void strCat(char * dst, int size, const char * src); NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE; /// String builder. class NVCORE_CLASS StringBuilder { public: StringBuilder(); explicit StringBuilder( int size_hint ); StringBuilder( const char * str ); StringBuilder( const StringBuilder & ); ~StringBuilder(); StringBuilder & format( const char * format, ... ) __attribute__((format (printf, 2, 3))); StringBuilder & format( const char * format, va_list arg ); StringBuilder & append( const char * str ); StringBuilder & appendFormat( const char * format, ... ) __attribute__((format (printf, 2, 3))); StringBuilder & appendFormat( const char * format, va_list arg ); StringBuilder & number( int i, int base = 10 ); StringBuilder & number( uint i, int base = 10 ); StringBuilder & reserve( uint size_hint ); StringBuilder & copy( const char * str ); StringBuilder & copy( const StringBuilder & str ); StringBuilder & toLower(); StringBuilder & toUpper(); void reset(); bool isNull() const { return m_size == 0; } // const char * accessors operator const char * () const { return m_str; } operator char * () { return m_str; } const char * str() const { return m_str; } char * str() { return m_str; } /// Implement value semantics. StringBuilder & operator=( const StringBuilder & s ) { return copy(s); } /// Implement value semantics. StringBuilder & operator=( const char * s ) { return copy(s); } /// Equal operator. bool operator==( const StringBuilder & s ) const { if (s.isNull()) return isNull(); else if (isNull()) return false; else return strcmp(s.m_str, m_str) != 0; } /// Return the exact length. uint length() const { return isNull() ? 0 : uint(strlen(m_str)); } /// Return the size of the string container. uint capacity() const { return m_size; } /// Return the hash of the string. uint hash() const { return isNull() ? 0 : strHash(m_str); } /// Swap strings. friend void swap(StringBuilder & a, StringBuilder & b) { nv::swap(a.m_size, b.m_size); nv::swap(a.m_str, b.m_str); } protected: /// Size of the string container. uint m_size; /// String. char * m_str; }; /// Path string. @@ This should be called PathBuilder. class NVCORE_CLASS Path : public StringBuilder { public: Path() : StringBuilder() {} explicit Path(int size_hint) : StringBuilder(size_hint) {} Path(const char * str) : StringBuilder(str) {} Path(const Path & path) : StringBuilder(path) {} const char * fileName() const; const char * extension() const; void translatePath(); void stripFileName(); void stripExtension(); // statics NVCORE_API static char separator(); NVCORE_API static const char * fileName(const char *); NVCORE_API static const char * extension(const char *); }; /// String class. class NVCORE_CLASS String { public: /// Constructs a null string. @sa isNull() String() { data = NULL; } /// Constructs a shared copy of str. String(const String & str) { data = str.data; if (data != NULL) addRef(); } /// Constructs a shared string from a standard string. String(const char * str) { setString(str); } /// Constructs a shared string from a standard string. String(const char * str, int length) { setString(str, length); } /// Constructs a shared string from a StringBuilder. String(const StringBuilder & str) { setString(str); } /// Dtor. ~String() { release(); } String clone() const; /// Release the current string and allocate a new one. const String & operator=( const char * str ) { release(); setString( str ); return *this; } /// Release the current string and allocate a new one. const String & operator=( const StringBuilder & str ) { release(); setString( str ); return *this; } /// Implement value semantics. String & operator=( const String & str ) { if (str.data != data) { release(); data = str.data; addRef(); } return *this; } /// Equal operator. bool operator==( const String & str ) const { if( str.data == data ) { return true; } if ((data == NULL) != (str.data == NULL)) { return false; } return strcmp(data, str.data) == 0; } /// Equal operator. bool operator==( const char * str ) const { nvCheck(str != NULL); // Use isNull! if (data == NULL) { return false; } return strcmp(data, str) == 0; } /// Not equal operator. bool operator!=( const String & str ) const { if( str.data == data ) { return false; } if ((data == NULL) != (str.data == NULL)) { return true; } return strcmp(data, str.data) != 0; } /// Not equal operator. bool operator!=( const char * str ) const { nvCheck(str != NULL); // Use isNull! if (data == NULL) { return false; } return strcmp(data, str) != 0; } /// Returns true if this string is the null string. bool isNull() const { return data == NULL; } /// Return the exact length. uint length() const { nvDebugCheck(data != NULL); return uint(strlen(data)); } /// Return the hash of the string. uint hash() const { nvDebugCheck(data != NULL); return strHash(data); } /// const char * cast operator. operator const char * () const { return data; } /// Get string pointer. const char * str() const { return data; } private: // Add reference count. void addRef() { if (data != NULL) { setRefCount(getRefCount() + 1); } } // Decrease reference count. void release() { if (data != NULL) { const uint16 count = getRefCount(); setRefCount(count - 1); if (count - 1 == 0) { mem::free(data - 2); data = NULL; } } } uint16 getRefCount() const { nvDebugCheck(data != NULL); return *reinterpret_cast(data - 2); } void setRefCount(uint16 count) { nvDebugCheck(data != NULL); nvCheck(count < 0xFFFF); *reinterpret_cast(const_cast(data - 2)) = uint16(count); } void setData(const char * str) { data = str + 2; } void allocString(const char * str) { allocString(str, (int)strlen(str)); } void allocString(const char * str, int len) { const char * ptr = static_cast(mem::malloc(2 + len + 1)); setData( ptr ); setRefCount( 0 ); // Copy string. strCpy(const_cast(data), len+1, str, len); // Add terminating character. const_cast(data)[len] = '\0'; } void setString(const char * str); void setString(const char * str, int length); void setString(const StringBuilder & str); /// Swap strings. friend void swap(String & a, String & b) { swap(a.data, b.data); } private: const char * data; }; } // nv namespace #endif // NV_CORE_STRING_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Stream.h000066400000000000000000000071051173441656100224060ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NVCORE_STREAM_H #define NVCORE_STREAM_H #include #include namespace nv { /// Base stream class. class NVCORE_CLASS Stream { public: enum ByteOrder { LittleEndian = false, BigEndian = true, }; /// Get the byte order of the system. static ByteOrder getSystemByteOrder() { # if NV_LITTLE_ENDIAN return LittleEndian; # else return BigEndian; # endif } /// Ctor. Stream() : m_byteOrder(LittleEndian) { } /// Virtual destructor. virtual ~Stream() {} /// Set byte order. void setByteOrder(ByteOrder bo) { m_byteOrder = bo; } /// Get byte order. ByteOrder byteOrder() const { return m_byteOrder; } /// Serialize the given data. virtual uint serialize( void * data, uint len ) = 0; /// Move to the given position in the archive. virtual void seek( uint pos ) = 0; /// Return the current position in the archive. virtual uint tell() const = 0; /// Return the current size of the archive. virtual uint size() const = 0; /// Determine if there has been any error. virtual bool isError() const = 0; /// Clear errors. virtual void clearError() = 0; /// Return true if the stream is at the end. virtual bool isAtEnd() const = 0; /// Return true if the stream is seekable. virtual bool isSeekable() const = 0; /// Return true if this is an input stream. virtual bool isLoading() const = 0; /// Return true if this is an output stream. virtual bool isSaving() const = 0; // friends friend Stream & operator<<( Stream & s, bool & c ) { # if NV_OS_DARWIN nvStaticCheck(sizeof(bool) == 4); uint8 b = c ? 1 : 0; s.serialize( &b, 1 ); c = (b == 1); # else nvStaticCheck(sizeof(bool) == 1); s.serialize( &c, 1 ); # endif return s; } friend Stream & operator<<( Stream & s, char & c ) { nvStaticCheck(sizeof(char) == 1); s.serialize( &c, 1 ); return s; } friend Stream & operator<<( Stream & s, uint8 & c ) { nvStaticCheck(sizeof(uint8) == 1); s.serialize( &c, 1 ); return s; } friend Stream & operator<<( Stream & s, int8 & c ) { nvStaticCheck(sizeof(int8) == 1); s.serialize( &c, 1 ); return s; } friend Stream & operator<<( Stream & s, uint16 & c ) { nvStaticCheck(sizeof(uint16) == 2); return s.byteOrderSerialize( &c, 2 ); } friend Stream & operator<<( Stream & s, int16 & c ) { nvStaticCheck(sizeof(int16) == 2); return s.byteOrderSerialize( &c, 2 ); } friend Stream & operator<<( Stream & s, uint32 & c ) { nvStaticCheck(sizeof(uint32) == 4); return s.byteOrderSerialize( &c, 4 ); } friend Stream & operator<<( Stream & s, int32 & c ) { nvStaticCheck(sizeof(int32) == 4); return s.byteOrderSerialize( &c, 4 ); } friend Stream & operator<<( Stream & s, uint64 & c ) { nvStaticCheck(sizeof(uint64) == 8); return s.byteOrderSerialize( &c, 8 ); } friend Stream & operator<<( Stream & s, int64 & c ) { nvStaticCheck(sizeof(int64) == 8); return s.byteOrderSerialize( &c, 8 ); } friend Stream & operator<<( Stream & s, float & c ) { nvStaticCheck(sizeof(float) == 4); return s.byteOrderSerialize( &c, 4 ); } friend Stream & operator<<( Stream & s, double & c ) { nvStaticCheck(sizeof(double) == 8); return s.byteOrderSerialize( &c, 8 ); } protected: /// Serialize in the stream byte order. Stream & byteOrderSerialize( void * v, uint len ) { if( m_byteOrder == getSystemByteOrder() ) { serialize( v, len ); } else { for( uint i = len; i > 0; i-- ) { serialize( (uint8 *)v + i - 1, 1 ); } } return *this; } private: ByteOrder m_byteOrder; }; } // nv namespace #endif // NV_STREAM_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/TextReader.cpp000066400000000000000000000024561173441656100235610ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include using namespace nv; /// Peek next character. char TextReader::peek() { nvDebugCheck(m_stream != NULL); nvDebugCheck(m_stream->isSeekable()); if (m_stream->isAtEnd()) { return 0; } uint pos = m_stream->tell(); char c; m_stream->serialize(&c, 1); m_stream->seek(pos); return c; } /// Read a single char. char TextReader::read() { nvDebugCheck(m_stream != NULL); char c; m_stream->serialize(&c, 1); if( m_stream->isAtEnd() ) { return 0; } return c; } /// Read from the current location to the end of the stream. const char * TextReader::readToEnd() { nvDebugCheck(m_stream != NULL); const int size = m_stream->size(); m_text.clear(); m_text.reserve(size + 1); m_text.resize(size); m_stream->serialize(m_text.unsecureBuffer(), size); m_text.pushBack('\0'); return m_text.buffer(); } /// Read from the current location to the end of the line. const char * TextReader::readLine() { m_text.clear(); if (m_stream->isAtEnd()) { return NULL; } while (true) { char c = read(); if (c == 0 || c == '\n') { break; } else if (c == '\r') { if( peek() == '\n' ) { read(); } break; } m_text.pushBack(c); } m_text.pushBack('\0'); return m_text.buffer(); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/TextReader.h000066400000000000000000000011731173441656100232210ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NVCORE_TEXTREADER_H #define NVCORE_TEXTREADER_H #include #include #include namespace nv { /// Text reader. class NVCORE_CLASS TextReader { public: /// Ctor. TextReader(Stream * stream) : m_stream(stream), m_text(512) { nvCheck(stream != NULL); nvCheck(stream->isLoading()); } char peek(); char read(); const char *readToEnd(); // Returns a temporary string. const char * readLine(); private: Stream * m_stream; Array m_text; }; } // nv namespace #endif // NVCORE_TEXTREADER_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/TextWriter.cpp000066400000000000000000000015221173441656100236240ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include using namespace nv; /// Constructor TextWriter::TextWriter(Stream * s) : s(s), str(1024) { nvCheck(s != NULL); nvCheck(s->isSaving()); } void TextWriter::writeString(const char * str) { nvDebugCheck(s != NULL); s->serialize(const_cast(str), (int)strlen(str)); } void TextWriter::writeString(const char * str, uint len) { nvDebugCheck(s != NULL); s->serialize(const_cast(str), len); } void TextWriter::write(const char * format, ...) { va_list arg; va_start(arg,format); str.format(format, arg); writeString(str.str(), str.length()); va_end(arg); } void TextWriter::write(const char * format, va_list arg) { va_list tmp; va_copy(tmp, arg); str.format(format, arg); writeString(str.str(), str.length()); va_end(tmp); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/TextWriter.h000066400000000000000000000020461173441656100232730ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NVCORE_TEXTWRITER_H #define NVCORE_TEXTWRITER_H #include #include #include namespace nv { /// Text writer. class NVCORE_CLASS TextWriter { public: TextWriter(Stream * s); void writeString(const char * str); void writeString(const char * str, uint len); void write(const char * format, ...) __attribute__((format (printf, 2, 3))); void write(const char * format, va_list arg); private: Stream * s; // Temporary string. StringBuilder str; }; inline TextWriter & operator<<( TextWriter & tw, int i) { tw.write("%d", i); return tw; } inline TextWriter & operator<<( TextWriter & tw, uint i) { tw.write("%u", i); return tw; } inline TextWriter & operator<<( TextWriter & tw, float f) { tw.write("%f", f); return tw; } inline TextWriter & operator<<( TextWriter & tw, const char * str) { tw.writeString(str); return tw; } } // nv namespace #endif // NVCORE_TEXTWRITER_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Tokenizer.cpp000066400000000000000000000072321173441656100234610ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include #include // vsscanf #include // va_list #include // atof, atoi #if NV_CC_MSVC #if 0 // This doesn't work on MSVC for x64 /* vsscanf for Win32 * Written 5/2003 by * This code is in the Public Domain */ #include // alloca //#include static int vsscanf(const char * buffer, const char * format, va_list argPtr) { // Get an upper bound for the # of args size_t count = 0; const char *p = format; while(1) { char c = *(p++); if(c==0) break; if(c=='%' && (p[0]!='*' && p[0]!='%')) ++count; } // Make a local stack size_t stackSize = (2+count)*sizeof(void*); void **newStack = (void**)alloca(stackSize); // Fill local stack the way sscanf likes it newStack[0] = (void*)buffer; newStack[1] = (void*)format; memcpy(newStack+2, argPtr, count*sizeof(void*)); // @@ Use: CALL DWORD PTR [sscanf] // Warp into system sscanf with new stack int result; void *savedESP; __asm { mov savedESP, esp mov esp, newStack #if _MSC_VER >= 1400 call DWORD PTR [sscanf_s] #else call DWORD PTR [sscanf] #endif mov esp, savedESP mov result, eax } return result; } #endif #endif using namespace nv; Token::Token() : m_str(""), m_len(0) { } Token::Token(const Token & token) : m_str(token.m_str), m_len(token.m_len) { } Token::Token(const char * str, int len) : m_str(str), m_len(len) { } bool Token::operator==(const char * str) const { return strncmp(m_str, str, m_len) == 0; } bool Token::operator!=(const char * str) const { return strncmp(m_str, str, m_len) != 0; } bool Token::isNull() { return m_len != 0; } float Token::toFloat() const { return float(atof(m_str)); } int Token::toInt() const { return atoi(m_str); } uint Token::toUnsignedInt() const { // @@ TBD return uint(atoi(m_str)); } String Token::toString() const { return String(m_str, m_len); } bool Token::parse(const char * format, int count, ...) const { va_list arg; va_start(arg, count); int readCount = vsscanf(m_str, format, arg); va_end(arg); return readCount == count; } Tokenizer::Tokenizer(Stream * stream) : m_reader(stream), m_lineNumber(0), m_columnNumber(0), m_delimiters("{}()="), m_spaces(" \t") { } bool Tokenizer::nextLine(bool skipEmptyLines /*= true*/) { do { if (!readLine()) { return false; } } while (!readToken() && skipEmptyLines); return true; } bool Tokenizer::nextToken(bool skipEndOfLine /*= false*/) { if (!readToken()) { if (!skipEndOfLine) { return false; } else { return nextLine(true); } } return true; } bool Tokenizer::readToken() { skipSpaces(); const char * begin = m_line + m_columnNumber; if (*begin == '\0') { return false; } char c = readChar(); if (isDelimiter(c)) { m_token = Token(begin, 1); return true; } // @@ Add support for quoted tokens "", '' int len = 0; while (!isDelimiter(c) && !isSpace(c) && c != '\0') { c = readChar(); len++; } m_columnNumber--; m_token = Token(begin, len); return true; } char Tokenizer::readChar() { return m_line[m_columnNumber++]; } bool Tokenizer::readLine() { m_lineNumber++; m_columnNumber = 0; m_line = m_reader.readLine(); return m_line != NULL; } void Tokenizer::skipSpaces() { while (isSpace(readChar())) {} m_columnNumber--; } bool Tokenizer::isSpace(char c) { uint i = 0; while (m_spaces[i] != '\0') { if (c == m_spaces[i]) { return true; } i++; } return false; } bool Tokenizer::isDelimiter(char c) { uint i = 0; while (m_delimiters[i] != '\0') { if (c == m_delimiters[i]) { return true; } i++; } return false; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/Tokenizer.h000066400000000000000000000042211173441656100231210ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_TOKENIZER_H #define NV_CORE_TOKENIZER_H #include #include #include #include namespace nv { /// A token produced by the Tokenizer. class NVCORE_CLASS Token { public: Token(); Token(const Token & token); Token(const char * str, int len); bool operator==(const char * str) const; bool operator!=(const char * str) const; bool isNull(); float toFloat() const; int toInt() const; uint toUnsignedInt() const; String toString() const; bool parse(const char * format, int count, ...) const __attribute__((format (scanf, 2, 4))); private: const char * m_str; int m_len; }; /// Exception thrown by the tokenizer. class TokenizerException { public: TokenizerException(int line, int column) : m_line(line), m_column(column) {} int line() const { return m_line; } int column() const { return m_column; } private: int m_line; int m_column; }; // @@ Use enums instead of bools for clarity! //enum SkipEmptyLines { skipEmptyLines, noSkipEmptyLines }; //enum SkipEndOfLine { skipEndOfLine, noSkipEndOfLine }; /// A simple stream tokenizer. class NVCORE_CLASS Tokenizer { public: Tokenizer(Stream * stream); bool nextLine(bool skipEmptyLines = true); bool nextToken(bool skipEndOfLine = false); const Token & token() const { return m_token; } int lineNumber() const { return m_lineNumber; } int columnNumber() const { return m_columnNumber; } void setDelimiters(const char * str) { m_delimiters = str; } const char * delimiters() const { return m_delimiters; } void setSpaces(const char * str) { m_spaces = str; } const char * spaces() const { return m_spaces; } private: char readChar(); bool readLine(); bool readToken(); void skipSpaces(); bool isSpace(char c); bool isDelimiter(char c); private: TextReader m_reader; const char * m_line; Token m_token; int m_lineNumber; int m_columnNumber; const char * m_delimiters; const char * m_spaces; }; } // nv namespace #endif // NV_CORE_TOKENIZER_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/nvcore.h000066400000000000000000000072231173441656100224500ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_CORE_H #define NV_CORE_H // cmake config #include // Function linkage #if NVCORE_SHARED #ifdef NVCORE_EXPORTS #define NVCORE_API DLL_EXPORT #define NVCORE_CLASS DLL_EXPORT_CLASS #else #define NVCORE_API DLL_IMPORT #define NVCORE_CLASS DLL_IMPORT #endif #else // NVCORE_SHARED #define NVCORE_API #define NVCORE_CLASS #endif // NVCORE_SHARED // Platform definitions #include "poshlib/posh.h" // OS: // NV_OS_WIN32 // NV_OS_WIN64 // NV_OS_MINGW // NV_OS_CYGWIN // NV_OS_LINUX // NV_OS_UNIX // NV_OS_DARWIN #define NV_OS_STRING POSH_OS_STRING #if defined POSH_OS_LINUX # define NV_OS_LINUX 1 # define NV_OS_UNIX 1 #elif defined POSH_OS_CYGWIN32 # define NV_OS_CYGWIN 1 #elif defined POSH_OS_MINGW # define NV_OS_MINGW 1 # define NV_OS_WIN32 1 #elif defined POSH_OS_OSX # define NV_OS_DARWIN 1 # define NV_OS_UNIX 1 #elif defined POSH_OS_UNIX # define NV_OS_UNIX 1 #elif defined POSH_OS_WIN32 # define NV_OS_WIN32 1 #elif defined POSH_OS_WIN64 # define NV_OS_WIN64 1 #else # error "Unsupported OS" #endif // CPUs: // NV_CPU_X86 // NV_CPU_X86_64 // NV_CPU_PPC #define NV_CPU_STRING POSH_CPU_STRING #if defined POSH_CPU_X86_64 # define NV_CPU_X86_64 1 #elif defined POSH_CPU_X86 # define NV_CPU_X86 1 #elif defined POSH_CPU_PPC # define NV_CPU_PPC 1 #else # error "Unsupported CPU" #endif // Compiler: // NV_CC_GNUC // NV_CC_MSVC // @@ NV_CC_MSVC6 // @@ NV_CC_MSVC7 // @@ NV_CC_MSVC8 #if defined POSH_COMPILER_GCC # define NV_CC_GNUC 1 # define NV_CC_STRING "gcc" #elif defined POSH_COMPILER_MSVC # define NV_CC_MSVC 1 # define NV_CC_STRING "msvc" #else # error "Unsupported compiler" #endif // Endiannes: #define NV_LITTLE_ENDIAN POSH_LITTLE_ENDIAN #define NV_BIG_ENDIAN POSH_BIG_ENDIAN #define NV_ENDIAN_STRING POSH_ENDIAN_STRING // Version string: #define NV_VERSION_STRING \ NV_OS_STRING "/" NV_CC_STRING "/" NV_CPU_STRING"/" \ NV_ENDIAN_STRING"-endian - " __DATE__ "-" __TIME__ /// Disable copy constructor and assignment operator. /// @hideinitializer #define NV_FORBID_COPY(C) \ private: \ C( const C & ); \ C &operator=( const C & ); /// Disable dynamic allocation on the heap. /// See Prohibiting Heap-Based Objects in More Effective C++. /// @hideinitializer #define NV_FORBID_HEAPALLOC() \ private: \ static void *operator new(size_t size); \ static void *operator new[](size_t size); // String concatenation macros. #define NV_STRING_JOIN2(arg1, arg2) NV_DO_STRING_JOIN2(arg1, arg2) #define NV_DO_STRING_JOIN2(arg1, arg2) arg1 ## arg2 #define NV_STRING_JOIN3(arg1, arg2, arg3) NV_DO_STRING_JOIN3(arg1, arg2, arg3) #define NV_DO_STRING_JOIN3(arg1, arg2, arg3) arg1 ## arg2 ## arg3 // Startup initialization macro. #define NV_AT_STARTUP(some_code) \ namespace { \ static struct NV_STRING_JOIN2(AtStartup_, __LINE__) { \ NV_STRING_JOIN2(AtStartup_, __LINE__)() { some_code; } \ } \ NV_STRING_JOIN3(AtStartup_, __LINE__, Instance); \ }; /// Indicate the compiler that the parameter is not used to suppress compier warnings. /// @hideinitializer #define NV_UNUSED(a) ((a)=(a)) /// Null index. @@ Move this somewhere else... This could have collisions with other definitions! #define NIL uint(~0) /// Null pointer. #ifndef NULL #define NULL 0 #endif // Platform includes #if NV_CC_MSVC # if NV_OS_WIN32 # include "DefsVcWin32.h" # else # error "MSVC: Platform not supported" # endif #elif NV_CC_GNUC # if NV_OS_LINUX # include "DefsGnucLinux.h" # elif NV_OS_DARWIN # include "DefsGnucDarwin.h" # elif NV_OS_MINGW # include "DefsGnucWin32.h" # elif NV_OS_CYGWIN # error "GCC: Cygwin not supported" # else # error "GCC: Platform not supported" # endif #endif #endif // NV_CORE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/poshlib/000077500000000000000000000000001173441656100224375ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/poshlib/CMakeLists.txt000066400000000000000000000001161173441656100251750ustar00rootroot00000000000000 SET(POSHLIB_SRCS posh.c posh.h) ADD_LIBRARY(posh STATIC ${POSHLIB_SRCS}) nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/poshlib/posh.c000066400000000000000000000624131173441656100235620ustar00rootroot00000000000000/* LICENSE: Copyright (c) 2004, Brian Hook All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of this package'ss contributors contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file posh.c @author Brian Hook @date 2002 @brief Portable Open Source Harness primary source file */ #include "posh.h" #if !defined FORCE_DOXYGEN #if !defined POSH_NO_FLOAT # define POSH_FLOAT_STRING "enabled" #else # define POSH_FLOAT_STRING "disabled" #endif #if defined POSH_64BIT_INTEGER # define POSH_64BIT_INTEGER_STRING "yes" #else # define POSH_64BIT_INTEGER_STRING "no" #endif #if defined POSH_64BIT_POINTER # define POSH_POINTER_STRING "64-bits" #else # define POSH_POINTER_STRING "32-bits" #endif #if defined POSH_LITTLE_ENDIAN # define IS_BIG_ENDIAN 0 # define NATIVE16 POSH_LittleU16 # define NATIVE32 POSH_LittleU32 # define NATIVE64 POSH_LittleU64 # define FOREIGN16 POSH_BigU16 # define FOREIGN32 POSH_BigU32 # define FOREIGN64 POSH_BigU64 #else # define IS_BIG_ENDIAN 1 # define NATIVE16 POSH_BigU16 # define NATIVE32 POSH_BigU32 # define NATIVE64 POSH_BigU64 # define FOREIGN16 POSH_LittleU16 # define FOREIGN32 POSH_LittleU32 # define FOREIGN64 POSH_LittleU64 #endif /* POSH_LITTLE_ENDIAN */ static int s_testBigEndian( void ) { union { posh_byte_t c[ 4 ]; posh_u32_t i; } u; u.i= 1; if ( u.c[ 0 ] == 1 ) { return 0; } return 1; } static const char * s_testSerialization( void ) { posh_byte_t serbuf[ 8 ]; posh_u16_t tmp16; posh_u32_t tmp32; /* 16-bit serialization */ POSH_WriteU16ToLittle( serbuf, 0xABCD ); if ( ( tmp16 = POSH_ReadU16FromLittle( serbuf ) ) != 0xABCD ) { return "*ERROR: failed little-endian 16-bit serialization test"; } POSH_WriteU16ToBig( serbuf, 0xABCD ); if ( ( tmp16 = POSH_ReadU16FromBig( serbuf ) ) != 0xABCD ) { return "*ERROR: failed big-endian 16-bit serialization test"; } /* 32-bit serialization */ POSH_WriteU32ToLittle( serbuf, 0xABCD1234L ); if ( ( tmp32 = POSH_ReadU32FromLittle( serbuf ) ) != 0xABCD1234 ) { return "*ERROR: failed little-endian 32-bit serialization test"; } POSH_WriteU32ToBig( serbuf, 0xABCD1234L ); if ( ( tmp32 = POSH_ReadU32FromBig( serbuf ) ) != 0xABCD1234 ) { return "*ERROR: failed big-endian 32-bit serialization test"; } #if defined POSH_64BIT_INTEGER { #define REF64 POSH_U64(0xFEDCBA9876543210) posh_u64_t tmp64; POSH_WriteU64ToLittle( serbuf, REF64 ); if ( ( tmp64 = POSH_ReadU64FromLittle( serbuf ) ) != REF64 ) { return "*ERROR: failed little-endian 64-bit serialization test"; } POSH_WriteU64ToBig( serbuf, REF64 ); if ( ( tmp64 = POSH_ReadU64FromBig( serbuf ) ) != REF64 ) { return "*ERROR: failed big-endian 64-bit serialization test"; } } #endif return 0; } #if !defined POSH_NO_FLOAT static const char * s_testFloatingPoint( void ) { float fRef = 10.0f/30.0f; double dRef = 10.0/30.0; posh_byte_t dbuf[ 8 ]; float fTmp; double dTmp; fTmp = POSH_FloatFromLittleBits( POSH_LittleFloatBits( fRef ) ); if ( fTmp != fRef ) { return "*ERROR: POSH little endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n"; } fTmp = POSH_FloatFromBigBits( POSH_BigFloatBits( fRef ) ); if ( fTmp != fRef ) { return "*ERROR: POSH big endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n"; } POSH_DoubleBits( dRef, dbuf ); dTmp = POSH_DoubleFromBits( dbuf ); if ( dTmp != dRef ) { return "*ERROR: POSH double precision floating point serialization failed. Please report this to poshlib@poshlib.org!\n"; } return 0; } #endif /* !defined POSH_NO_FLOAT */ static const char * s_testEndianess( void ) { /* check endianess */ if ( s_testBigEndian() != IS_BIG_ENDIAN ) { return "*ERROR: POSH compile time endianess does not match run-time endianess verification. Please report this to poshlib@poshlib.org!\n"; } /* make sure our endian swap routines work */ if ( ( NATIVE32( 0x11223344L ) != 0x11223344L ) || ( FOREIGN32( 0x11223344L ) != 0x44332211L ) || ( NATIVE16( 0x1234 ) != 0x1234 ) || ( FOREIGN16( 0x1234 ) != 0x3412 ) ) { return "*ERROR: POSH endianess macro selection failed. Please report this to poshlib@poshlib.org!\n"; } /* test serialization routines */ return 0; } #endif /* !defined FORCE_DOXYGEN */ /** Returns a string describing this platform's basic attributes. POSH_GetArchString() reports on an architecture's statically determined attributes. In addition, it will perform run-time verification checks to make sure the various platform specific functions work. If an error occurs, please contact me at poshlib@poshlib.org so we can try to resolve what the specific failure case is. @returns a string describing this platform on success, or a string in the form "*ERROR: [text]" on failure. You can simply check to see if the first character returned is '*' to verify an error condition. */ const char * POSH_GetArchString( void ) { const char *err; const char *s = "OS:.............."POSH_OS_STRING"\n" "CPU:............."POSH_CPU_STRING"\n" "endian:.........."POSH_ENDIAN_STRING"\n" "ptr size:........"POSH_POINTER_STRING"\n" "64-bit ints......"POSH_64BIT_INTEGER_STRING"\n" "floating point..."POSH_FLOAT_STRING"\n" "compiler........."POSH_COMPILER_STRING"\n"; /* test endianess */ err = s_testEndianess(); if ( err != 0 ) { return err; } /* test serialization */ err = s_testSerialization(); if ( err != 0 ) { return err; } #if !defined POSH_NO_FLOAT /* check that our floating point support is correct */ err = s_testFloatingPoint(); if ( err != 0 ) { return err; } #endif return s; } /* ---------------------------------------------------------------------------*/ /* BYTE SWAPPING SUPPORT */ /* ---------------------------------------------------------------------------*/ /** * Byte swaps a 16-bit unsigned value * @ingroup ByteSwapFunctions @param v [in] unsigned 16-bit input value to swap @returns a byte swapped version of v */ posh_u16_t POSH_SwapU16( posh_u16_t v ) { posh_u16_t swapped; swapped = v << 8; swapped |= v >> 8; return swapped; } /** * Byte swaps a 16-bit signed value * @ingroup ByteSwapFunctions @param v [in] signed 16-bit input value to swap @returns a byte swapped version of v @remarks This just calls back to the unsigned version, since byte swapping is independent of sign. However, we still provide this function to avoid signed/unsigned mismatch compiler warnings. */ posh_i16_t POSH_SwapI16( posh_i16_t v ) { return ( posh_i16_t ) POSH_SwapU16( v ); } /** * Byte swaps a 32-bit unsigned value * @ingroup ByteSwapFunctions @param v [in] unsigned 32-bit input value to swap @returns a byte swapped version of v */ posh_u32_t POSH_SwapU32( posh_u32_t v ) { posh_u32_t swapped; swapped = ( v & 0xFF ) << 24; swapped |= ( v & 0xFF00 ) << 8; swapped |= ( v >> 8 ) & 0xFF00; swapped |= ( v >> 24 ); return swapped; } /** * Byte swaps a 32-bit signed value * @ingroup ByteSwapFunctions @param v [in] signed 32-bit input value to swap @returns a byte swapped version of v @remarks This just calls back to the unsigned version, since byte swapping is independent of sign. However, we still provide this function to avoid signed/unsigned mismatch compiler warnings. */ posh_i32_t POSH_SwapI32( posh_i32_t v ) { return ( posh_i32_t ) POSH_SwapU32( ( posh_u32_t ) v ); } #if defined POSH_64BIT_INTEGER /** * Byte swaps a 64-bit unsigned value @param v [in] a 64-bit input value to swap @ingroup SixtyFourBit @returns a byte swapped version of v */ posh_u64_t POSH_SwapU64( posh_u64_t v ) { posh_byte_t tmp; union { posh_byte_t bytes[ 8 ]; posh_u64_t u64; } u; u.u64 = v; tmp = u.bytes[ 0 ]; u.bytes[ 0 ] = u.bytes[ 7 ]; u.bytes[ 7 ] = tmp; tmp = u.bytes[ 1 ]; u.bytes[ 1 ] = u.bytes[ 6 ]; u.bytes[ 6 ] = tmp; tmp = u.bytes[ 2 ]; u.bytes[ 2 ] = u.bytes[ 5 ]; u.bytes[ 5 ] = tmp; tmp = u.bytes[ 3 ]; u.bytes[ 3 ] = u.bytes[ 4 ]; u.bytes[ 4 ] = tmp; return u.u64; } /** * Byte swaps a 64-bit signed value @param v [in] a 64-bit input value to swap @ingroup SixtyFourBit @returns a byte swapped version of v */ posh_i64_t POSH_SwapI64( posh_i64_t v ) { return ( posh_i64_t ) POSH_SwapU64( ( posh_u64_t ) v ); } #endif /* defined POSH_64BIT_INTEGER */ /* ---------------------------------------------------------------------------*/ /* IN-MEMORY SERIALIZATION */ /* ---------------------------------------------------------------------------*/ /** * Writes an unsigned 16-bit value to a little endian buffer @ingroup MemoryBuffer @param dst [out] pointer to the destination buffer, may not be NULL. Alignment doesn't matter. @param value [in] host-endian unsigned 16-bit value @returns a pointer to the location two bytes after dst @remarks does no validation of the inputs */ posh_u16_t * POSH_WriteU16ToLittle( void *dst, posh_u16_t value ) { posh_u16_t *p16 = ( posh_u16_t * ) dst; posh_byte_t *p = ( posh_byte_t * ) dst; p[ 0 ] = value & 0xFF; p[ 1 ] = ( value & 0xFF00) >> 8; return p16 + 1; } /** * Writes a signed 16-bit value to a little endian buffer @ingroup MemoryBuffer @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian signed 16-bit value @returns a pointer to the location two bytes after dst @remarks does no validation of the inputs. This simply calls POSH_WriteU16ToLittle() with appropriate casting. */ posh_i16_t * POSH_WriteI16ToLittle( void *dst, posh_i16_t value ) { return ( posh_i16_t * ) POSH_WriteU16ToLittle( dst, ( posh_u16_t ) value ); } /** * Writes an unsigned 32-bit value to a little endian buffer @ingroup MemoryBuffer @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian signed 32-bit value @returns a pointer to the location four bytes after dst @remarks does no validation of the inputs. */ posh_u32_t * POSH_WriteU32ToLittle( void *dst, posh_u32_t value ) { posh_u32_t *p32 = ( posh_u32_t * ) dst; posh_byte_t *p = ( posh_byte_t * ) dst; p[ 0 ] = ( value & 0xFF ); p[ 1 ] = ( value & 0xFF00 ) >> 8; p[ 2 ] = ( value & 0xFF0000 ) >> 16; p[ 3 ] = ( value & 0xFF000000 ) >> 24; return p32 + 1; } /** * Writes a signed 32-bit value to a little endian buffer @ingroup MemoryBuffer @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian signed 32-bit value @returns a pointer to the location four bytes after dst @remarks does no validation of the inputs. This simply calls POSH_WriteU32ToLittle() with appropriate casting. */ posh_i32_t * POSH_WriteI32ToLittle( void *dst, posh_i32_t value ) { return ( posh_i32_t * ) POSH_WriteU32ToLittle( dst, ( posh_u32_t ) value ); } /** * Writes an unsigned 16-bit value to a big endian buffer @ingroup MemoryBuffer @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian unsigned 16-bit value @returns a pointer to the location two bytes after dst @remarks does no validation of the inputs */ posh_u16_t * POSH_WriteU16ToBig( void *dst, posh_u16_t value ) { posh_u16_t *p16 = ( posh_u16_t * ) dst; posh_byte_t *p = ( posh_byte_t * ) dst; p[ 1 ] = ( value & 0xFF ); p[ 0 ] = ( value & 0xFF00 ) >> 8; return p16 + 1; } /** * Writes a signed 16-bit value to a big endian buffer @ingroup MemoryBuffer @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian signed 16-bit value @returns a pointer to the location two bytes after dst @remarks does no validation of the inputs. This simply calls POSH_WriteU16ToLittle() with appropriate casting. */ posh_i16_t * POSH_WriteI16ToBig( void *dst, posh_i16_t value ) { return ( posh_i16_t * ) POSH_WriteU16ToBig( dst, ( posh_u16_t ) value ); } /** * Writes an unsigned 32-bit value to a big endian buffer @ingroup MemoryBuffer @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian unsigned 32-bit value @returns a pointer to the location four bytes after dst @remarks does no validation of the inputs. */ posh_u32_t * POSH_WriteU32ToBig( void *dst, posh_u32_t value ) { posh_u32_t *p32 = ( posh_u32_t * ) dst; posh_byte_t *p = ( posh_byte_t * ) dst; p[ 3 ] = ( value & 0xFF ); p[ 2 ] = ( value & 0xFF00 ) >> 8; p[ 1 ] = ( value & 0xFF0000 ) >> 16; p[ 0 ] = ( value & 0xFF000000 ) >> 24; return p32 + 1; } /** * Writes a signed 32-bit value to a big endian buffer @ingroup MemoryBuffer @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian signed 32-bit value @returns a pointer to the location four bytes after dst @remarks does no validation of the inputs. This simply calls POSH_WriteU32ToBig() with appropriate casting. */ posh_i32_t * POSH_WriteI32ToBig( void *dst, posh_i32_t value ) { return ( posh_i32_t * ) POSH_WriteU32ToBig( dst, ( posh_u32_t ) value ); } #if defined POSH_64BIT_INTEGER /** * Writes an unsigned 64-bit value to a little-endian buffer @ingroup SixtyFourBit @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian unsigned 64-bit value @returns a pointer to the location eight bytes after dst @remarks does no validation of the inputs. */ posh_u64_t * POSH_WriteU64ToLittle( void *dst, posh_u64_t value ) { posh_u64_t *p64 = ( posh_u64_t * ) dst; posh_byte_t *p = ( posh_byte_t * ) dst; int i; for ( i = 0; i < 8; i++, value >>= 8 ) { p[ i ] = ( posh_byte_t ) ( value & 0xFF ); } return p64 + 1; } /** * Writes a signed 64-bit value to a little-endian buffer @ingroup SixtyFourBit @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian unsigned 64-bit value @returns a pointer to the location eight bytes after dst @remarks does no validation of the inputs. */ posh_i64_t * POSH_WriteI64ToLittle( void *dst, posh_i64_t value ) { return ( posh_i64_t * ) POSH_WriteU64ToLittle( dst, ( posh_u64_t ) value ); } /** * Writes an unsigned 64-bit value to a big-endian buffer @ingroup SixtyFourBit @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian unsigned 64-bit value @returns a pointer to the location eight bytes after dst @remarks does no validation of the inputs. */ posh_u64_t * POSH_WriteU64ToBig( void *dst, posh_u64_t value ) { posh_u64_t *p64 = ( posh_u64_t * ) dst; posh_byte_t *p = ( posh_byte_t * ) dst; int i; for ( i = 0; i < 8; i++, value >>= 8 ) { p[ 7-i ] = ( posh_byte_t ) ( value & 0xFF ); } return p64 + 8; } /** * Writes a signed 64-bit value to a big-endian buffer @ingroup SixtyFourBit @param dst [out] pointer to the destination buffer, may not be NULL @param value [in] host-endian signed 64-bit value @returns a pointer to the location eight bytes after dst @remarks does no validation of the inputs. */ posh_i64_t * POSH_WriteI64ToBig( void *dst, posh_i64_t value ) { return ( posh_i64_t * ) POSH_WriteU64ToBig( dst, ( posh_u64_t ) value ); } #endif /* POSH_64BIT_INTEGER */ /* ---------------------------------------------------------------------------*/ /* IN-MEMORY DESERIALIZATION */ /* ---------------------------------------------------------------------------*/ /** * Reads an unsigned 16-bit value from a little-endian buffer @ingroup MemoryBuffer @param src [in] source buffer @returns host-endian unsigned 16-bit value */ posh_u16_t POSH_ReadU16FromLittle( const void *src ) { posh_u16_t v = 0; posh_byte_t *p = ( posh_byte_t * ) src; v |= p[ 0 ]; v |= ( ( posh_u16_t ) p[ 1 ] ) << 8; return v; } /** * Reads a signed 16-bit value from a little-endian buffer @ingroup MemoryBuffer @param src [in] source buffer @returns host-endian signed 16-bit value */ posh_i16_t POSH_ReadI16FromLittle( const void *src ) { return ( posh_i16_t ) POSH_ReadU16FromLittle( src ); } /** * Reads an unsigned 32-bit value from a little-endian buffer @ingroup MemoryBuffer @param src [in] source buffer @returns host-endian unsigned 32-bit value */ posh_u32_t POSH_ReadU32FromLittle( const void *src ) { posh_u32_t v = 0; posh_byte_t *p = ( posh_byte_t * ) src; v |= p[ 0 ]; v |= ( ( posh_u32_t ) p[ 1 ] ) << 8; v |= ( ( posh_u32_t ) p[ 2 ] ) << 16; v |= ( ( posh_u32_t ) p[ 3 ] ) << 24; return v; } /** * Reads a signed 32-bit value from a little-endian buffer @ingroup MemoryBuffer @param src [in] source buffer @returns host-endian signed 32-bit value */ posh_i32_t POSH_ReadI32FromLittle( const void *src ) { return ( posh_i32_t ) POSH_ReadU32FromLittle( src ); } /** * Reads an unsigned 16-bit value from a big-endian buffer @ingroup MemoryBuffer @param src [in] source buffer @returns host-endian unsigned 16-bit value */ posh_u16_t POSH_ReadU16FromBig( const void *src ) { posh_u16_t v = 0; posh_byte_t *p = ( posh_byte_t * ) src; v |= p[ 1 ]; v |= ( ( posh_u16_t ) p[ 0 ] ) << 8; return v; } /** * Reads a signed 16-bit value from a big-endian buffer @ingroup MemoryBuffer @param src [in] source buffer @returns host-endian signed 16-bit value */ posh_i16_t POSH_ReadI16FromBig( const void *src ) { return ( posh_i16_t ) POSH_ReadU16FromBig( src ); } /** * Reads an unsigned 32-bit value from a big-endian buffer @ingroup MemoryBuffer @param src [in] source buffer @returns host-endian unsigned 32-bit value */ posh_u32_t POSH_ReadU32FromBig( const void *src ) { posh_u32_t v = 0; posh_byte_t *p = ( posh_byte_t * ) src; v |= p[ 3 ]; v |= ( ( posh_u32_t ) p[ 2 ] ) << 8; v |= ( ( posh_u32_t ) p[ 1 ] ) << 16; v |= ( ( posh_u32_t ) p[ 0 ] ) << 24; return v; } /** * Reads a signed 32-bit value from a big-endian buffer @ingroup MemoryBuffer @param src [in] source buffer @returns host-endian signed 32-bit value */ posh_i32_t POSH_ReadI32FromBig( const void *src ) { return POSH_BigI32( (*(const posh_i32_t*)src ) ); } #if defined POSH_64BIT_INTEGER /** * Reads an unsigned 64-bit value from a little-endian buffer @param src [in] source buffer @returns host-endian unsigned 32-bit value */ posh_u64_t POSH_ReadU64FromLittle( const void *src ) { posh_u64_t v = 0; posh_byte_t *p = ( posh_byte_t * ) src; int i; for ( i = 0; i < 8; i++ ) { v |= ( ( posh_u64_t ) p[ i ] ) << (i*8); } return v; } /** * Reads a signed 64-bit value from a little-endian buffer @param src [in] source buffer @returns host-endian signed 32-bit value */ posh_i64_t POSH_ReadI64FromLittle( const void *src ) { return ( posh_i64_t ) POSH_ReadU64FromLittle( src ); } /** * Reads an unsigned 64-bit value from a big-endian buffer @param src [in] source buffer @returns host-endian unsigned 32-bit value */ posh_u64_t POSH_ReadU64FromBig( const void *src ) { posh_u64_t v = 0; posh_byte_t *p = ( posh_byte_t * ) src; int i; for ( i = 0; i < 8; i++ ) { v |= ( ( posh_u64_t ) p[ 7-i ] ) << (i*8); } return v; } /** * Reads an signed 64-bit value from a big-endian buffer @param src [in] source buffer @returns host-endian signed 32-bit value */ posh_i64_t POSH_ReadI64FromBig( const void *src ) { return ( posh_i64_t ) POSH_ReadU64FromBig( src ); } #endif /* POSH_64BIT_INTEGER */ /* ---------------------------------------------------------------------------*/ /* FLOATING POINT SUPPORT */ /* ---------------------------------------------------------------------------*/ #if !defined POSH_NO_FLOAT /** @ingroup FloatingPoint @param[in] f floating point value @returns a little-endian bit representation of f */ posh_u32_t POSH_LittleFloatBits( float f ) { union { float f32; posh_u32_t u32; } u; u.f32 = f; return POSH_LittleU32( u.u32 ); } /** * Extracts raw big-endian bits from a 32-bit floating point value * @ingroup FloatingPoint @param f [in] floating point value @returns a big-endian bit representation of f */ posh_u32_t POSH_BigFloatBits( float f ) { union { float f32; posh_u32_t u32; } u; u.f32 = f; return POSH_BigU32( u.u32 ); } /** * Extracts raw, little-endian bit representation from a 64-bit double. * @param d [in] 64-bit double precision value @param dst [out] 8-byte storage buffer @ingroup FloatingPoint @returns the raw bits used to represent the value 'd', in the form dst[0]=LSB */ void POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] ) { union { double d64; posh_byte_t bytes[ 8 ]; } u; u.d64 = d; #if defined POSH_LITTLE_ENDIAN dst[ 0 ] = u.bytes[ 0 ]; dst[ 1 ] = u.bytes[ 1 ]; dst[ 2 ] = u.bytes[ 2 ]; dst[ 3 ] = u.bytes[ 3 ]; dst[ 4 ] = u.bytes[ 4 ]; dst[ 5 ] = u.bytes[ 5 ]; dst[ 6 ] = u.bytes[ 6 ]; dst[ 7 ] = u.bytes[ 7 ]; #else dst[ 0 ] = u.bytes[ 7 ]; dst[ 1 ] = u.bytes[ 6 ]; dst[ 2 ] = u.bytes[ 5 ]; dst[ 3 ] = u.bytes[ 4 ]; dst[ 4 ] = u.bytes[ 3 ]; dst[ 5 ] = u.bytes[ 2 ]; dst[ 6 ] = u.bytes[ 1 ]; dst[ 7 ] = u.bytes[ 0 ]; #endif } /** * Creates a double-precision, 64-bit floating point value from a set of raw, * little-endian bits @ingroup FloatingPoint @param src [in] little-endian byte representation of 64-bit double precision floating point value @returns double precision floating point representation of the raw bits @remarks No error checking is performed, so there are no guarantees that the result is a valid number, nor is there any check to ensure that src is non-NULL. BE CAREFUL USING THIS. */ double POSH_DoubleFromBits( const posh_byte_t src[ 8 ] ) { union { double d64; posh_byte_t bytes[ 8 ]; } u; #if defined POSH_LITTLE_ENDIAN u.bytes[ 0 ] = src[ 0 ]; u.bytes[ 1 ] = src[ 1 ]; u.bytes[ 2 ] = src[ 2 ]; u.bytes[ 3 ] = src[ 3 ]; u.bytes[ 4 ] = src[ 4 ]; u.bytes[ 5 ] = src[ 5 ]; u.bytes[ 6 ] = src[ 6 ]; u.bytes[ 7 ] = src[ 7 ]; #else u.bytes[ 0 ] = src[ 7 ]; u.bytes[ 1 ] = src[ 6 ]; u.bytes[ 2 ] = src[ 5 ]; u.bytes[ 3 ] = src[ 4 ]; u.bytes[ 4 ] = src[ 3 ]; u.bytes[ 5 ] = src[ 2 ]; u.bytes[ 6 ] = src[ 1 ]; u.bytes[ 7 ] = src[ 0 ]; #endif return u.d64; } /** * Creates a floating point number from little endian bits * @ingroup FloatingPoint @param bits [in] raw floating point bits in little-endian form @returns a floating point number based on the given bit representation @remarks No error checking is performed, so there are no guarantees that the result is a valid number. BE CAREFUL USING THIS. */ float POSH_FloatFromLittleBits( posh_u32_t bits ) { union { float f32; posh_u32_t u32; } u; u.u32 = bits; #if defined POSH_BIG_ENDIAN u.u32 = POSH_SwapU32( u.u32 ); #endif return u.f32; } /** * Creates a floating point number from big-endian bits * @ingroup FloatingPoint @param bits [in] raw floating point bits in big-endian form @returns a floating point number based on the given bit representation @remarks No error checking is performed, so there are no guarantees that the result is a valid number. BE CAREFUL USING THIS. */ float POSH_FloatFromBigBits( posh_u32_t bits ) { union { float f32; posh_u32_t u32; } u; u.u32 = bits; #if defined POSH_LITTLE_ENDIAN u.u32 = POSH_SwapU32( u.u32 ); #endif return u.f32; } #endif /* !defined POSH_NO_FLOAT */ nvidia-texture-tools-2.0.8-1+dfsg/src/nvcore/poshlib/posh.h000066400000000000000000000744641173441656100236000ustar00rootroot00000000000000/** @file posh.h @author Brian Hook @version 1.3.001 Header file for POSH, the Portable Open Source Harness project. NOTE: Unlike most header files, this one is designed to be included multiple times, which is why it does not have the @#ifndef/@#define preamble. POSH relies on environment specified preprocessor symbols in order to infer as much as possible about the target OS/architecture and the host compiler capabilities. NOTE: POSH is simple and focused. It attempts to provide basic functionality and information, but it does NOT attempt to emulate missing functionality. I am also not willing to make POSH dirty and hackish to support truly ancient and/or outmoded and/or bizarre technologies such as non-ANSI compilers, systems with non-IEEE floating point formats, segmented 16-bit operating systems, etc. Please refer to the accompanying HTML documentation or visit http://www.poshlib.org for more information on how to use POSH. LICENSE: Copyright (c) 2004, Brian Hook All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of this package'ss contributors contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. REVISION: I've been lax about revision histories, so this starts at, um, 1.3.001. Sorry for any inconveniences. 1.3.001 - 2/23/2006 - Incorporated fix for bug reported by Bill Cary, where I was not detecting Visual Studio compilation on x86-64 systems. Added check for _M_X64 which should fix that. */ /* I have yet to find an authoritative reference on preprocessor symbols, but so far this is what I've gleaned: GNU GCC/G++: - __GNUC__: GNU C version - __GNUG__: GNU C++ compiler - __sun__ : on Sun platforms - __svr4__: on Solaris and other SysV R4 platforms - __mips__: on MIPS processor platforms - __sparc_v9__: on Sparc 64-bit CPUs - __sparcv9: 64-bit Solaris - __MIPSEL__: mips processor, compiled for little endian - __MIPSEB__: mips processor, compiled for big endian - _R5900: MIPS/Sony/Toshiba R5900 (PS2) - mc68000: 68K - m68000: 68K - m68k: 68K - __palmos__: PalmOS Intel C/C++ Compiler: - __ECC : compiler version, IA64 only - __EDG__ - __ELF__ - __GXX_ABI_VERSION - __i386 : IA-32 only - __i386__ : IA-32 only - i386 : IA-32 only - __ia64 : IA-64 only - __ia64__ : IA-64 only - ia64 : IA-64 only - __ICC : IA-32 only - __INTEL_COMPILER : IA-32 or IA-64, newer versions only Apple's C/C++ Compiler for OS X: - __APPLE_CC__ - __APPLE__ - __BIG_ENDIAN__ - __APPLE__ - __ppc__ - __MACH__ DJGPP: - __MSDOS__ - __unix__ - __unix - __GNUC__ - __GO32 - DJGPP - __i386, __i386, i386 Cray's C compiler: - _ADDR64: if 64-bit pointers - _UNICOS: - __unix: SGI's CC compiler predefines the following (and more) with -ansi: - __sgi - __unix - __host_mips - _SYSTYPE_SVR4 - __mips - _MIPSEB - anyone know if there is a predefined symbol for the compiler?! MinGW: - as GnuC but also defines _WIN32, __WIN32, WIN32, _X86_, __i386, __i386__, and several others - __MINGW32__ Cygwin: - as Gnu C, but also - __unix__ - __CYGWIN32__ Microsoft Visual Studio predefines the following: - _MSC_VER - _WIN32: on Win32 - _M_IX6 (on x86 systems) - _M_X64: on x86-64 systems - _M_ALPHA (on DEC AXP systems) - _SH3: WinCE, Hitachi SH-3 - _MIPS: WinCE, MIPS - _ARM: WinCE, ARM Sun's C Compiler: - sun and _sun - unix and _unix - sparc and _sparc (SPARC systems only) - i386 and _i386 (x86 systems only) - __SVR4 (Solaris only) - __sparcv9: 64-bit solaris - __SUNPRO_C - _LP64: defined in 64-bit LP64 mode, but only if is included Borland C/C++ predefines the following: - __BORLANDC__: DEC/Compaq C/C++ on Alpha: - __alpha - __arch64__ - __unix__ (on Tru64 Unix) - __osf__ - __DECC - __DECCXX (C++ compilation) - __DECC_VER - __DECCXX_VER IBM's AIX compiler: - __64BIT__ if 64-bit mode - _AIX - __IBMC__: C compiler version - __IBMCPP__: C++ compiler version - _LONG_LONG: compiler allows long long Watcom: - __WATCOMC__ - __DOS__ : if targeting DOS - __386__ : if 32-bit support - __WIN32__ : if targetin 32-bit Windows HP-UX C/C++ Compiler: - __hpux - __unix - __hppa (on PA-RISC) - __LP64__: if compiled in 64-bit mode Metrowerks: - __MWERKS__ - __powerpc__ - _powerc - __MC68K__ - macintosh when compiling for MacOS - __INTEL__ for x86 targets - __POWERPC__ */ /* ** ---------------------------------------------------------------------------- ** Include optionally ** ---------------------------------------------------------------------------- */ #ifdef POSH_USE_LIMITS_H # include #endif /* ** ---------------------------------------------------------------------------- ** Determine compilation environment ** ---------------------------------------------------------------------------- */ #if defined __ECC || defined __ICC || defined __INTEL_COMPILER # define POSH_COMPILER_STRING "Intel C/C++" # define POSH_COMPILER_INTEL 1 #endif #if ( defined __host_mips || defined __sgi ) && !defined __GNUC__ # define POSH_COMPILER_STRING "MIPSpro C/C++" # define POSH_COMPILER_MIPSPRO 1 #endif #if defined __hpux && !defined __GNUC__ # define POSH_COMPILER_STRING "HP-UX CC" # define POSH_COMPILER_HPCC 1 #endif #if defined __GNUC__ # define POSH_COMPILER_STRING "Gnu GCC" # define POSH_COMPILER_GCC 1 #endif #if defined __APPLE_CC__ /* we don't define the compiler string here, let it be GNU */ # define POSH_COMPILER_APPLECC 1 #endif #if defined __IBMC__ || defined __IBMCPP__ # define POSH_COMPILER_STRING "IBM C/C++" # define POSH_COMPILER_IBM 1 #endif #if defined _MSC_VER # define POSH_COMPILER_STRING "Microsoft Visual C++" # define POSH_COMPILER_MSVC 1 #endif #if defined __SUNPRO_C # define POSH_COMPILER_STRING "Sun Pro" # define POSH_COMPILER_SUN 1 #endif #if defined __BORLANDC__ # define POSH_COMPILER_STRING "Borland C/C++" # define POSH_COMPILER_BORLAND 1 #endif #if defined __MWERKS__ # define POSH_COMPILER_STRING "MetroWerks CodeWarrior" # define POSH_COMPILER_METROWERKS 1 #endif #if defined __DECC || defined __DECCXX # define POSH_COMPILER_STRING "Compaq/DEC C/C++" # define POSH_COMPILER_DEC 1 #endif #if defined __WATCOMC__ # define POSH_COMPILER_STRING "Watcom C/C++" # define POSH_COMPILER_WATCOM 1 #endif #if !defined POSH_COMPILER_STRING # define POSH_COMPILER_STRING "Unknown compiler" #endif /* ** ---------------------------------------------------------------------------- ** Determine target operating system ** ---------------------------------------------------------------------------- */ #if defined linux || defined __linux__ # define POSH_OS_LINUX 1 # define POSH_OS_STRING "Linux" #endif #if defined __CYGWIN32__ # define POSH_OS_CYGWIN32 1 # define POSH_OS_STRING "Cygwin" #endif #if defined GEKKO # define POSH_OS_GAMECUBE # define __powerpc__ # define POSH_OS_STRING "GameCube" #endif #if defined __MINGW32__ # define POSH_OS_MINGW 1 # define POSH_OS_STRING "MinGW" #endif #if defined GO32 && defined DJGPP && defined __MSDOS__ # define POSH_OS_GO32 1 # define POSH_OS_STRING "GO32/MS-DOS" #endif /* NOTE: make sure you use /bt=DOS if compiling for 32-bit DOS, otherwise Watcom assumes host=target */ #if defined __WATCOMC__ && defined __386__ && defined __DOS__ # define POSH_OS_DOS32 1 # define POSH_OS_STRING "DOS/32-bit" #endif #if defined _UNICOS # define POSH_OS_UNICOS 1 # define POSH_OS_STRING "UNICOS" #endif #if ( defined __MWERKS__ && defined __powerc && !defined macintosh ) || defined __APPLE_CC__ || defined macosx # define POSH_OS_OSX 1 # define POSH_OS_STRING "MacOS X" #endif #if defined __sun__ || defined sun || defined __sun || defined __solaris__ # if defined __SVR4 || defined __svr4__ || defined __solaris__ # define POSH_OS_STRING "Solaris" # define POSH_OS_SOLARIS 1 # endif # if !defined POSH_OS_STRING # define POSH_OS_STRING "SunOS" # define POSH_OS_SUNOS 1 # endif #endif #if defined __sgi__ || defined sgi || defined __sgi # define POSH_OS_IRIX 1 # define POSH_OS_STRING "Irix" #endif #if defined __hpux__ || defined __hpux # define POSH_OS_HPUX 1 # define POSH_OS_STRING "HP-UX" #endif #if defined _AIX # define POSH_OS_AIX 1 # define POSH_OS_STRING "AIX" #endif #if ( defined __alpha && defined __osf__ ) # define POSH_OS_TRU64 1 # define POSH_OS_STRING "Tru64" #endif #if defined __BEOS__ || defined __beos__ # define POSH_OS_BEOS 1 # define POSH_OS_STRING "BeOS" #endif #if defined amiga || defined amigados || defined AMIGA || defined _AMIGA # define POSH_OS_AMIGA 1 # define POSH_OS_STRING "Amiga" #endif #if defined __unix__ # define POSH_OS_UNIX 1 # if !defined POSH_OS_STRING # define POSH_OS_STRING "Unix-like(generic)" # endif #endif #if defined _WIN32_WCE # define POSH_OS_WINCE 1 # define POSH_OS_STRING "Windows CE" #endif #if defined _XBOX # define POSH_OS_XBOX 1 # define POSH_OS_STRING "XBOX" #endif #if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__ # define POSH_OS_WIN32 1 # if !defined POSH_OS_XBOX # if defined _WIN64 # define POSH_OS_WIN64 1 # define POSH_OS_STRING "Win64" # else # if !defined POSH_OS_STRING # define POSH_OS_STRING "Win32" # endif # endif # endif #endif #if defined __palmos__ # define POSH_OS_PALM 1 # define POSH_OS_STRING "PalmOS" #endif #if defined THINK_C || defined macintosh # define POSH_OS_MACOS 1 # define POSH_OS_STRING "MacOS" #endif /* ** ----------------------------------------------------------------------------- ** Determine target CPU ** ----------------------------------------------------------------------------- */ #if defined GEKKO # define POSH_CPU_PPC750 1 # define POSH_CPU_STRING "IBM PowerPC 750 (NGC)" #endif #if defined mc68000 || defined m68k || defined __MC68K__ || defined m68000 # define POSH_CPU_68K 1 # define POSH_CPU_STRING "MC68000" #endif #if defined __PPC__ || defined __POWERPC__ || defined powerpc || defined _POWER || defined __ppc__ || defined __powerpc__ # define POSH_CPU_PPC 1 # if !defined POSH_CPU_STRING # if defined __powerpc64__ # define POSH_CPU_STRING "PowerPC64" # else # define POSH_CPU_STRING "PowerPC" # endif # endif #endif #if defined _CRAYT3E || defined _CRAYMPP # define POSH_CPU_CRAYT3E 1 /* target processor is a DEC Alpha 21164 used in a Cray T3E*/ # define POSH_CPU_STRING "Cray T3E (Alpha 21164)" #endif #if defined CRAY || defined _CRAY && !defined _CRAYT3E # error Non-AXP Cray systems not supported #endif #if defined _SH3 # define POSH_CPU_SH3 1 # define POSH_CPU_STRING "Hitachi SH-3" #endif #if defined __sh4__ || defined __SH4__ # define POSH_CPU_SH3 1 # define POSH_CPU_SH4 1 # define POSH_CPU_STRING "Hitachi SH-4" #endif #if defined __sparc__ || defined __sparc # if defined __arch64__ || defined __sparcv9 || defined __sparc_v9__ # define POSH_CPU_SPARC64 1 # define POSH_CPU_STRING "Sparc/64" # else # define POSH_CPU_STRING "Sparc/32" # endif # define POSH_CPU_SPARC 1 #endif #if defined ARM || defined __arm__ || defined _ARM # define POSH_CPU_STRONGARM 1 # define POSH_CPU_STRING "ARM" #endif #if defined mips || defined __mips__ || defined __MIPS__ || defined _MIPS # define POSH_CPU_MIPS 1 # if defined _R5900 # define POSH_CPU_STRING "MIPS R5900 (PS2)" # else # define POSH_CPU_STRING "MIPS" # endif #endif #if defined __ia64 || defined _M_IA64 || defined __ia64__ # define POSH_CPU_IA64 1 # define POSH_CPU_STRING "IA64" #endif #if defined __X86__ || defined __i386__ || defined i386 || defined _M_IX86 || defined __386__ || defined __x86_64__ || defined _M_X64 # define POSH_CPU_X86 1 # if defined __x86_64__ || defined _M_X64 # define POSH_CPU_X86_64 1 # endif # if defined POSH_CPU_X86_64 # define POSH_CPU_STRING "AMD x86-64" # else # define POSH_CPU_STRING "Intel 386+" # endif #endif #if defined __alpha || defined alpha || defined _M_ALPHA || defined __alpha__ # define POSH_CPU_AXP 1 # define POSH_CPU_STRING "AXP" #endif #if defined __hppa || defined hppa # define POSH_CPU_HPPA 1 # define POSH_CPU_STRING "PA-RISC" #endif #if !defined POSH_CPU_STRING # error POSH cannot determine target CPU # define POSH_CPU_STRING "Unknown" /* this is here for Doxygen's benefit */ #endif /* ** ----------------------------------------------------------------------------- ** Attempt to autodetect building for embedded on Sony PS2 ** ----------------------------------------------------------------------------- */ #if !defined POSH_OS_STRING # if !defined FORCE_DOXYGEN # define POSH_OS_EMBEDDED 1 # endif # if defined _R5900 # define POSH_OS_STRING "Sony PS2(embedded)" # else # define POSH_OS_STRING "Embedded/Unknown" # endif #endif /* ** --------------------------------------------------------------------------- ** Handle cdecl, stdcall, fastcall, etc. ** --------------------------------------------------------------------------- */ #if defined POSH_CPU_X86 && !defined POSH_CPU_X86_64 # if defined __GNUC__ # define POSH_CDECL __attribute__((cdecl)) # define POSH_STDCALL __attribute__((stdcall)) # define POSH_FASTCALL __attribute__((fastcall)) # elif ( defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ || defined __MWERKS__ ) # define POSH_CDECL __cdecl # define POSH_STDCALL __stdcall # define POSH_FASTCALL __fastcall # endif #else # define POSH_CDECL # define POSH_STDCALL # define POSH_FASTCALL #endif /* ** --------------------------------------------------------------------------- ** Define POSH_IMPORTEXPORT signature based on POSH_DLL and POSH_BUILDING_LIB ** --------------------------------------------------------------------------- */ /* ** We undefine this so that multiple inclusions will work */ #if defined POSH_IMPORTEXPORT # undef POSH_IMPORTEXPORT #endif #if defined POSH_DLL # if defined POSH_OS_WIN32 # if defined _MSC_VER # if ( _MSC_VER >= 800 ) # if defined POSH_BUILDING_LIB # define POSH_IMPORTEXPORT __declspec( dllexport ) # else # define POSH_IMPORTEXPORT __declspec( dllimport ) # endif # else # if defined POSH_BUILDING_LIB # define POSH_IMPORTEXPORT __export # else # define POSH_IMPORTEXPORT # endif # endif # endif /* defined _MSC_VER */ # if defined __BORLANDC__ # if ( __BORLANDC__ >= 0x500 ) # if defined POSH_BUILDING_LIB # define POSH_IMPORTEXPORT __declspec( dllexport ) # else # define POSH_IMPORTEXPORT __declspec( dllimport ) # endif # else # if defined POSH_BUILDING_LIB # define POSH_IMPORTEXPORT __export # else # define POSH_IMPORTEXPORT # endif # endif # endif /* defined __BORLANDC__ */ /* for all other compilers, we're just making a blanket assumption */ # if defined __GNUC__ || defined __WATCOMC__ || defined __MWERKS__ # if defined POSH_BUILDING_LIB # define POSH_IMPORTEXPORT __declspec( dllexport ) # else # define POSH_IMPORTEXPORT __declspec( dllimport ) # endif # endif /* all other compilers */ # if !defined POSH_IMPORTEXPORT # error Building DLLs not supported on this compiler (poshlib@poshlib.org if you know how) # endif # endif /* defined POSH_OS_WIN32 */ #endif /* On pretty much everything else, we can thankfully just ignore this */ #if !defined POSH_IMPORTEXPORT # define POSH_IMPORTEXPORT #endif #if defined FORCE_DOXYGEN # define POSH_DLL # define POSH_BUILDING_LIB # undef POSH_DLL # undef POSH_BUILDING_LIB #endif /* ** ---------------------------------------------------------------------------- ** (Re)define POSH_PUBLIC_API export signature ** ---------------------------------------------------------------------------- */ #ifdef POSH_PUBLIC_API # undef POSH_PUBLIC_API #endif #if ( ( defined _MSC_VER ) && ( _MSC_VER < 800 ) ) || ( defined __BORLANDC__ && ( __BORLANDC__ < 0x500 ) ) # define POSH_PUBLIC_API(rtype) extern rtype POSH_IMPORTEXPORT #else # define POSH_PUBLIC_API(rtype) extern POSH_IMPORTEXPORT rtype #endif /* ** ---------------------------------------------------------------------------- ** Try to infer endianess. Basically we just go through the CPUs we know are ** little endian, and assume anything that isn't one of those is big endian. ** As a sanity check, we also do this with operating systems we know are ** little endian, such as Windows. Some processors are bi-endian, such as ** the MIPS series, so we have to be careful about those. ** ---------------------------------------------------------------------------- */ #if defined POSH_CPU_X86 || defined POSH_CPU_AXP || defined POSH_CPU_STRONGARM || defined POSH_OS_WIN32 || defined POSH_OS_WINCE || defined __MIPSEL__ # define POSH_ENDIAN_STRING "little" # define POSH_LITTLE_ENDIAN 1 #else # define POSH_ENDIAN_STRING "big" # define POSH_BIG_ENDIAN 1 #endif #if defined FORCE_DOXYGEN # define POSH_LITTLE_ENDIAN #endif /* ** ---------------------------------------------------------------------------- ** Cross-platform compile time assertion macro ** ---------------------------------------------------------------------------- */ #define POSH_COMPILE_TIME_ASSERT(name, x) typedef int _POSH_dummy_ ## name[(x) ? 1 : -1 ] /* ** ---------------------------------------------------------------------------- ** 64-bit Integer ** ** We don't require 64-bit support, nor do we emulate its functionality, we ** simply export it if it's available. Since we can't count on ** for 64-bit support, we ignore the POSH_USE_LIMITS_H directive. ** ---------------------------------------------------------------------------- */ #if defined ( __LP64__ ) || defined ( __powerpc64__ ) || defined POSH_CPU_SPARC64 # define POSH_64BIT_INTEGER 1 typedef long posh_i64_t; typedef unsigned long posh_u64_t; # define POSH_I64( x ) ((posh_i64_t)x) # define POSH_U64( x ) ((posh_u64_t)x) # define POSH_I64_PRINTF_PREFIX "l" #elif defined _MSC_VER || defined __BORLANDC__ || defined __WATCOMC__ || ( defined __alpha && defined __DECC ) # define POSH_64BIT_INTEGER 1 typedef __int64 posh_i64_t; typedef unsigned __int64 posh_u64_t; # define POSH_I64( x ) ((posh_i64_t)x) # define POSH_U64( x ) ((posh_u64_t)x) # define POSH_I64_PRINTF_PREFIX "I64" #elif defined __GNUC__ || defined __MWERKS__ || defined __SUNPRO_C || defined __SUNPRO_CC || defined __APPLE_CC__ || defined POSH_OS_IRIX || defined _LONG_LONG || defined _CRAYC # define POSH_64BIT_INTEGER 1 typedef long long posh_i64_t; typedef unsigned long long posh_u64_t; # define POSH_U64( x ) ((posh_u64_t)(x##LL)) # define POSH_I64( x ) ((posh_i64_t)(x##LL)) # define POSH_I64_PRINTF_PREFIX "ll" #endif /* hack */ /*#ifdef __MINGW32__ #undef POSH_I64 #undef POSH_U64 #undef POSH_I64_PRINTF_PREFIX #define POSH_I64( x ) ((posh_i64_t)x) #define POSH_U64( x ) ((posh_u64_t)x) #define POSH_I64_PRINTF_PREFIX "I64" #endif*/ #ifdef FORCE_DOXYGEN typedef long long posh_i64_t; typedef unsigned long posh_u64_t; # define POSH_64BIT_INTEGER # define POSH_I64_PRINTF_PREFIX # define POSH_I64(x) # define POSH_U64(x) #endif /** Minimum value for a 64-bit signed integer */ #define POSH_I64_MIN POSH_I64(0x8000000000000000) /** Maximum value for a 64-bit signed integer */ #define POSH_I64_MAX POSH_I64(0x7FFFFFFFFFFFFFFF) /** Minimum value for a 64-bit unsigned integer */ #define POSH_U64_MIN POSH_U64(0) /** Maximum value for a 64-bit unsigned integer */ #define POSH_U64_MAX POSH_U64(0xFFFFFFFFFFFFFFFF) /* ---------------------------------------------------------------------------- ** Basic Sized Types ** ** These types are expected to be EXACTLY sized so you can use them for ** serialization. ** ---------------------------------------------------------------------------- */ #define POSH_FALSE 0 #define POSH_TRUE 1 typedef int posh_bool_t; typedef unsigned char posh_byte_t; /* NOTE: These assume that CHAR_BIT is 8!! */ typedef unsigned char posh_u8_t; typedef signed char posh_i8_t; #if defined POSH_USE_LIMITS_H # if CHAR_BITS > 8 # error This machine uses 9-bit characters. This is a warning, you can comment this out now. # endif /* CHAR_BITS > 8 */ /* 16-bit */ # if ( USHRT_MAX == 65535 ) typedef unsigned short posh_u16_t; typedef short posh_i16_t; # else /* Yes, in theory there could still be a 16-bit character type and shorts are 32-bits in size...if you find such an architecture, let me know =P */ # error No 16-bit type found # endif /* 32-bit */ # if ( INT_MAX == 2147483647 ) typedef unsigned posh_u32_t; typedef int posh_i32_t; # elif ( LONG_MAX == 2147483647 ) typedef unsigned long posh_u32_t; typedef long posh_i32_t; # else error No 32-bit type found # endif #else /* POSH_USE_LIMITS_H */ typedef unsigned short posh_u16_t; typedef short posh_i16_t; # if !defined POSH_OS_PALM typedef unsigned posh_u32_t; typedef int posh_i32_t; # else typedef unsigned long posh_u32_t; typedef long posh_i32_t; # endif #endif /** Minimum value for a byte */ #define POSH_BYTE_MIN 0 /** Maximum value for an 8-bit unsigned value */ #define POSH_BYTE_MAX 255 /** Minimum value for a byte */ #define POSH_I16_MIN ( ( posh_i16_t ) 0x8000 ) /** Maximum value for a 16-bit signed value */ #define POSH_I16_MAX ( ( posh_i16_t ) 0x7FFF ) /** Minimum value for a 16-bit unsigned value */ #define POSH_U16_MIN 0 /** Maximum value for a 16-bit unsigned value */ #define POSH_U16_MAX ( ( posh_u16_t ) 0xFFFF ) /** Minimum value for a 32-bit signed value */ #define POSH_I32_MIN ( ( posh_i32_t ) 0x80000000 ) /** Maximum value for a 32-bit signed value */ #define POSH_I32_MAX ( ( posh_i32_t ) 0x7FFFFFFF ) /** Minimum value for a 32-bit unsigned value */ #define POSH_U32_MIN 0 /** Maximum value for a 32-bit unsigned value */ #define POSH_U32_MAX ( ( posh_u32_t ) 0xFFFFFFFF ) /* ** ---------------------------------------------------------------------------- ** Sanity checks on expected sizes ** ---------------------------------------------------------------------------- */ #if !defined FORCE_DOXYGEN POSH_COMPILE_TIME_ASSERT(posh_byte_t, sizeof(posh_byte_t) == 1); POSH_COMPILE_TIME_ASSERT(posh_u8_t, sizeof(posh_u8_t) == 1); POSH_COMPILE_TIME_ASSERT(posh_i8_t, sizeof(posh_i8_t) == 1); POSH_COMPILE_TIME_ASSERT(posh_u16_t, sizeof(posh_u16_t) == 2); POSH_COMPILE_TIME_ASSERT(posh_i16_t, sizeof(posh_i16_t) == 2); POSH_COMPILE_TIME_ASSERT(posh_u32_t, sizeof(posh_u32_t) == 4); POSH_COMPILE_TIME_ASSERT(posh_i32_t, sizeof(posh_i32_t) == 4); #if !defined POSH_NO_FLOAT POSH_COMPILE_TIME_ASSERT(posh_testfloat_t, sizeof(float)==4 ); POSH_COMPILE_TIME_ASSERT(posh_testdouble_t, sizeof(double)==8); #endif #if defined POSH_64BIT_INTEGER POSH_COMPILE_TIME_ASSERT(posh_u64_t, sizeof(posh_u64_t) == 8); POSH_COMPILE_TIME_ASSERT(posh_i64_t, sizeof(posh_i64_t) == 8); #endif #endif /* ** ---------------------------------------------------------------------------- ** 64-bit pointer support ** ---------------------------------------------------------------------------- */ #if defined POSH_CPU_AXP && ( defined POSH_OS_TRU64 || defined POSH_OS_LINUX ) # define POSH_64BIT_POINTER 1 #endif #if defined POSH_CPU_X86_64 && defined POSH_OS_LINUX # define POSH_64BIT_POINTER 1 #endif #if defined POSH_CPU_SPARC64 || defined POSH_OS_WIN64 || defined __64BIT__ || defined __LP64 || defined _LP64 || defined __LP64__ || defined _ADDR64 || defined _CRAYC # define POSH_64BIT_POINTER 1 #endif #if defined POSH_64BIT_POINTER POSH_COMPILE_TIME_ASSERT( posh_64bit_pointer, sizeof( void * ) == 8 ); #elif !defined FORCE_DOXYGEN /* if this assertion is hit then you're on a system that either has 64-bit addressing and we didn't catch it, or you're on a system with 16-bit pointers. In the latter case, POSH doesn't actually care, we're just triggering this assertion to make sure you're aware of the situation, so feel free to delete it. If this assertion is triggered on a known 32 or 64-bit platform, please let us know (poshlib@poshlib.org) */ POSH_COMPILE_TIME_ASSERT( posh_32bit_pointer, sizeof( void * ) == 4 ); #endif #if defined FORCE_DOXYGEN # define POSH_64BIT_POINTER #endif /* ** ---------------------------------------------------------------------------- ** POSH Utility Functions ** ** These are optional POSH utility functions that are not required if you don't ** need anything except static checking of your host and target environment. ** ** These functions are NOT wrapped with POSH_PUBLIC_API because I didn't want ** to enforce their export if your own library is only using them internally. ** ---------------------------------------------------------------------------- */ #ifdef __cplusplus extern "C" { #endif const char *POSH_GetArchString( void ); #if !defined POSH_NO_FLOAT posh_u32_t POSH_LittleFloatBits( float f ); posh_u32_t POSH_BigFloatBits( float f ); float POSH_FloatFromLittleBits( posh_u32_t bits ); float POSH_FloatFromBigBits( posh_u32_t bits ); void POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] ); double POSH_DoubleFromBits( const posh_byte_t src[ 8 ] ); /* unimplemented float *POSH_WriteFloatToLittle( void *dst, float f ); float *POSH_WriteFloatToBig( void *dst, float f ); float POSH_ReadFloatFromLittle( const void *src ); float POSH_ReadFloatFromBig( const void *src ); double *POSH_WriteDoubleToLittle( void *dst, double d ); double *POSH_WriteDoubleToBig( void *dst, double d ); double POSH_ReadDoubleFromLittle( const void *src ); double POSH_ReadDoubleFromBig( const void *src ); */ #endif /* !defined POSH_NO_FLOAT */ #if defined FORCE_DOXYGEN # define POSH_NO_FLOAT # undef POSH_NO_FLOAT #endif extern posh_u16_t POSH_SwapU16( posh_u16_t u ); extern posh_i16_t POSH_SwapI16( posh_i16_t u ); extern posh_u32_t POSH_SwapU32( posh_u32_t u ); extern posh_i32_t POSH_SwapI32( posh_i32_t u ); #if defined POSH_64BIT_INTEGER extern posh_u64_t POSH_SwapU64( posh_u64_t u ); extern posh_i64_t POSH_SwapI64( posh_i64_t u ); #endif /*POSH_64BIT_INTEGER */ extern posh_u16_t *POSH_WriteU16ToLittle( void *dst, posh_u16_t value ); extern posh_i16_t *POSH_WriteI16ToLittle( void *dst, posh_i16_t value ); extern posh_u32_t *POSH_WriteU32ToLittle( void *dst, posh_u32_t value ); extern posh_i32_t *POSH_WriteI32ToLittle( void *dst, posh_i32_t value ); extern posh_u16_t *POSH_WriteU16ToBig( void *dst, posh_u16_t value ); extern posh_i16_t *POSH_WriteI16ToBig( void *dst, posh_i16_t value ); extern posh_u32_t *POSH_WriteU32ToBig( void *dst, posh_u32_t value ); extern posh_i32_t *POSH_WriteI32ToBig( void *dst, posh_i32_t value ); extern posh_u16_t POSH_ReadU16FromLittle( const void *src ); extern posh_i16_t POSH_ReadI16FromLittle( const void *src ); extern posh_u32_t POSH_ReadU32FromLittle( const void *src ); extern posh_i32_t POSH_ReadI32FromLittle( const void *src ); extern posh_u16_t POSH_ReadU16FromBig( const void *src ); extern posh_i16_t POSH_ReadI16FromBig( const void *src ); extern posh_u32_t POSH_ReadU32FromBig( const void *src ); extern posh_i32_t POSH_ReadI32FromBig( const void *src ); #if defined POSH_64BIT_INTEGER extern posh_u64_t *POSH_WriteU64ToLittle( void *dst, posh_u64_t value ); extern posh_i64_t *POSH_WriteI64ToLittle( void *dst, posh_i64_t value ); extern posh_u64_t *POSH_WriteU64ToBig( void *dst, posh_u64_t value ); extern posh_i64_t *POSH_WriteI64ToBig( void *dst, posh_i64_t value ); extern posh_u64_t POSH_ReadU64FromLittle( const void *src ); extern posh_i64_t POSH_ReadI64FromLittle( const void *src ); extern posh_u64_t POSH_ReadU64FromBig( const void *src ); extern posh_i64_t POSH_ReadI64FromBig( const void *src ); #endif /* POSH_64BIT_INTEGER */ #if defined POSH_LITTLE_ENDIAN # define POSH_LittleU16(x) (x) # define POSH_LittleU32(x) (x) # define POSH_LittleI16(x) (x) # define POSH_LittleI32(x) (x) # if defined POSH_64BIT_INTEGER # define POSH_LittleU64(x) (x) # define POSH_LittleI64(x) (x) # endif /* defined POSH_64BIT_INTEGER */ # define POSH_BigU16(x) POSH_SwapU16(x) # define POSH_BigU32(x) POSH_SwapU32(x) # define POSH_BigI16(x) POSH_SwapI16(x) # define POSH_BigI32(x) POSH_SwapI32(x) # if defined POSH_64BIT_INTEGER # define POSH_BigU64(x) POSH_SwapU64(x) # define POSH_BigI64(x) POSH_SwapI64(x) # endif /* defined POSH_64BIT_INTEGER */ #else # define POSH_BigU16(x) (x) # define POSH_BigU32(x) (x) # define POSH_BigI16(x) (x) # define POSH_BigI32(x) (x) # if defined POSH_64BIT_INTEGER # define POSH_BigU64(x) (x) # define POSH_BigI64(x) (x) # endif /* POSH_64BIT_INTEGER */ # define POSH_LittleU16(x) POSH_SwapU16(x) # define POSH_LittleU32(x) POSH_SwapU32(x) # define POSH_LittleI16(x) POSH_SwapI16(x) # define POSH_LittleI32(x) POSH_SwapI32(x) # if defined POSH_64BIT_INTEGER # define POSH_LittleU64(x) POSH_SwapU64(x) # define POSH_LittleI64(x) POSH_SwapI64(x) # endif /* POSH_64BIT_INTEGER */ #endif #ifdef __cplusplus } #endif nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/000077500000000000000000000000001173441656100211315ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/BlockDXT.cpp000066400000000000000000000412341173441656100232530ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include "ColorBlock.h" #include "BlockDXT.h" using namespace nv; /*---------------------------------------------------------------------------- BlockDXT1 ----------------------------------------------------------------------------*/ uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const { // Does bit expansion before interpolation. color_array[0].b = (col0.b << 3) | (col0.b >> 2); color_array[0].g = (col0.g << 2) | (col0.g >> 4); color_array[0].r = (col0.r << 3) | (col0.r >> 2); color_array[0].a = 0xFF; // @@ Same as above, but faster? // Color32 c; // c.u = ((col0.u << 3) & 0xf8) | ((col0.u << 5) & 0xfc00) | ((col0.u << 8) & 0xf80000); // c.u |= (c.u >> 5) & 0x070007; // c.u |= (c.u >> 6) & 0x000300; // color_array[0].u = c.u; color_array[1].r = (col1.r << 3) | (col1.r >> 2); color_array[1].g = (col1.g << 2) | (col1.g >> 4); color_array[1].b = (col1.b << 3) | (col1.b >> 2); color_array[1].a = 0xFF; // @@ Same as above, but faster? // c.u = ((col1.u << 3) & 0xf8) | ((col1.u << 5) & 0xfc00) | ((col1.u << 8) & 0xf80000); // c.u |= (c.u >> 5) & 0x070007; // c.u |= (c.u >> 6) & 0x000300; // color_array[1].u = c.u; if( col0.u > col1.u ) { // Four-color block: derive the other two colors. color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3; color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; color_array[2].a = 0xFF; color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3; color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; color_array[3].a = 0xFF; return 4; } else { // Three-color block: derive the other color. color_array[2].r = (color_array[0].r + color_array[1].r) / 2; color_array[2].g = (color_array[0].g + color_array[1].g) / 2; color_array[2].b = (color_array[0].b + color_array[1].b) / 2; color_array[2].a = 0xFF; // Set all components to 0 to match DXT specs. color_array[3].r = 0x00; // color_array[2].r; color_array[3].g = 0x00; // color_array[2].g; color_array[3].b = 0x00; // color_array[2].b; color_array[3].a = 0x00; return 3; } } // Evaluate palette assuming 3 color block. void BlockDXT1::evaluatePalette3(Color32 color_array[4]) const { color_array[0].b = (col0.b << 3) | (col0.b >> 2); color_array[0].g = (col0.g << 2) | (col0.g >> 4); color_array[0].r = (col0.r << 3) | (col0.r >> 2); color_array[0].a = 0xFF; color_array[1].r = (col1.r << 3) | (col1.r >> 2); color_array[1].g = (col1.g << 2) | (col1.g >> 4); color_array[1].b = (col1.b << 3) | (col1.b >> 2); color_array[1].a = 0xFF; // Three-color block: derive the other color. color_array[2].r = (color_array[0].r + color_array[1].r) / 2; color_array[2].g = (color_array[0].g + color_array[1].g) / 2; color_array[2].b = (color_array[0].b + color_array[1].b) / 2; color_array[2].a = 0xFF; // Set all components to 0 to match DXT specs. color_array[3].r = 0x00; // color_array[2].r; color_array[3].g = 0x00; // color_array[2].g; color_array[3].b = 0x00; // color_array[2].b; color_array[3].a = 0x00; } // Evaluate palette assuming 4 color block. void BlockDXT1::evaluatePalette4(Color32 color_array[4]) const { color_array[0].b = (col0.b << 3) | (col0.b >> 2); color_array[0].g = (col0.g << 2) | (col0.g >> 4); color_array[0].r = (col0.r << 3) | (col0.r >> 2); color_array[0].a = 0xFF; color_array[1].r = (col1.r << 3) | (col1.r >> 2); color_array[1].g = (col1.g << 2) | (col1.g >> 4); color_array[1].b = (col1.b << 3) | (col1.b >> 2); color_array[1].a = 0xFF; // Four-color block: derive the other two colors. color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3; color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; color_array[2].a = 0xFF; color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3; color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; color_array[3].a = 0xFF; } /* Jason Dorie's code. // ---------------------------------------------------------------------------- // Build palette for a 3 color + traparent black block // ---------------------------------------------------------------------------- void DXTCGen::BuildCodes3(cbVector *pVects, cbVector &v1, cbVector &v2) { //pVects[0] = v1; //pVects[2] = v2; //pVects[1][0] = v1[0]; //pVects[1][1] = (BYTE)( ((long)v1[1] + (long)v2[1]) / 2 ); //pVects[1][2] = (BYTE)( ((long)v1[2] + (long)v2[2]) / 2 ); //pVects[1][3] = (BYTE)( ((long)v1[3] + (long)v2[3]) / 2 ); __asm { mov ecx, dword ptr pVects mov eax, dword ptr v1 mov ebx, dword ptr v2 movd mm0, [eax] movd mm1, [ebx] pxor mm2, mm2 nop movd [ecx], mm0 movd [ecx+8], mm1 punpcklbw mm0, mm2 punpcklbw mm1, mm2 paddw mm0, mm1 psrlw mm0, 1 packuswb mm0, mm0 movd [ecx+4], mm0 } // *(long *)&pVects[1] = r1; } __int64 ScaleOneThird = 0x5500550055005500; // ---------------------------------------------------------------------------- // Build palette for a 4 color block // ---------------------------------------------------------------------------- void DXTCGen::BuildCodes4(cbVector *pVects, cbVector &v1, cbVector &v2) { // pVects[0] = v1; // pVects[3] = v2; // // pVects[1][0] = v1[0]; // pVects[1][1] = (BYTE)( ((long)v1[1] * 2 + (long)v2[1]) / 3 ); // pVects[1][2] = (BYTE)( ((long)v1[2] * 2 + (long)v2[2]) / 3 ); // pVects[1][3] = (BYTE)( ((long)v1[3] * 2 + (long)v2[3]) / 3 ); // // pVects[2][0] = v1[0]; // pVects[2][1] = (BYTE)( ((long)v2[1] * 2 + (long)v1[1]) / 3 ); // pVects[2][2] = (BYTE)( ((long)v2[2] * 2 + (long)v1[2]) / 3 ); // pVects[2][3] = (BYTE)( ((long)v2[3] * 2 + (long)v1[3]) / 3 ); __asm { mov ecx, dword ptr pVects mov eax, dword ptr v1 mov ebx, dword ptr v2 movd mm0, [eax] movd mm1, [ebx] pxor mm2, mm2 movd [ecx], mm0 movd [ecx+12], mm1 punpcklbw mm0, mm2 punpcklbw mm1, mm2 movq mm3, mm0 // mm3 = v0 paddw mm0, mm1 // mm0 = v0 + v1 paddw mm3, mm3 // mm3 = v0*2 paddw mm0, mm1 // mm0 = v0 + v1*2 paddw mm1, mm3 // mm1 = v0*2 + v1 pmulhw mm0, ScaleOneThird pmulhw mm1, ScaleOneThird packuswb mm1, mm0 movq [ecx+4], mm1 } } */ void BlockDXT1::decodeBlock(ColorBlock * block) const { nvDebugCheck(block != NULL); // Decode color block. Color32 color_array[4]; evaluatePalette(color_array); // Write color block. for( uint j = 0; j < 4; j++ ) { for( uint i = 0; i < 4; i++ ) { uint idx = (row[j] >> (2 * i)) & 3; block->color(i, j) = color_array[idx]; } } } void BlockDXT1::setIndices(int * idx) { indices = 0; for(uint i = 0; i < 16; i++) { indices |= (idx[i] & 3) << (2 * i); } } /// Flip DXT1 block vertically. inline void BlockDXT1::flip4() { swap(row[0], row[3]); swap(row[1], row[2]); } /// Flip half DXT1 block vertically. inline void BlockDXT1::flip2() { swap(row[0], row[1]); } /*---------------------------------------------------------------------------- BlockDXT3 ----------------------------------------------------------------------------*/ void BlockDXT3::decodeBlock(ColorBlock * block) const { nvDebugCheck(block != NULL); // Decode color. color.decodeBlock(block); // Decode alpha. alpha.decodeBlock(block); } void AlphaBlockDXT3::decodeBlock(ColorBlock * block) const { nvDebugCheck(block != NULL); block->color(0x0).a = (alpha0 << 4) | alpha0; block->color(0x1).a = (alpha1 << 4) | alpha1; block->color(0x2).a = (alpha2 << 4) | alpha2; block->color(0x3).a = (alpha3 << 4) | alpha3; block->color(0x4).a = (alpha4 << 4) | alpha4; block->color(0x5).a = (alpha5 << 4) | alpha5; block->color(0x6).a = (alpha6 << 4) | alpha6; block->color(0x7).a = (alpha7 << 4) | alpha7; block->color(0x8).a = (alpha8 << 4) | alpha8; block->color(0x9).a = (alpha9 << 4) | alpha9; block->color(0xA).a = (alphaA << 4) | alphaA; block->color(0xB).a = (alphaB << 4) | alphaB; block->color(0xC).a = (alphaC << 4) | alphaC; block->color(0xD).a = (alphaD << 4) | alphaD; block->color(0xE).a = (alphaE << 4) | alphaE; block->color(0xF).a = (alphaF << 4) | alphaF; } /// Flip DXT3 alpha block vertically. void AlphaBlockDXT3::flip4() { swap(row[0], row[3]); swap(row[1], row[2]); } /// Flip half DXT3 alpha block vertically. void AlphaBlockDXT3::flip2() { swap(row[0], row[1]); } /// Flip DXT3 block vertically. void BlockDXT3::flip4() { alpha.flip4(); color.flip4(); } /// Flip half DXT3 block vertically. void BlockDXT3::flip2() { alpha.flip2(); color.flip2(); } /*---------------------------------------------------------------------------- BlockDXT5 ----------------------------------------------------------------------------*/ void AlphaBlockDXT5::evaluatePalette(uint8 alpha[8]) const { if (alpha0 > alpha1) { evaluatePalette8(alpha); } else { evaluatePalette6(alpha); } } void AlphaBlockDXT5::evaluatePalette8(uint8 alpha[8]) const { // 8-alpha block: derive the other six alphas. // Bit code 000 = alpha0, 001 = alpha1, others are interpolated. alpha[0] = alpha0; alpha[1] = alpha1; alpha[2] = (6 * alpha[0] + 1 * alpha[1]) / 7; // bit code 010 alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7; // bit code 011 alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7; // bit code 100 alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7; // bit code 101 alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7; // bit code 110 alpha[7] = (1 * alpha[0] + 6 * alpha[1]) / 7; // bit code 111 } void AlphaBlockDXT5::evaluatePalette6(uint8 alpha[8]) const { // 6-alpha block. // Bit code 000 = alpha0, 001 = alpha1, others are interpolated. alpha[0] = alpha0; alpha[1] = alpha1; alpha[2] = (4 * alpha[0] + 1 * alpha[1]) / 5; // Bit code 010 alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5; // Bit code 011 alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5; // Bit code 100 alpha[5] = (1 * alpha[0] + 4 * alpha[1]) / 5; // Bit code 101 alpha[6] = 0x00; // Bit code 110 alpha[7] = 0xFF; // Bit code 111 } void AlphaBlockDXT5::indices(uint8 index_array[16]) const { index_array[0x0] = bits0; index_array[0x1] = bits1; index_array[0x2] = bits2; index_array[0x3] = bits3; index_array[0x4] = bits4; index_array[0x5] = bits5; index_array[0x6] = bits6; index_array[0x7] = bits7; index_array[0x8] = bits8; index_array[0x9] = bits9; index_array[0xA] = bitsA; index_array[0xB] = bitsB; index_array[0xC] = bitsC; index_array[0xD] = bitsD; index_array[0xE] = bitsE; index_array[0xF] = bitsF; } uint AlphaBlockDXT5::index(uint index) const { nvDebugCheck(index < 16); int offset = (3 * index + 16); return uint((this->u >> offset) & 0x7); } void AlphaBlockDXT5::setIndex(uint index, uint value) { nvDebugCheck(index < 16); nvDebugCheck(value < 8); int offset = (3 * index + 16); uint64 mask = uint64(0x7) << offset; this->u = (this->u & ~mask) | (uint64(value) << offset); } void AlphaBlockDXT5::decodeBlock(ColorBlock * block) const { nvDebugCheck(block != NULL); uint8 alpha_array[8]; evaluatePalette(alpha_array); uint8 index_array[16]; indices(index_array); for(uint i = 0; i < 16; i++) { block->color(i).a = alpha_array[index_array[i]]; } } void AlphaBlockDXT5::flip4() { uint64 * b = (uint64 *)this; // @@ The masks might have to be byte swapped. uint64 tmp = (*b & POSH_U64(0x000000000000FFFF)); tmp |= (*b & POSH_U64(0x000000000FFF0000)) << 36; tmp |= (*b & POSH_U64(0x000000FFF0000000)) << 12; tmp |= (*b & POSH_U64(0x000FFF0000000000)) >> 12; tmp |= (*b & POSH_U64(0xFFF0000000000000)) >> 36; *b = tmp; } void AlphaBlockDXT5::flip2() { uint * b = (uint *)this; // @@ The masks might have to be byte swapped. uint tmp = (*b & 0xFF000000); tmp |= (*b & 0x00000FFF) << 12; tmp |= (*b & 0x00FFF000) >> 12; *b = tmp; } void BlockDXT5::decodeBlock(ColorBlock * block) const { nvDebugCheck(block != NULL); // Decode color. color.decodeBlock(block); // Decode alpha. alpha.decodeBlock(block); } /// Flip DXT5 block vertically. void BlockDXT5::flip4() { alpha.flip4(); color.flip4(); } /// Flip half DXT5 block vertically. void BlockDXT5::flip2() { alpha.flip2(); color.flip2(); } /// Decode ATI1 block. void BlockATI1::decodeBlock(ColorBlock * block) const { uint8 alpha_array[8]; alpha.evaluatePalette(alpha_array); uint8 index_array[16]; alpha.indices(index_array); for(uint i = 0; i < 16; i++) { Color32 & c = block->color(i); c.b = c.g = c.r = alpha_array[index_array[i]]; c.a = 255; } } /// Flip ATI1 block vertically. void BlockATI1::flip4() { alpha.flip4(); } /// Flip half ATI1 block vertically. void BlockATI1::flip2() { alpha.flip2(); } /// Decode ATI2 block. void BlockATI2::decodeBlock(ColorBlock * block) const { uint8 alpha_array[8]; uint8 index_array[16]; x.evaluatePalette(alpha_array); x.indices(index_array); for(uint i = 0; i < 16; i++) { Color32 & c = block->color(i); c.r = alpha_array[index_array[i]]; } y.evaluatePalette(alpha_array); y.indices(index_array); for(uint i = 0; i < 16; i++) { Color32 & c = block->color(i); c.g = alpha_array[index_array[i]]; c.b = 0; c.a = 255; } } /// Flip ATI2 block vertically. void BlockATI2::flip4() { x.flip4(); y.flip4(); } /// Flip half ATI2 block vertically. void BlockATI2::flip2() { x.flip2(); y.flip2(); } void BlockCTX1::evaluatePalette(Color32 color_array[4]) const { // Does bit expansion before interpolation. color_array[0].b = 0x00; color_array[0].g = col0[1]; color_array[0].r = col0[0]; color_array[0].a = 0xFF; color_array[1].r = 0x00; color_array[1].g = col0[1]; color_array[1].b = col1[0]; color_array[1].a = 0xFF; color_array[2].r = 0x00; color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3; color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3; color_array[2].a = 0xFF; color_array[3].r = 0x00; color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3; color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3; color_array[3].a = 0xFF; } void BlockCTX1::decodeBlock(ColorBlock * block) const { nvDebugCheck(block != NULL); // Decode color block. Color32 color_array[4]; evaluatePalette(color_array); // Write color block. for( uint j = 0; j < 4; j++ ) { for( uint i = 0; i < 4; i++ ) { uint idx = (row[j] >> (2 * i)) & 3; block->color(i, j) = color_array[idx]; } } } void BlockCTX1::setIndices(int * idx) { indices = 0; for(uint i = 0; i < 16; i++) { indices |= (idx[i] & 3) << (2 * i); } } /// Flip CTX1 block vertically. inline void BlockCTX1::flip4() { swap(row[0], row[3]); swap(row[1], row[2]); } /// Flip half CTX1 block vertically. inline void BlockCTX1::flip2() { swap(row[0], row[1]); } Stream & nv::operator<<(Stream & stream, BlockDXT1 & block) { stream << block.col0.u << block.col1.u; stream.serialize(&block.indices, sizeof(block.indices)); return stream; } Stream & nv::operator<<(Stream & stream, AlphaBlockDXT3 & block) { stream.serialize(&block, sizeof(block)); return stream; } Stream & nv::operator<<(Stream & stream, BlockDXT3 & block) { return stream << block.alpha << block.color; } Stream & nv::operator<<(Stream & stream, AlphaBlockDXT5 & block) { stream.serialize(&block, sizeof(block)); return stream; } Stream & nv::operator<<(Stream & stream, BlockDXT5 & block) { return stream << block.alpha << block.color; } Stream & nv::operator<<(Stream & stream, BlockATI1 & block) { return stream << block.alpha; } Stream & nv::operator<<(Stream & stream, BlockATI2 & block) { return stream << block.x << block.y; } Stream & nv::operator<<(Stream & stream, BlockCTX1 & block) { stream.serialize(&block, sizeof(block)); return stream; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/BlockDXT.h000066400000000000000000000120601173441656100227130ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_IMAGE_BLOCKDXT_H #define NV_IMAGE_BLOCKDXT_H #include #include namespace nv { struct ColorBlock; class Stream; /// DXT1 block. struct BlockDXT1 { Color16 col0; Color16 col1; union { uint8 row[4]; uint indices; }; bool isFourColorMode() const; uint evaluatePalette(Color32 color_array[4]) const; uint evaluatePaletteFast(Color32 color_array[4]) const; void evaluatePalette3(Color32 color_array[4]) const; void evaluatePalette4(Color32 color_array[4]) const; void decodeBlock(ColorBlock * block) const; void setIndices(int * idx); void flip4(); void flip2(); }; /// Return true if the block uses four color mode, false otherwise. inline bool BlockDXT1::isFourColorMode() const { return col0.u > col1.u; } /// DXT3 alpha block with explicit alpha. struct AlphaBlockDXT3 { union { struct { uint alpha0 : 4; uint alpha1 : 4; uint alpha2 : 4; uint alpha3 : 4; uint alpha4 : 4; uint alpha5 : 4; uint alpha6 : 4; uint alpha7 : 4; uint alpha8 : 4; uint alpha9 : 4; uint alphaA : 4; uint alphaB : 4; uint alphaC : 4; uint alphaD : 4; uint alphaE : 4; uint alphaF : 4; }; uint16 row[4]; }; void decodeBlock(ColorBlock * block) const; void flip4(); void flip2(); }; /// DXT3 block. struct BlockDXT3 { AlphaBlockDXT3 alpha; BlockDXT1 color; void decodeBlock(ColorBlock * block) const; void flip4(); void flip2(); }; /// DXT5 alpha block. struct AlphaBlockDXT5 { union { struct { uint64 alpha0 : 8; // 8 uint64 alpha1 : 8; // 16 uint64 bits0 : 3; // 3 - 19 uint64 bits1 : 3; // 6 - 22 uint64 bits2 : 3; // 9 - 25 uint64 bits3 : 3; // 12 - 28 uint64 bits4 : 3; // 15 - 31 uint64 bits5 : 3; // 18 - 34 uint64 bits6 : 3; // 21 - 37 uint64 bits7 : 3; // 24 - 40 uint64 bits8 : 3; // 27 - 43 uint64 bits9 : 3; // 30 - 46 uint64 bitsA : 3; // 33 - 49 uint64 bitsB : 3; // 36 - 52 uint64 bitsC : 3; // 39 - 55 uint64 bitsD : 3; // 42 - 58 uint64 bitsE : 3; // 45 - 61 uint64 bitsF : 3; // 48 - 64 }; uint64 u; }; void evaluatePalette(uint8 alpha[8]) const; void evaluatePalette8(uint8 alpha[8]) const; void evaluatePalette6(uint8 alpha[8]) const; void indices(uint8 index_array[16]) const; uint index(uint index) const; void setIndex(uint index, uint value); void decodeBlock(ColorBlock * block) const; void flip4(); void flip2(); }; /// DXT5 block. struct BlockDXT5 { AlphaBlockDXT5 alpha; BlockDXT1 color; void decodeBlock(ColorBlock * block) const; void flip4(); void flip2(); }; /// ATI1 block. struct BlockATI1 { AlphaBlockDXT5 alpha; void decodeBlock(ColorBlock * block) const; void flip4(); void flip2(); }; /// ATI2 block. struct BlockATI2 { AlphaBlockDXT5 x; AlphaBlockDXT5 y; void decodeBlock(ColorBlock * block) const; void flip4(); void flip2(); }; /// CTX1 block. struct BlockCTX1 { uint8 col0[2]; uint8 col1[2]; union { uint8 row[4]; uint indices; }; void evaluatePalette(Color32 color_array[4]) const; void setIndices(int * idx); void decodeBlock(ColorBlock * block) const; void flip4(); void flip2(); }; // Serialization functions. NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT1 & block); NVIMAGE_API Stream & operator<<(Stream & stream, AlphaBlockDXT3 & block); NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT3 & block); NVIMAGE_API Stream & operator<<(Stream & stream, AlphaBlockDXT5 & block); NVIMAGE_API Stream & operator<<(Stream & stream, BlockDXT5 & block); NVIMAGE_API Stream & operator<<(Stream & stream, BlockATI1 & block); NVIMAGE_API Stream & operator<<(Stream & stream, BlockATI2 & block); NVIMAGE_API Stream & operator<<(Stream & stream, BlockCTX1 & block); } // nv namespace #endif // NV_IMAGE_BLOCKDXT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/CMakeLists.txt000066400000000000000000000024121173441656100236700ustar00rootroot00000000000000PROJECT(nvimage) SET(IMAGE_SRCS nvimage.h FloatImage.h FloatImage.cpp Filter.h Filter.cpp Image.h Image.cpp ImageIO.h ImageIO.cpp ColorBlock.h ColorBlock.cpp BlockDXT.h BlockDXT.cpp HoleFilling.h HoleFilling.cpp DirectDrawSurface.h DirectDrawSurface.cpp Quantize.h Quantize.cpp NormalMap.h NormalMap.cpp NormalMipmap.h NormalMipmap.cpp PsdFile.h TgaFile.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) IF(PNG_FOUND) SET(LIBS ${LIBS} ${PNG_LIBRARIES}) INCLUDE_DIRECTORIES(${PNG_INCLUDE_DIR}) ENDIF(PNG_FOUND) IF(JPEG_FOUND) SET(LIBS ${LIBS} ${JPEG_LIBRARIES}) INCLUDE_DIRECTORIES(${JPEG_INCLUDE_DIR}) ENDIF(JPEG_FOUND) IF(TIFF_FOUND) SET(LIBS ${LIBS} ${TIFF_LIBRARIES}) INCLUDE_DIRECTORIES(${TIFF_INCLUDE_DIR}) ENDIF(TIFF_FOUND) IF(OPENEXR_FOUND) SET(LIBS ${LIBS} ${OPENEXR_LIBRARIES}) INCLUDE_DIRECTORIES(${OPENEXR_INCLUDE_PATHS}) ENDIF(OPENEXR_FOUND) # targets ADD_DEFINITIONS(-DNVIMAGE_EXPORTS) IF(NVIMAGE_SHARED) ADD_DEFINITIONS(-DNVIMAGE_SHARED=1) ADD_LIBRARY(nvimage SHARED ${IMAGE_SRCS}) ELSE(NVIMAGE_SHARED) ADD_LIBRARY(nvimage ${IMAGE_SRCS}) ENDIF(NVIMAGE_SHARED) TARGET_LINK_LIBRARIES(nvimage ${LIBS} nvcore nvmath posh) INSTALL(TARGETS nvimage RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib/static) nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/ColorBlock.cpp000066400000000000000000000217221173441656100236720ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include #include using namespace nv; namespace { // Get approximate luminance. inline static uint colorLuminance(Color32 c) { return c.r + c.g + c.b; } // Get the euclidean distance between the given colors. inline static uint colorDistance(Color32 c0, Color32 c1) { return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) + (c0.b - c1.b) * (c0.b - c1.b); } } // namespace` /// Default constructor. ColorBlock::ColorBlock() { } /// Init the color block from an array of colors. ColorBlock::ColorBlock(const uint * linearImage) { for(uint i = 0; i < 16; i++) { color(i) = Color32(linearImage[i]); } } /// Init the color block with the contents of the given block. ColorBlock::ColorBlock(const ColorBlock & block) { for(uint i = 0; i < 16; i++) { color(i) = block.color(i); } } /// Initialize this color block. ColorBlock::ColorBlock(const Image * img, uint x, uint y) { init(img, x, y); } void ColorBlock::init(const Image * img, uint x, uint y) { nvDebugCheck(img != NULL); const uint bw = min(img->width() - x, 4U); const uint bh = min(img->height() - y, 4U); nvDebugCheck(bw != 0); nvDebugCheck(bh != 0); static int remainder[] = { 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 0, 0, 1, 2, 3, }; // Blocks that are smaller than 4x4 are handled by repeating the pixels. // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :( for(uint i = 0; i < 4; i++) { //const int by = i % bh; const int by = remainder[(bh - 1) * 4 + i]; for(uint e = 0; e < 4; e++) { //const int bx = e % bw; const int bx = remainder[(bw - 1) * 4 + e]; color(e, i) = img->pixel(x + bx, y + by); } } } void ColorBlock::swizzleDXT5n() { for(int i = 0; i < 16; i++) { Color32 c = m_color[i]; m_color[i] = Color32(0xFF, c.g, 0, c.r); } } void ColorBlock::splatX() { for(int i = 0; i < 16; i++) { uint8 x = m_color[i].r; m_color[i] = Color32(x, x, x, x); } } void ColorBlock::splatY() { for(int i = 0; i < 16; i++) { uint8 y = m_color[i].g; m_color[i] = Color32(y, y, y, y); } } /// Returns true if the block has a single color. bool ColorBlock::isSingleColor() const { Color32 mask(0xFF, 0xFF, 0xFF, 0x00); uint u = m_color[0].u & mask.u; for (int i = 1; i < 16; i++) { if (u != (m_color[i].u & mask.u)) { return false; } } return true; } /// Count number of unique colors in this color block. uint ColorBlock::countUniqueColors() const { uint count = 0; // @@ This does not have to be o(n^2) for(int i = 0; i < 16; i++) { bool unique = true; for(int j = 0; j < i; j++) { if( m_color[i] != m_color[j] ) { unique = false; } } if( unique ) { count++; } } return count; } /// Get average color of the block. Color32 ColorBlock::averageColor() const { uint r, g, b, a; r = g = b = a = 0; for(uint i = 0; i < 16; i++) { r += m_color[i].r; g += m_color[i].g; b += m_color[i].b; a += m_color[i].a; } return Color32(uint8(r / 16), uint8(g / 16), uint8(b / 16), uint8(a / 16)); } /// Return true if the block is not fully opaque. bool ColorBlock::hasAlpha() const { for (uint i = 0; i < 16; i++) { if (m_color[i].a != 255) return true; } return false; } /// Get diameter color range. void ColorBlock::diameterRange(Color32 * start, Color32 * end) const { nvDebugCheck(start != NULL); nvDebugCheck(end != NULL); Color32 c0, c1; uint best_dist = 0; for(int i = 0; i < 16; i++) { for (int j = i+1; j < 16; j++) { uint dist = colorDistance(m_color[i], m_color[j]); if( dist > best_dist ) { best_dist = dist; c0 = m_color[i]; c1 = m_color[j]; } } } *start = c0; *end = c1; } /// Get luminance color range. void ColorBlock::luminanceRange(Color32 * start, Color32 * end) const { nvDebugCheck(start != NULL); nvDebugCheck(end != NULL); Color32 minColor, maxColor; uint minLuminance, maxLuminance; maxLuminance = minLuminance = colorLuminance(m_color[0]); for(uint i = 1; i < 16; i++) { uint luminance = colorLuminance(m_color[i]); if (luminance > maxLuminance) { maxLuminance = luminance; maxColor = m_color[i]; } else if (luminance < minLuminance) { minLuminance = luminance; minColor = m_color[i]; } } *start = minColor; *end = maxColor; } /// Get color range based on the bounding box. void ColorBlock::boundsRange(Color32 * start, Color32 * end) const { nvDebugCheck(start != NULL); nvDebugCheck(end != NULL); Color32 minColor(255, 255, 255); Color32 maxColor(0, 0, 0); for(uint i = 0; i < 16; i++) { if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; } if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; } if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; } if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; } if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; } if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; } } // Offset range by 1/16 of the extents Color32 inset; inset.r = (maxColor.r - minColor.r) >> 4; inset.g = (maxColor.g - minColor.g) >> 4; inset.b = (maxColor.b - minColor.b) >> 4; minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255; minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255; minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255; maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0; maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0; maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0; *start = minColor; *end = maxColor; } /// Get color range based on the bounding box. void ColorBlock::boundsRangeAlpha(Color32 * start, Color32 * end) const { nvDebugCheck(start != NULL); nvDebugCheck(end != NULL); Color32 minColor(255, 255, 255, 255); Color32 maxColor(0, 0, 0, 0); for(uint i = 0; i < 16; i++) { if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; } if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; } if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; } if (m_color[i].a < minColor.a) { minColor.a = m_color[i].a; } if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; } if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; } if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; } if (m_color[i].a > maxColor.a) { maxColor.a = m_color[i].a; } } // Offset range by 1/16 of the extents Color32 inset; inset.r = (maxColor.r - minColor.r) >> 4; inset.g = (maxColor.g - minColor.g) >> 4; inset.b = (maxColor.b - minColor.b) >> 4; inset.a = (maxColor.a - minColor.a) >> 4; minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255; minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255; minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255; minColor.a = (minColor.a + inset.a <= 255) ? minColor.a + inset.a : 255; maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0; maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0; maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0; maxColor.a = (maxColor.a >= inset.a) ? maxColor.a - inset.a : 0; *start = minColor; *end = maxColor; } /// Sort colors by abosolute value in their 16 bit representation. void ColorBlock::sortColorsByAbsoluteValue() { // Dummy selection sort. for( uint a = 0; a < 16; a++ ) { uint max = a; Color16 cmax(m_color[a]); for( uint b = a+1; b < 16; b++ ) { Color16 cb(m_color[b]); if( cb.u > cmax.u ) { max = b; cmax = cb; } } swap( m_color[a], m_color[max] ); } } /// Find extreme colors in the given axis. void ColorBlock::computeRange(Vector3::Arg axis, Color32 * start, Color32 * end) const { nvDebugCheck(start != NULL); nvDebugCheck(end != NULL); int mini, maxi; mini = maxi = 0; float min, max; min = max = dot(Vector3(m_color[0].r, m_color[0].g, m_color[0].b), axis); for(uint i = 1; i < 16; i++) { const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b); float val = dot(vec, axis); if( val < min ) { mini = i; min = val; } else if( val > max ) { maxi = i; max = val; } } *start = m_color[mini]; *end = m_color[maxi]; } /// Sort colors in the given axis. void ColorBlock::sortColors(const Vector3 & axis) { float luma_array[16]; for(uint i = 0; i < 16; i++) { const Vector3 vec(m_color[i].r, m_color[i].g, m_color[i].b); luma_array[i] = dot(vec, axis); } // Dummy selection sort. for( uint a = 0; a < 16; a++ ) { uint min = a; for( uint b = a+1; b < 16; b++ ) { if( luma_array[b] < luma_array[min] ) { min = b; } } swap( luma_array[a], luma_array[min] ); swap( m_color[a], m_color[min] ); } } /// Get the volume of the color block. float ColorBlock::volume() const { Box bounds; bounds.clearBounds(); for(int i = 0; i < 16; i++) { const Vector3 point(m_color[i].r, m_color[i].g, m_color[i].b); bounds.addPointToBounds(point); } return bounds.volume(); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/ColorBlock.h000066400000000000000000000036761173441656100233470ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_COLORBLOCK_H #define NV_IMAGE_COLORBLOCK_H #include namespace nv { class Image; /// Uncompressed 4x4 color block. struct ColorBlock { ColorBlock(); ColorBlock(const uint * linearImage); ColorBlock(const ColorBlock & block); ColorBlock(const Image * img, uint x, uint y); void init(const Image * img, uint x, uint y); void swizzleDXT5n(); void splatX(); void splatY(); bool isSingleColor() const; uint countUniqueColors() const; Color32 averageColor() const; bool hasAlpha() const; void diameterRange(Color32 * start, Color32 * end) const; void luminanceRange(Color32 * start, Color32 * end) const; void boundsRange(Color32 * start, Color32 * end) const; void boundsRangeAlpha(Color32 * start, Color32 * end) const; void sortColorsByAbsoluteValue(); void computeRange(const Vector3 & axis, Color32 * start, Color32 * end) const; void sortColors(const Vector3 & axis); float volume() const; // Accessors const Color32 * colors() const; Color32 color(uint i) const; Color32 & color(uint i); Color32 color(uint x, uint y) const; Color32 & color(uint x, uint y); private: Color32 m_color[4*4]; }; /// Get pointer to block colors. inline const Color32 * ColorBlock::colors() const { return m_color; } /// Get block color. inline Color32 ColorBlock::color(uint i) const { nvDebugCheck(i < 16); return m_color[i]; } /// Get block color. inline Color32 & ColorBlock::color(uint i) { nvDebugCheck(i < 16); return m_color[i]; } /// Get block color. inline Color32 ColorBlock::color(uint x, uint y) const { nvDebugCheck(x < 4 && y < 4); return m_color[y * 4 + x]; } /// Get block color. inline Color32 & ColorBlock::color(uint x, uint y) { nvDebugCheck(x < 4 && y < 4); return m_color[y * 4 + x]; } } // nv namespace #endif // NV_IMAGE_COLORBLOCK_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/ConeMap.cpp000066400000000000000000000056241173441656100231660ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include using namespace nv; static float processPixel(const FloatImage * img, uint x, uint y) { nvDebugCheck(img != NULL); const uint w = img->width(); const uint h = img->height(); float d = img->pixel(x, y, 0); float fx0 = (float) x / w; float fy0 = (float) y / h; float best_ratio = INF; uint best_x = w; uint best_y = h; for (uint yy = 0; yy < h; yy++) { for (uint xx = 0; xx < w; xx++) { float ch = d - img->pixel(xx, yy, 0); if (ch > 0) { float dx = float(xx - x); float dy = float(yy - y); float ratio = (dx * dx + dy * dy) / ch; if (ratio < best_ratio) { best_x = xx; best_y = yy; } } } } if (best_x != w) { nvDebugCheck(best_y !=h); float dx = float(best_x - x) / w; float dy = float(best_y - y) / h; float cw = sqrtf(dx*dx + dy*dy); float ch = d - img->pixel(xx, yy, 0); return min(1, sqrtf(cw / ch)); } return 1; } // Create cone map using the given kernels. FloatImage * createConeMap(const Image * img, Vector4::Arg heightWeights) { nvCheck(img != NULL); const uint w = img->width(); const uint h = img->height(); AutoPtr fimage(new FloatImage()); //fimage->allocate(2, w, h); fimage->allocate(4, w, h); // Compute height and store in red channel: float * heightChannel = fimage->channel(0); for(uint i = 0; i < w*h; i++) { Vector4 color = toVector4(img->pixel(i)); heightChannel[i] = dot(color, heightWeights); } // Compute cones: for(uint y = 0; y < h; y++) { for(uint x = 0; x < w; x++) { processPixel(fimage, x, y); } } return fimage.release(); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/ConeMap.h000066400000000000000000000026541173441656100226330ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_IMAGE_CONEMAP_H #define NV_IMAGE_CONEMAP_H #include #include namespace nv { class Image; class FloatImage; FloatImage * createConeMap(const Image * img, Vector4::Arg heightWeights); } // nv namespace #endif // NV_IMAGE_CONEMAP_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/DirectDrawSurface.cpp000066400000000000000000001030251173441656100251770ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include // max #include #include #include #include #include #include #include // memset using namespace nv; #if !defined(MAKEFOURCC) # define MAKEFOURCC(ch0, ch1, ch2, ch3) \ (uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | \ (uint(uint8(ch2)) << 16) | (uint(uint8(ch3)) << 24 )) #endif namespace { static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' '); static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'); static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'); static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'); static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'); static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'); static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B'); static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1'); static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y'); static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0'); // 32 bit RGB formats. static const uint D3DFMT_R8G8B8 = 20; static const uint D3DFMT_A8R8G8B8 = 21; static const uint D3DFMT_X8R8G8B8 = 22; static const uint D3DFMT_R5G6B5 = 23; static const uint D3DFMT_X1R5G5B5 = 24; static const uint D3DFMT_A1R5G5B5 = 25; static const uint D3DFMT_A4R4G4B4 = 26; static const uint D3DFMT_R3G3B2 = 27; static const uint D3DFMT_A8 = 28; static const uint D3DFMT_A8R3G3B2 = 29; static const uint D3DFMT_X4R4G4B4 = 30; static const uint D3DFMT_A2B10G10R10 = 31; static const uint D3DFMT_A8B8G8R8 = 32; static const uint D3DFMT_X8B8G8R8 = 33; static const uint D3DFMT_G16R16 = 34; static const uint D3DFMT_A2R10G10B10 = 35; static const uint D3DFMT_A16B16G16R16 = 36; // Palette formats. static const uint D3DFMT_A8P8 = 40; static const uint D3DFMT_P8 = 41; // Luminance formats. static const uint D3DFMT_L8 = 50; static const uint D3DFMT_A8L8 = 51; static const uint D3DFMT_A4L4 = 52; static const uint D3DFMT_L16 = 81; // Floating point formats static const uint D3DFMT_R16F = 111; static const uint D3DFMT_G16R16F = 112; static const uint D3DFMT_A16B16G16R16F = 113; static const uint D3DFMT_R32F = 114; static const uint D3DFMT_G32R32F = 115; static const uint D3DFMT_A32B32G32R32F = 116; static const uint DDSD_CAPS = 0x00000001U; static const uint DDSD_PIXELFORMAT = 0x00001000U; static const uint DDSD_WIDTH = 0x00000004U; static const uint DDSD_HEIGHT = 0x00000002U; static const uint DDSD_PITCH = 0x00000008U; static const uint DDSD_MIPMAPCOUNT = 0x00020000U; static const uint DDSD_LINEARSIZE = 0x00080000U; static const uint DDSD_DEPTH = 0x00800000U; static const uint DDSCAPS_COMPLEX = 0x00000008U; static const uint DDSCAPS_TEXTURE = 0x00001000U; static const uint DDSCAPS_MIPMAP = 0x00400000U; static const uint DDSCAPS2_VOLUME = 0x00200000U; static const uint DDSCAPS2_CUBEMAP = 0x00000200U; static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U; static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U; static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U; static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U; static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U; static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U; static const uint DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U; static const uint DDPF_ALPHAPIXELS = 0x00000001U; static const uint DDPF_ALPHA = 0x00000002U; static const uint DDPF_FOURCC = 0x00000004U; static const uint DDPF_RGB = 0x00000040U; static const uint DDPF_PALETTEINDEXED1 = 0x00000800U; static const uint DDPF_PALETTEINDEXED2 = 0x00001000U; static const uint DDPF_PALETTEINDEXED4 = 0x00000008U; static const uint DDPF_PALETTEINDEXED8 = 0x00000020U; static const uint DDPF_LUMINANCE = 0x00020000U; static const uint DDPF_ALPHAPREMULT = 0x00008000U; static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag. // DX10 formats. enum DXGI_FORMAT { DXGI_FORMAT_UNKNOWN = 0, DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, DXGI_FORMAT_R32G32B32A32_FLOAT = 2, DXGI_FORMAT_R32G32B32A32_UINT = 3, DXGI_FORMAT_R32G32B32A32_SINT = 4, DXGI_FORMAT_R32G32B32_TYPELESS = 5, DXGI_FORMAT_R32G32B32_FLOAT = 6, DXGI_FORMAT_R32G32B32_UINT = 7, DXGI_FORMAT_R32G32B32_SINT = 8, DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, DXGI_FORMAT_R16G16B16A16_FLOAT = 10, DXGI_FORMAT_R16G16B16A16_UNORM = 11, DXGI_FORMAT_R16G16B16A16_UINT = 12, DXGI_FORMAT_R16G16B16A16_SNORM = 13, DXGI_FORMAT_R16G16B16A16_SINT = 14, DXGI_FORMAT_R32G32_TYPELESS = 15, DXGI_FORMAT_R32G32_FLOAT = 16, DXGI_FORMAT_R32G32_UINT = 17, DXGI_FORMAT_R32G32_SINT = 18, DXGI_FORMAT_R32G8X24_TYPELESS = 19, DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, DXGI_FORMAT_R10G10B10A2_UNORM = 24, DXGI_FORMAT_R10G10B10A2_UINT = 25, DXGI_FORMAT_R11G11B10_FLOAT = 26, DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, DXGI_FORMAT_R8G8B8A8_UNORM = 28, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, DXGI_FORMAT_R8G8B8A8_UINT = 30, DXGI_FORMAT_R8G8B8A8_SNORM = 31, DXGI_FORMAT_R8G8B8A8_SINT = 32, DXGI_FORMAT_R16G16_TYPELESS = 33, DXGI_FORMAT_R16G16_FLOAT = 34, DXGI_FORMAT_R16G16_UNORM = 35, DXGI_FORMAT_R16G16_UINT = 36, DXGI_FORMAT_R16G16_SNORM = 37, DXGI_FORMAT_R16G16_SINT = 38, DXGI_FORMAT_R32_TYPELESS = 39, DXGI_FORMAT_D32_FLOAT = 40, DXGI_FORMAT_R32_FLOAT = 41, DXGI_FORMAT_R32_UINT = 42, DXGI_FORMAT_R32_SINT = 43, DXGI_FORMAT_R24G8_TYPELESS = 44, DXGI_FORMAT_D24_UNORM_S8_UINT = 45, DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, DXGI_FORMAT_R8G8_TYPELESS = 48, DXGI_FORMAT_R8G8_UNORM = 49, DXGI_FORMAT_R8G8_UINT = 50, DXGI_FORMAT_R8G8_SNORM = 51, DXGI_FORMAT_R8G8_SINT = 52, DXGI_FORMAT_R16_TYPELESS = 53, DXGI_FORMAT_R16_FLOAT = 54, DXGI_FORMAT_D16_UNORM = 55, DXGI_FORMAT_R16_UNORM = 56, DXGI_FORMAT_R16_UINT = 57, DXGI_FORMAT_R16_SNORM = 58, DXGI_FORMAT_R16_SINT = 59, DXGI_FORMAT_R8_TYPELESS = 60, DXGI_FORMAT_R8_UNORM = 61, DXGI_FORMAT_R8_UINT = 62, DXGI_FORMAT_R8_SNORM = 63, DXGI_FORMAT_R8_SINT = 64, DXGI_FORMAT_A8_UNORM = 65, DXGI_FORMAT_R1_UNORM = 66, DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, DXGI_FORMAT_R8G8_B8G8_UNORM = 68, DXGI_FORMAT_G8R8_G8B8_UNORM = 69, DXGI_FORMAT_BC1_TYPELESS = 70, DXGI_FORMAT_BC1_UNORM = 71, DXGI_FORMAT_BC1_UNORM_SRGB = 72, DXGI_FORMAT_BC2_TYPELESS = 73, DXGI_FORMAT_BC2_UNORM = 74, DXGI_FORMAT_BC2_UNORM_SRGB = 75, DXGI_FORMAT_BC3_TYPELESS = 76, DXGI_FORMAT_BC3_UNORM = 77, DXGI_FORMAT_BC3_UNORM_SRGB = 78, DXGI_FORMAT_BC4_TYPELESS = 79, DXGI_FORMAT_BC4_UNORM = 80, DXGI_FORMAT_BC4_SNORM = 81, DXGI_FORMAT_BC5_TYPELESS = 82, DXGI_FORMAT_BC5_UNORM = 83, DXGI_FORMAT_BC5_SNORM = 84, DXGI_FORMAT_B5G6R5_UNORM = 85, DXGI_FORMAT_B5G5R5A1_UNORM = 86, DXGI_FORMAT_B8G8R8A8_UNORM = 87, DXGI_FORMAT_B8G8R8X8_UNORM = 88, }; enum D3D10_RESOURCE_DIMENSION { D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, D3D10_RESOURCE_DIMENSION_BUFFER = 1, D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4, }; const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) { #define CASE(format) case DXGI_FORMAT_##format: return #format switch(dxgiFormat) { CASE(UNKNOWN); CASE(R32G32B32A32_TYPELESS); CASE(R32G32B32A32_FLOAT); CASE(R32G32B32A32_UINT); CASE(R32G32B32A32_SINT); CASE(R32G32B32_TYPELESS); CASE(R32G32B32_FLOAT); CASE(R32G32B32_UINT); CASE(R32G32B32_SINT); CASE(R16G16B16A16_TYPELESS); CASE(R16G16B16A16_FLOAT); CASE(R16G16B16A16_UNORM); CASE(R16G16B16A16_UINT); CASE(R16G16B16A16_SNORM); CASE(R16G16B16A16_SINT); CASE(R32G32_TYPELESS); CASE(R32G32_FLOAT); CASE(R32G32_UINT); CASE(R32G32_SINT); CASE(R32G8X24_TYPELESS); CASE(D32_FLOAT_S8X24_UINT); CASE(R32_FLOAT_X8X24_TYPELESS); CASE(X32_TYPELESS_G8X24_UINT); CASE(R10G10B10A2_TYPELESS); CASE(R10G10B10A2_UNORM); CASE(R10G10B10A2_UINT); CASE(R11G11B10_FLOAT); CASE(R8G8B8A8_TYPELESS); CASE(R8G8B8A8_UNORM); CASE(R8G8B8A8_UNORM_SRGB); CASE(R8G8B8A8_UINT); CASE(R8G8B8A8_SNORM); CASE(R8G8B8A8_SINT); CASE(R16G16_TYPELESS); CASE(R16G16_FLOAT); CASE(R16G16_UNORM); CASE(R16G16_UINT); CASE(R16G16_SNORM); CASE(R16G16_SINT); CASE(R32_TYPELESS); CASE(D32_FLOAT); CASE(R32_FLOAT); CASE(R32_UINT); CASE(R32_SINT); CASE(R24G8_TYPELESS); CASE(D24_UNORM_S8_UINT); CASE(R24_UNORM_X8_TYPELESS); CASE(X24_TYPELESS_G8_UINT); CASE(R8G8_TYPELESS); CASE(R8G8_UNORM); CASE(R8G8_UINT); CASE(R8G8_SNORM); CASE(R8G8_SINT); CASE(R16_TYPELESS); CASE(R16_FLOAT); CASE(D16_UNORM); CASE(R16_UNORM); CASE(R16_UINT); CASE(R16_SNORM); CASE(R16_SINT); CASE(R8_TYPELESS); CASE(R8_UNORM); CASE(R8_UINT); CASE(R8_SNORM); CASE(R8_SINT); CASE(A8_UNORM); CASE(R1_UNORM); CASE(R9G9B9E5_SHAREDEXP); CASE(R8G8_B8G8_UNORM); CASE(G8R8_G8B8_UNORM); CASE(BC1_TYPELESS); CASE(BC1_UNORM); CASE(BC1_UNORM_SRGB); CASE(BC2_TYPELESS); CASE(BC2_UNORM); CASE(BC2_UNORM_SRGB); CASE(BC3_TYPELESS); CASE(BC3_UNORM); CASE(BC3_UNORM_SRGB); CASE(BC4_TYPELESS); CASE(BC4_UNORM); CASE(BC4_SNORM); CASE(BC5_TYPELESS); CASE(BC5_UNORM); CASE(BC5_SNORM); CASE(B5G6R5_UNORM); CASE(B5G5R5A1_UNORM); CASE(B8G8R8A8_UNORM); CASE(B8G8R8X8_UNORM); default: return "UNKNOWN"; } #undef CASE } const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) { switch(resourceDimension) { default: case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN"; case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER"; case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D"; case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D"; case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D"; } } } // namespace namespace nv { static Stream & operator<< (Stream & s, DDSPixelFormat & pf) { nvStaticCheck(sizeof(DDSPixelFormat) == 32); s << pf.size; s << pf.flags; s << pf.fourcc; s << pf.bitcount; s << pf.rmask; s << pf.gmask; s << pf.bmask; s << pf.amask; return s; } static Stream & operator<< (Stream & s, DDSCaps & caps) { nvStaticCheck(sizeof(DDSCaps) == 16); s << caps.caps1; s << caps.caps2; s << caps.caps3; s << caps.caps4; return s; } static Stream & operator<< (Stream & s, DDSHeader10 & header) { nvStaticCheck(sizeof(DDSHeader10) == 20); s << header.dxgiFormat; s << header.resourceDimension; s << header.miscFlag; s << header.arraySize; s << header.reserved; return s; } Stream & operator<< (Stream & s, DDSHeader & header) { nvStaticCheck(sizeof(DDSHeader) == 148); s << header.fourcc; s << header.size; s << header.flags; s << header.height; s << header.width; s << header.pitch; s << header.depth; s << header.mipmapcount; s.serialize(header.reserved, 11 * sizeof(uint)); s << header.pf; s << header.caps; s << header.notused; if (header.hasDX10Header()) { s << header.header10; } return s; } } // nv namespace /* Not used! namespace { struct FormatDescriptor { uint format; uint bitcount; uint rmask; uint gmask; uint bmask; uint amask; }; static const FormatDescriptor s_d3dFormats[] = { { D3DFMT_R8G8B8, 24, 0xFF0000, 0xFF00, 0xFF, 0 }, { D3DFMT_A8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0xFF000000 }, // DXGI_FORMAT_B8G8R8A8_UNORM { D3DFMT_X8R8G8B8, 32, 0xFF0000, 0xFF00, 0xFF, 0 }, // DXGI_FORMAT_B8G8R8X8_UNORM { D3DFMT_R5G6B5, 16, 0xF800, 0x7E0, 0x1F, 0 }, // DXGI_FORMAT_B5G6R5_UNORM { D3DFMT_X1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0 }, { D3DFMT_A1R5G5B5, 16, 0x7C00, 0x3E0, 0x1F, 0x8000 }, // DXGI_FORMAT_B5G5R5A1_UNORM { D3DFMT_A4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0xF000 }, { D3DFMT_R3G3B2, 8, 0xE0, 0x1C, 0x3, 0 }, { D3DFMT_A8, 8, 0, 0, 0, 8 }, // DXGI_FORMAT_A8_UNORM { D3DFMT_A8R3G3B2, 16, 0xE0, 0x1C, 0x3, 0xFF00 }, { D3DFMT_X4R4G4B4, 16, 0xF00, 0xF0, 0xF, 0 }, { D3DFMT_A2B10G10R10, 32, 0x3FF, 0xFFC00, 0x3FF00000, 0xC0000000 }, // DXGI_FORMAT_R10G10B10A2 { D3DFMT_A8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 }, // DXGI_FORMAT_R8G8B8A8_UNORM { D3DFMT_X8B8G8R8, 32, 0xFF, 0xFF00, 0xFF0000, 0 }, { D3DFMT_G16R16, 32, 0xFFFF, 0xFFFF0000, 0, 0 }, // DXGI_FORMAT_R16G16_UNORM { D3DFMT_A2R10G10B10, 32, 0x3FF00000, 0xFFC00, 0x3FF, 0xC0000000 }, { D3DFMT_L8, 8, 8, 0, 0, 0 }, // DXGI_FORMAT_R8_UNORM { D3DFMT_L16, 16, 16, 0, 0, 0 }, // DXGI_FORMAT_R16_UNORM }; static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]); static uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { for (int i = 0; i < s_d3dFormatCount; i++) { if (s_d3dFormats[i].bitcount == bitcount && s_d3dFormats[i].rmask == rmask && s_d3dFormats[i].gmask == gmask && s_d3dFormats[i].bmask == bmask && s_d3dFormats[i].amask == amask) { return s_d3dFormats[i].format; } } return 0; } } // nv namespace */ DDSHeader::DDSHeader() { this->fourcc = FOURCC_DDS; this->size = 124; this->flags = (DDSD_CAPS|DDSD_PIXELFORMAT); this->height = 0; this->width = 0; this->pitch = 0; this->depth = 0; this->mipmapcount = 0; memset(this->reserved, 0, sizeof(this->reserved)); // Store version information on the reserved header attributes. this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T'); this->reserved[10] = (2 << 16) | (0 << 8) | (8); // major.minor.revision this->pf.size = 32; this->pf.flags = 0; this->pf.fourcc = 0; this->pf.bitcount = 0; this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; this->pf.amask = 0; this->caps.caps1 = DDSCAPS_TEXTURE; this->caps.caps2 = 0; this->caps.caps3 = 0; this->caps.caps4 = 0; this->notused = 0; this->header10.dxgiFormat = DXGI_FORMAT_UNKNOWN; this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_UNKNOWN; this->header10.miscFlag = 0; this->header10.arraySize = 0; this->header10.reserved = 0; } void DDSHeader::setWidth(uint w) { this->flags |= DDSD_WIDTH; this->width = w; } void DDSHeader::setHeight(uint h) { this->flags |= DDSD_HEIGHT; this->height = h; } void DDSHeader::setDepth(uint d) { this->flags |= DDSD_DEPTH; this->height = d; } void DDSHeader::setMipmapCount(uint count) { if (count == 0 || count == 1) { this->flags &= ~DDSD_MIPMAPCOUNT; this->mipmapcount = 0; if (this->caps.caps2 == 0) { this->caps.caps1 = DDSCAPS_TEXTURE; } else { this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX; } } else { this->flags |= DDSD_MIPMAPCOUNT; this->mipmapcount = count; this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; } } void DDSHeader::setTexture2D() { this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; } void DDSHeader::setTexture3D() { this->caps.caps2 = DDSCAPS2_VOLUME; this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D; } void DDSHeader::setTextureCube() { this->caps.caps1 |= DDSCAPS_COMPLEX; this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES; this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D; this->header10.arraySize = 6; } void DDSHeader::setLinearSize(uint size) { this->flags &= ~DDSD_PITCH; this->flags |= DDSD_LINEARSIZE; this->pitch = size; } void DDSHeader::setPitch(uint pitch) { this->flags &= ~DDSD_LINEARSIZE; this->flags |= DDSD_PITCH; this->pitch = pitch; } void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3) { // set fourcc pixel format. this->pf.flags = DDPF_FOURCC; this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3); if (this->pf.fourcc == FOURCC_ATI2) { this->pf.bitcount = FOURCC_A2XY; } else { this->pf.bitcount = 0; } this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; this->pf.amask = 0; } void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { // Make sure the masks are correct. nvCheck((rmask & gmask) == 0); nvCheck((rmask & bmask) == 0); nvCheck((rmask & amask) == 0); nvCheck((gmask & bmask) == 0); nvCheck((gmask & amask) == 0); nvCheck((bmask & amask) == 0); this->pf.flags = DDPF_RGB; if (amask != 0) { this->pf.flags |= DDPF_ALPHAPIXELS; } if (bitcount == 0) { // Compute bit count from the masks. uint total = rmask | gmask | bmask | amask; while(total != 0) { bitcount++; total >>= 1; } } nvCheck(bitcount > 0 && bitcount <= 32); // Align to 8. if (bitcount <= 8) bitcount = 8; else if (bitcount <= 16) bitcount = 16; else if (bitcount <= 24) bitcount = 24; else bitcount = 32; this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask); this->pf.bitcount = bitcount; this->pf.rmask = rmask; this->pf.gmask = gmask; this->pf.bmask = bmask; this->pf.amask = amask; } void DDSHeader::setDX10Format(uint format) { //this->pf.flags = 0; this->pf.fourcc = FOURCC_DX10; this->header10.dxgiFormat = format; } void DDSHeader::setNormalFlag(bool b) { if (b) this->pf.flags |= DDPF_NORMAL; else this->pf.flags &= ~DDPF_NORMAL; } void DDSHeader::swapBytes() { this->fourcc = POSH_LittleU32(this->fourcc); this->size = POSH_LittleU32(this->size); this->flags = POSH_LittleU32(this->flags); this->height = POSH_LittleU32(this->height); this->width = POSH_LittleU32(this->width); this->pitch = POSH_LittleU32(this->pitch); this->depth = POSH_LittleU32(this->depth); this->mipmapcount = POSH_LittleU32(this->mipmapcount); for(int i = 0; i < 11; i++) { this->reserved[i] = POSH_LittleU32(this->reserved[i]); } this->pf.size = POSH_LittleU32(this->pf.size); this->pf.flags = POSH_LittleU32(this->pf.flags); this->pf.fourcc = POSH_LittleU32(this->pf.fourcc); this->pf.bitcount = POSH_LittleU32(this->pf.bitcount); this->pf.rmask = POSH_LittleU32(this->pf.rmask); this->pf.gmask = POSH_LittleU32(this->pf.gmask); this->pf.bmask = POSH_LittleU32(this->pf.bmask); this->pf.amask = POSH_LittleU32(this->pf.amask); this->caps.caps1 = POSH_LittleU32(this->caps.caps1); this->caps.caps2 = POSH_LittleU32(this->caps.caps2); this->caps.caps3 = POSH_LittleU32(this->caps.caps3); this->caps.caps4 = POSH_LittleU32(this->caps.caps4); this->notused = POSH_LittleU32(this->notused); this->header10.dxgiFormat = POSH_LittleU32(this->header10.dxgiFormat); this->header10.resourceDimension = POSH_LittleU32(this->header10.resourceDimension); this->header10.miscFlag = POSH_LittleU32(this->header10.miscFlag); this->header10.arraySize = POSH_LittleU32(this->header10.arraySize); this->header10.reserved = POSH_LittleU32(this->header10.reserved); } bool DDSHeader::hasDX10Header() const { return this->pf.fourcc == FOURCC_DX10; // @@ This is according to AMD //return this->pf.flags == 0; // @@ This is according to MS } DirectDrawSurface::DirectDrawSurface(const char * name) : stream(new StdInputStream(name)) { if (!stream->isError()) { (*stream) << header; } } DirectDrawSurface::~DirectDrawSurface() { delete stream; } bool DirectDrawSurface::isValid() const { if (stream->isError()) { return false; } if (header.fourcc != FOURCC_DDS || header.size != 124) { return false; } const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/); if( (header.flags & required) != required ) { return false; } if (header.pf.size != 32) { return false; } if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) { return false; } return true; } bool DirectDrawSurface::isSupported() const { nvDebugCheck(isValid()); if (header.hasDX10Header()) { } else { if (header.pf.flags & DDPF_FOURCC) { if (header.pf.fourcc != FOURCC_DXT1 && header.pf.fourcc != FOURCC_DXT2 && header.pf.fourcc != FOURCC_DXT3 && header.pf.fourcc != FOURCC_DXT4 && header.pf.fourcc != FOURCC_DXT5 && header.pf.fourcc != FOURCC_RXGB && header.pf.fourcc != FOURCC_ATI1 && header.pf.fourcc != FOURCC_ATI2) { // Unknown fourcc code. return false; } } else if (header.pf.flags & DDPF_RGB) { // All RGB formats are supported now. } else { return false; } if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) { // Cubemaps must contain all faces. return false; } if (isTexture3D()) { // @@ 3D textures not supported yet. return false; } } return true; } uint DirectDrawSurface::mipmapCount() const { nvDebugCheck(isValid()); if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount; else return 1; } uint DirectDrawSurface::width() const { nvDebugCheck(isValid()); if (header.flags & DDSD_WIDTH) return header.width; else return 1; } uint DirectDrawSurface::height() const { nvDebugCheck(isValid()); if (header.flags & DDSD_HEIGHT) return header.height; else return 1; } uint DirectDrawSurface::depth() const { nvDebugCheck(isValid()); if (header.flags & DDSD_DEPTH) return header.depth; else return 1; } bool DirectDrawSurface::isTexture1D() const { nvDebugCheck(isValid()); if (header.hasDX10Header()) { return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; } return false; } bool DirectDrawSurface::isTexture2D() const { nvDebugCheck(isValid()); if (header.hasDX10Header()) { return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D; } else { return !isTexture3D() && !isTextureCube(); } } bool DirectDrawSurface::isTexture3D() const { nvDebugCheck(isValid()); if (header.hasDX10Header()) { return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D; } else { return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; } } bool DirectDrawSurface::isTextureCube() const { nvDebugCheck(isValid()); return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } void DirectDrawSurface::setNormalFlag(bool b) { nvDebugCheck(isValid()); header.setNormalFlag(b); } void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) { nvDebugCheck(isValid()); stream->seek(offset(face, mipmap)); uint w = width(); uint h = height(); // Compute width and height. for (uint m = 0; m < mipmap; m++) { w = max(1U, w / 2); h = max(1U, h / 2); } img->allocate(w, h); if (header.pf.flags & DDPF_RGB) { readLinearImage(img); } else if (header.pf.flags & DDPF_FOURCC) { readBlockImage(img); } } void DirectDrawSurface::readLinearImage(Image * img) { nvDebugCheck(stream != NULL); nvDebugCheck(img != NULL); const uint w = img->width(); const uint h = img->height(); uint rshift, rsize; PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize); uint gshift, gsize; PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize); uint bshift, bsize; PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize); uint ashift, asize; PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize); uint byteCount = (header.pf.bitcount + 7) / 8; // set image format: RGB or ARGB // alpha channel exists if and only if the alpha mask is non-zero if (header.pf.amask == 0) { img->setFormat(Image::Format_RGB); } else { img->setFormat(Image::Format_ARGB); } // Read linear RGB images. for (uint y = 0; y < h; y++) { for (uint x = 0; x < w; x++) { uint c = 0; stream->serialize(&c, byteCount); Color32 pixel(0, 0, 0, 0xFF); pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8); pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8); pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8); pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8); img->pixel(x, y) = pixel; } } } void DirectDrawSurface::readBlockImage(Image * img) { nvDebugCheck(stream != NULL); nvDebugCheck(img != NULL); // set image format: RGB or ARGB if (header.pf.fourcc == FOURCC_RXGB || header.pf.fourcc == FOURCC_ATI1 || header.pf.fourcc == FOURCC_ATI2 || header.pf.flags & DDPF_NORMAL) { img->setFormat(Image::Format_RGB); } else { img->setFormat(Image::Format_ARGB); } const uint w = img->width(); const uint h = img->height(); const uint bw = (w + 3) / 4; const uint bh = (h + 3) / 4; for (uint by = 0; by < bh; by++) { for (uint bx = 0; bx < bw; bx++) { ColorBlock block; // Read color block. readBlock(&block); // Write color block. for (uint y = 0; y < min(4U, h-4*by); y++) { for (uint x = 0; x < min(4U, w-4*bx); x++) { img->pixel(4*bx+x, 4*by+y) = block.color(x, y); } } } } } static Color32 buildNormal(uint8 x, uint8 y) { float nx = 2 * (x / 255.0f) - 1; float ny = 2 * (y / 255.0f) - 1; float nz = 0.0f; if (1 - nx*nx - ny*ny > 0) nz = sqrtf(1 - nx*nx - ny*ny); uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255); return Color32(x, y, z); } void DirectDrawSurface::readBlock(ColorBlock * rgba) { nvDebugCheck(stream != NULL); nvDebugCheck(rgba != NULL); if (header.pf.fourcc == FOURCC_DXT1) { BlockDXT1 block; *stream << block; block.decodeBlock(rgba); } else if (header.pf.fourcc == FOURCC_DXT2 || header.pf.fourcc == FOURCC_DXT3) { BlockDXT3 block; *stream << block; block.decodeBlock(rgba); } else if (header.pf.fourcc == FOURCC_DXT4 || header.pf.fourcc == FOURCC_DXT5 || header.pf.fourcc == FOURCC_RXGB) { BlockDXT5 block; *stream << block; block.decodeBlock(rgba); if (header.pf.fourcc == FOURCC_RXGB) { // Swap R & A. for (int i = 0; i < 16; i++) { Color32 & c = rgba->color(i); uint tmp = c.r; c.r = c.a; c.a = tmp; } } } else if (header.pf.fourcc == FOURCC_ATI1) { BlockATI1 block; *stream << block; block.decodeBlock(rgba); } else if (header.pf.fourcc == FOURCC_ATI2) { BlockATI2 block; *stream << block; block.decodeBlock(rgba); } // If normal flag set, convert to normal. if (header.pf.flags & DDPF_NORMAL) { if (header.pf.fourcc == FOURCC_ATI2) { for (int i = 0; i < 16; i++) { Color32 & c = rgba->color(i); c = buildNormal(c.r, c.g); } } else if (header.pf.fourcc == FOURCC_DXT5) { for (int i = 0; i < 16; i++) { Color32 & c = rgba->color(i); c = buildNormal(c.a, c.g); } } } } uint DirectDrawSurface::blockSize() const { switch(header.pf.fourcc) { case FOURCC_DXT1: case FOURCC_ATI1: return 8; case FOURCC_DXT2: case FOURCC_DXT3: case FOURCC_DXT4: case FOURCC_DXT5: case FOURCC_RXGB: case FOURCC_ATI2: return 16; }; // Not a block image. return 0; } uint DirectDrawSurface::mipmapSize(uint mipmap) const { uint w = width(); uint h = height(); uint d = depth(); for (uint m = 0; m < mipmap; m++) { w = max(1U, w / 2); h = max(1U, h / 2); d = max(1U, d / 2); } if (header.pf.flags & DDPF_FOURCC) { // @@ How are 3D textures aligned? w = (w + 3) / 4; h = (h + 3) / 4; return blockSize() * w * h; } else { nvDebugCheck(header.pf.flags & DDPF_RGB); // Align pixels to bytes. uint byteCount = (header.pf.bitcount + 7) / 8; // Align pitch to 4 bytes. uint pitch = 4 * ((w * byteCount + 3) / 4); return pitch * h * d; } } uint DirectDrawSurface::faceSize() const { const uint count = mipmapCount(); uint size = 0; for (uint m = 0; m < count; m++) { size += mipmapSize(m); } return size; } uint DirectDrawSurface::offset(const uint face, const uint mipmap) { uint size = 128; // sizeof(DDSHeader); if (header.hasDX10Header()) { size += 20; // sizeof(DDSHeader10); } if (face != 0) { size += face * faceSize(); } for (uint m = 0; m < mipmap; m++) { size += mipmapSize(m); } return size; } void DirectDrawSurface::printInfo() const { printf("Flags: 0x%.8X\n", header.flags); if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n"); if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n"); if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n"); if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n"); if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n"); if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n"); if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n"); if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n"); printf("Height: %d\n", header.height); printf("Width: %d\n", header.width); printf("Depth: %d\n", header.depth); if (header.flags & DDSD_PITCH) printf("Pitch: %d\n", header.pitch); else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %d\n", header.pitch); printf("Mipmap count: %d\n", header.mipmapcount); printf("Pixel Format:\n"); printf("\tFlags: 0x%.8X\n", header.pf.flags); if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n"); if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n"); if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n"); if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n"); if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n"); if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n"); if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n"); if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n"); if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF)); if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0)) { printf("\tSwizzle: '%c%c%c%c'\n", (header.pf.bitcount >> 0) & 0xFF, (header.pf.bitcount >> 8) & 0xFF, (header.pf.bitcount >> 16) & 0xFF, (header.pf.bitcount >> 24) & 0xFF); } else { printf("\tBit count: %d\n", header.pf.bitcount); } printf("\tRed mask: 0x%.8X\n", header.pf.rmask); printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); printf("\tAlpha mask: 0x%.8X\n", header.pf.amask); printf("Caps:\n"); printf("\tCaps 1: 0x%.8X\n", header.caps.caps1); if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n"); if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n"); if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n"); printf("\tCaps 2: 0x%.8X\n", header.caps.caps2); if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n"); else if (header.caps.caps2 & DDSCAPS2_CUBEMAP) { printf("\t\tDDSCAPS2_CUBEMAP\n"); if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n"); else { if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n"); if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n"); } } printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); if (header.hasDX10Header()) { printf("DX10 Header:\n"); printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension)); printf("\tMisc flag: %u\n", header.header10.miscFlag); printf("\tArray size: %u\n", header.header10.arraySize); } if (header.reserved[9] == MAKEFOURCC('N', 'V', 'T', 'T')) { int major = (header.reserved[10] >> 16) & 0xFF; int minor = (header.reserved[10] >> 8) & 0xFF; int revision= header.reserved[10] & 0xFF; printf("Version:\n"); printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision); } } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/DirectDrawSurface.h000066400000000000000000000070721173441656100246510ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_IMAGE_DIRECTDRAWSURFACE_H #define NV_IMAGE_DIRECTDRAWSURFACE_H #include namespace nv { class Image; class Stream; struct ColorBlock; struct NVIMAGE_CLASS DDSPixelFormat { uint size; uint flags; uint fourcc; uint bitcount; uint rmask; uint gmask; uint bmask; uint amask; }; struct NVIMAGE_CLASS DDSCaps { uint caps1; uint caps2; uint caps3; uint caps4; }; /// DDS file header for DX10. struct NVIMAGE_CLASS DDSHeader10 { uint dxgiFormat; uint resourceDimension; uint miscFlag; uint arraySize; uint reserved; }; /// DDS file header. struct NVIMAGE_CLASS DDSHeader { uint fourcc; uint size; uint flags; uint height; uint width; uint pitch; uint depth; uint mipmapcount; uint reserved[11]; DDSPixelFormat pf; DDSCaps caps; uint notused; DDSHeader10 header10; // Helper methods. DDSHeader(); void setWidth(uint w); void setHeight(uint h); void setDepth(uint d); void setMipmapCount(uint count); void setTexture2D(); void setTexture3D(); void setTextureCube(); void setLinearSize(uint size); void setPitch(uint pitch); void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3); void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask); void setDX10Format(uint format); void setNormalFlag(bool b); void swapBytes(); bool hasDX10Header() const; }; NVIMAGE_API Stream & operator<< (Stream & s, DDSHeader & header); /// DirectDraw Surface. (DDS) class NVIMAGE_CLASS DirectDrawSurface { public: DirectDrawSurface(const char * file); ~DirectDrawSurface(); bool isValid() const; bool isSupported() const; uint mipmapCount() const; uint width() const; uint height() const; uint depth() const; bool isTexture1D() const; bool isTexture2D() const; bool isTexture3D() const; bool isTextureCube() const; void setNormalFlag(bool b); void mipmap(Image * img, uint f, uint m); // void mipmap(FloatImage * img, uint f, uint m); void printInfo() const; private: uint blockSize() const; uint faceSize() const; uint mipmapSize(uint m) const; uint offset(uint f, uint m); void readLinearImage(Image * img); void readBlockImage(Image * img); void readBlock(ColorBlock * rgba); private: Stream * const stream; DDSHeader header; DDSHeader10 header10; }; } // nv namespace #endif // NV_IMAGE_DIRECTDRAWSURFACE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/Filter.cpp000066400000000000000000000320161173441656100230640ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es /** @file Filter.cpp * @brief Image filters. * * Jonathan Blow articles: * http://number-none.com/product/Mipmapping, Part 1/index.html * http://number-none.com/product/Mipmapping, Part 2/index.html * * References from Thacher Ulrich: * See _Graphics Gems III_ "General Filtered Image Rescaling", Dale A. Schumacher * http://tog.acm.org/GraphicsGems/gemsiii/filter.c * * References from Paul Heckbert: * A.V. Oppenheim, R.W. Schafer, Digital Signal Processing, Prentice-Hall, 1975 * * R.W. Hamming, Digital Filters, Prentice-Hall, Englewood Cliffs, NJ, 1983 * * W.K. Pratt, Digital Image Processing, John Wiley and Sons, 1978 * * H.S. Hou, H.C. Andrews, "Cubic Splines for Image Interpolation and * Digital Filtering", IEEE Trans. Acoustics, Speech, and Signal Proc., * vol. ASSP-26, no. 6, Dec. 1978, pp. 508-517 * * Paul Heckbert's zoom library. * http://www.xmission.com/~legalize/zoom.html * * Reconstruction Filters in Computer Graphics * http://www.mentallandscape.com/Papers_siggraph88.pdf * * More references: * http://www.worldserver.com/turk/computergraphics/ResamplingFilters.pdf * http://www.dspguide.com/ch16.htm */ #include "Filter.h" #include // Vector4 #include // swap using namespace nv; namespace { // Sinc function. inline static float sincf(const float x) { if (fabs(x) < NV_EPSILON) { //return 1.0; return 1.0f + x*x*(-1.0f/6.0f + x*x*1.0f/120.0f); } else { return sin(x) / x; } } // Bessel function of the first kind from Jon Blow's article. // http://mathworld.wolfram.com/BesselFunctionoftheFirstKind.html // http://en.wikipedia.org/wiki/Bessel_function inline static float bessel0(float x) { const float EPSILON_RATIO = 1e-6f; float xh, sum, pow, ds; int k; xh = 0.5f * x; sum = 1.0f; pow = 1.0f; k = 0; ds = 1.0; while (ds > sum * EPSILON_RATIO) { ++k; pow = pow * (xh / k); ds = pow * pow; sum = sum + ds; } return sum; } /*// Alternative bessel function from Paul Heckbert. static float _bessel0(float x) { const float EPSILON_RATIO = 1E-6; float sum = 1.0f; float y = x * x / 4.0f; float t = y; for(int i = 2; t > EPSILON_RATIO; i++) { sum += t; t *= y / float(i * i); } return sum; }*/ } // namespace Filter::Filter(float width) : m_width(width) { } /*virtual*/ Filter::~Filter() { } float Filter::sampleDelta(float x, float scale) const { return evaluate((x + 0.5f)* scale); } float Filter::sampleBox(float x, float scale, int samples) const { float sum = 0; float isamples = 1.0f / float(samples); for(int s = 0; s < samples; s++) { float p = (x + (float(s) + 0.5f) * isamples) * scale; float value = evaluate(p); sum += value; } return sum * isamples; } float Filter::sampleTriangle(float x, float scale, int samples) const { float sum = 0; float isamples = 1.0f / float(samples); for(int s = 0; s < samples; s++) { float offset = (2 * float(s) + 1.0f) * isamples; float p = (x + offset - 0.5f) * scale; float value = evaluate(p); float weight = offset; if (weight > 1.0f) weight = 2.0f - weight; sum += value * weight; } return 2 * sum * isamples; } BoxFilter::BoxFilter() : Filter(0.5f) {} BoxFilter::BoxFilter(float width) : Filter(width) {} float BoxFilter::evaluate(float x) const { if (fabs(x) <= m_width) return 1.0f; else return 0.0f; } TriangleFilter::TriangleFilter() : Filter(1.0f) {} TriangleFilter::TriangleFilter(float width) : Filter(width) {} float TriangleFilter::evaluate(float x) const { x = fabs(x); if( x < m_width ) return m_width - x; return 0.0f; } QuadraticFilter::QuadraticFilter() : Filter(1.5f) {} float QuadraticFilter::evaluate(float x) const { x = fabs(x); if( x < 0.5f ) return 0.75f - x * x; if( x < 1.5f ) { float t = x - 1.5f; return 0.5f * t * t; } return 0.0f; } CubicFilter::CubicFilter() : Filter(1.0f) {} float CubicFilter::evaluate(float x) const { // f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 x = fabs(x); if( x < 1.0f ) return((2.0f * x - 3.0f) * x * x + 1.0f); return 0.0f; } BSplineFilter::BSplineFilter() : Filter(2.0f) {} float BSplineFilter::evaluate(float x) const { x = fabs(x); if( x < 1.0f ) return (4.0f + x * x * (-6.0f + x * 3.0f)) / 6.0f; if( x < 2.0f ) { float t = 2.0f - x; return t * t * t / 6.0f; } return 0.0f; } MitchellFilter::MitchellFilter() : Filter(2.0f) { setParameters(1.0f/3.0f, 1.0f/3.0f); } float MitchellFilter::evaluate(float x) const { x = fabs(x); if( x < 1.0f ) return p0 + x * x * (p2 + x * p3); if( x < 2.0f ) return q0 + x * (q1 + x * (q2 + x * q3)); return 0.0f; } void MitchellFilter::setParameters(float b, float c) { p0 = (6.0f - 2.0f * b) / 6.0f; p2 = (-18.0f + 12.0f * b + 6.0f * c) / 6.0f; p3 = (12.0f - 9.0f * b - 6.0f * c) / 6.0f; q0 = (8.0f * b + 24.0f * c) / 6.0f; q1 = (-12.0f * b - 48.0f * c) / 6.0f; q2 = (6.0f * b + 30.0f * c) / 6.0f; q3 = (-b - 6.0f * c) / 6.0f; } LanczosFilter::LanczosFilter() : Filter(3.0f) {} float LanczosFilter::evaluate(float x) const { x = fabs(x); if( x < 3.0f ) return sincf(PI * x) * sincf(PI * x / 3.0f); return 0.0f; } SincFilter::SincFilter(float w) : Filter(w) {} float SincFilter::evaluate(float x) const { return sincf(PI * x); } KaiserFilter::KaiserFilter(float w) : Filter(w) { setParameters(4.0f, 1.0f); } float KaiserFilter::evaluate(float x) const { const float sinc_value = sincf(PI * x * stretch); const float t = x / m_width; if ((1 - t * t) >= 0) return sinc_value * bessel0(alpha * sqrtf(1 - t * t)) / bessel0(alpha); else return 0; } void KaiserFilter::setParameters(float alpha, float stretch) { this->alpha = alpha; this->stretch = stretch; } /// Ctor. Kernel1::Kernel1(const Filter & f, int iscale, int samples/*= 32*/) { nvDebugCheck(iscale > 1); nvDebugCheck(samples > 0); const float scale = 1.0f / iscale; m_width = f.width() * iscale; m_windowSize = (int)ceilf(2 * m_width); m_data = new float[m_windowSize]; const float offset = float(m_windowSize) / 2; float total = 0.0f; for (int i = 0; i < m_windowSize; i++) { const float sample = f.sampleBox(i - offset, scale, samples); m_data[i] = sample; total += sample; } const float inv = 1.0f / total; for (int i = 0; i < m_windowSize; i++) { m_data[i] *= inv; } } /// Dtor. Kernel1::~Kernel1() { delete m_data; } /// Print the kernel for debugging purposes. void Kernel1::debugPrint() { for (int i = 0; i < m_windowSize; i++) { nvDebug("%d: %f\n", i, m_data[i]); } } /// Ctor. Kernel2::Kernel2(uint ws) : m_windowSize(ws) { m_data = new float[m_windowSize * m_windowSize]; } /// Copy ctor. Kernel2::Kernel2(const Kernel2 & k) : m_windowSize(k.m_windowSize) { m_data = new float[m_windowSize * m_windowSize]; for (uint i = 0; i < m_windowSize * m_windowSize; i++) { m_data[i] = k.m_data[i]; } } /// Dtor. Kernel2::~Kernel2() { delete m_data; } /// Normalize the filter. void Kernel2::normalize() { float total = 0.0f; for(uint i = 0; i < m_windowSize*m_windowSize; i++) { total += fabs(m_data[i]); } float inv = 1.0f / total; for(uint i = 0; i < m_windowSize*m_windowSize; i++) { m_data[i] *= inv; } } /// Transpose the kernel. void Kernel2::transpose() { for(uint i = 0; i < m_windowSize; i++) { for(uint j = i+1; j < m_windowSize; j++) { swap(m_data[i*m_windowSize + j], m_data[j*m_windowSize + i]); } } } /// Init laplacian filter, usually used for sharpening. void Kernel2::initLaplacian() { nvDebugCheck(m_windowSize == 3); // m_data[0] = -1; m_data[1] = -1; m_data[2] = -1; // m_data[3] = -1; m_data[4] = +8; m_data[5] = -1; // m_data[6] = -1; m_data[7] = -1; m_data[8] = -1; m_data[0] = +0; m_data[1] = -1; m_data[2] = +0; m_data[3] = -1; m_data[4] = +4; m_data[5] = -1; m_data[6] = +0; m_data[7] = -1; m_data[8] = +0; // m_data[0] = +1; m_data[1] = -2; m_data[2] = +1; // m_data[3] = -2; m_data[4] = +4; m_data[5] = -2; // m_data[6] = +1; m_data[7] = -2; m_data[8] = +1; } /// Init simple edge detection filter. void Kernel2::initEdgeDetection() { nvCheck(m_windowSize == 3); m_data[0] = 0; m_data[1] = 0; m_data[2] = 0; m_data[3] =-1; m_data[4] = 0; m_data[5] = 1; m_data[6] = 0; m_data[7] = 0; m_data[8] = 0; } /// Init sobel filter. void Kernel2::initSobel() { if (m_windowSize == 3) { m_data[0] = -1; m_data[1] = 0; m_data[2] = 1; m_data[3] = -2; m_data[4] = 0; m_data[5] = 2; m_data[6] = -1; m_data[7] = 0; m_data[8] = 1; } else if (m_windowSize == 5) { float elements[] = { -1, -2, 0, 2, 1, -2, -3, 0, 3, 2, -3, -4, 0, 4, 3, -2, -3, 0, 3, 2, -1, -2, 0, 2, 1 }; for (int i = 0; i < 5*5; i++) { m_data[i] = elements[i]; } } else if (m_windowSize == 7) { float elements[] = { -1, -2, -3, 0, 3, 2, 1, -2, -3, -4, 0, 4, 3, 2, -3, -4, -5, 0, 5, 4, 3, -4, -5, -6, 0, 6, 5, 4, -3, -4, -5, 0, 5, 4, 3, -2, -3, -4, 0, 4, 3, 2, -1, -2, -3, 0, 3, 2, 1 }; for (int i = 0; i < 7*7; i++) { m_data[i] = elements[i]; } } else if (m_windowSize == 9) { float elements[] = { -1, -2, -3, -4, 0, 4, 3, 2, 1, -2, -3, -4, -5, 0, 5, 4, 3, 2, -3, -4, -5, -6, 0, 6, 5, 4, 3, -4, -5, -6, -7, 0, 7, 6, 5, 4, -5, -6, -7, -8, 0, 8, 7, 6, 5, -4, -5, -6, -7, 0, 7, 6, 5, 4, -3, -4, -5, -6, 0, 6, 5, 4, 3, -2, -3, -4, -5, 0, 5, 4, 3, 2, -1, -2, -3, -4, 0, 4, 3, 2, 1 }; for (int i = 0; i < 9*9; i++) { m_data[i] = elements[i]; } } } /// Init prewitt filter. void Kernel2::initPrewitt() { if (m_windowSize == 3) { m_data[0] = -1; m_data[1] = 0; m_data[2] = -1; m_data[3] = -1; m_data[4] = 0; m_data[5] = -1; m_data[6] = -1; m_data[7] = 0; m_data[8] = -1; } else if (m_windowSize == 5) { // @@ Is this correct? float elements[] = { -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2 }; for (int i = 0; i < 5*5; i++) { m_data[i] = elements[i]; } } } /// Init blended sobel filter. void Kernel2::initBlendedSobel(const Vector4 & scale) { nvCheck(m_windowSize == 9); { const float elements[] = { -1, -2, -3, -4, 0, 4, 3, 2, 1, -2, -3, -4, -5, 0, 5, 4, 3, 2, -3, -4, -5, -6, 0, 6, 5, 4, 3, -4, -5, -6, -7, 0, 7, 6, 5, 4, -5, -6, -7, -8, 0, 8, 7, 6, 5, -4, -5, -6, -7, 0, 7, 6, 5, 4, -3, -4, -5, -6, 0, 6, 5, 4, 3, -2, -3, -4, -5, 0, 5, 4, 3, 2, -1, -2, -3, -4, 0, 4, 3, 2, 1 }; for (int i = 0; i < 9*9; i++) { m_data[i] = elements[i] * scale.w(); } } { const float elements[] = { -1, -2, -3, 0, 3, 2, 1, -2, -3, -4, 0, 4, 3, 2, -3, -4, -5, 0, 5, 4, 3, -4, -5, -6, 0, 6, 5, 4, -3, -4, -5, 0, 5, 4, 3, -2, -3, -4, 0, 4, 3, 2, -1, -2, -3, 0, 3, 2, 1, }; for (int i = 0; i < 7; i++) { for (int e = 0; e < 7; e++) { m_data[(i + 1) * 9 + e + 1] += elements[i * 7 + e] * scale.z(); } } } { const float elements[] = { -1, -2, 0, 2, 1, -2, -3, 0, 3, 2, -3, -4, 0, 4, 3, -2, -3, 0, 3, 2, -1, -2, 0, 2, 1 }; for (int i = 0; i < 5; i++) { for (int e = 0; e < 5; e++) { m_data[(i + 2) * 9 + e + 2] += elements[i * 5 + e] * scale.y(); } } } { const float elements[] = { -1, 0, 1, -2, 0, 2, -1, 0, 1, }; for (int i = 0; i < 3; i++) { for (int e = 0; e < 3; e++) { m_data[(i + 3) * 9 + e + 3] += elements[i * 3 + e] * scale.x(); } } } } PolyphaseKernel::PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength, int samples/*= 32*/) { nvDebugCheck(samples > 0); float scale = float(dstLength) / float(srcLength); const float iscale = 1.0f / scale; if (scale > 1) { // Upsampling. samples = 1; scale = 1; } m_length = dstLength; m_width = f.width() * iscale; m_windowSize = (int)ceilf(m_width * 2) + 1; m_data = new float[m_windowSize * m_length]; memset(m_data, 0, sizeof(float) * m_windowSize * m_length); for (uint i = 0; i < m_length; i++) { const float center = (0.5f + i) * iscale; const int left = (int)floorf(center - m_width); const int right = (int)ceilf(center + m_width); nvDebugCheck(right - left <= m_windowSize); float total = 0.0f; for (int j = 0; j < m_windowSize; j++) { const float sample = f.sampleBox(left + j - center, scale, samples); m_data[i * m_windowSize + j] = sample; total += sample; } // normalize weights. for (int j = 0; j < m_windowSize; j++) { m_data[i * m_windowSize + j] /= total; } } } PolyphaseKernel::~PolyphaseKernel() { delete [] m_data; } /// Print the kernel for debugging purposes. void PolyphaseKernel::debugPrint() const { for (uint i = 0; i < m_length; i++) { nvDebug("%d: ", i); for (int j = 0; j < m_windowSize; j++) { nvDebug(" %6.4f", m_data[i * m_windowSize + j]); } nvDebug("\n"); } } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/Filter.h000066400000000000000000000077741173441656100225460ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_FILTER_H #define NV_IMAGE_FILTER_H #include #include namespace nv { class Vector4; /// Base filter class. class NVIMAGE_CLASS Filter { public: Filter(float width); virtual ~Filter(); float width() const { return m_width; } float sampleDelta(float x, float scale) const; float sampleBox(float x, float scale, int samples) const; float sampleTriangle(float x, float scale, int samples) const; virtual float evaluate(float x) const = 0; protected: const float m_width; }; // Box filter. class NVIMAGE_CLASS BoxFilter : public Filter { public: BoxFilter(); BoxFilter(float width); virtual float evaluate(float x) const; }; // Triangle (bilinear/tent) filter. class NVIMAGE_CLASS TriangleFilter : public Filter { public: TriangleFilter(); TriangleFilter(float width); virtual float evaluate(float x) const; }; // Quadratic (bell) filter. class NVIMAGE_CLASS QuadraticFilter : public Filter { public: QuadraticFilter(); virtual float evaluate(float x) const; }; // Cubic filter from Thatcher Ulrich. class NVIMAGE_CLASS CubicFilter : public Filter { public: CubicFilter(); virtual float evaluate(float x) const; }; // Cubic b-spline filter from Paul Heckbert. class NVIMAGE_CLASS BSplineFilter : public Filter { public: BSplineFilter(); virtual float evaluate(float x) const; }; /// Mitchell & Netravali's two-param cubic /// @see "Reconstruction Filters in Computer Graphics", SIGGRAPH 88 class NVIMAGE_CLASS MitchellFilter : public Filter { public: MitchellFilter(); virtual float evaluate(float x) const; void setParameters(float b, float c); private: float p0, p2, p3; float q0, q1, q2, q3; }; // Lanczos3 filter. class NVIMAGE_CLASS LanczosFilter : public Filter { public: LanczosFilter(); virtual float evaluate(float x) const; }; // Sinc filter. class NVIMAGE_CLASS SincFilter : public Filter { public: SincFilter(float w); virtual float evaluate(float x) const; }; // Kaiser filter. class NVIMAGE_CLASS KaiserFilter : public Filter { public: KaiserFilter(float w); virtual float evaluate(float x) const; void setParameters(float a, float stretch); private: float alpha; float stretch; }; /// A 1D kernel. Used to precompute filter weights. class NVIMAGE_CLASS Kernel1 { NV_FORBID_COPY(Kernel1); public: Kernel1(const Filter & f, int iscale, int samples = 32); ~Kernel1(); float valueAt(uint x) const { nvDebugCheck(x < (uint)m_windowSize); return m_data[x]; } int windowSize() const { return m_windowSize; } float width() const { return m_width; } void debugPrint(); private: int m_windowSize; float m_width; float * m_data; }; /// A 2D kernel. class NVIMAGE_CLASS Kernel2 { public: Kernel2(uint width); Kernel2(const Kernel2 & k); ~Kernel2(); void normalize(); void transpose(); float valueAt(uint x, uint y) const { return m_data[y * m_windowSize + x]; } uint windowSize() const { return m_windowSize; } void initLaplacian(); void initEdgeDetection(); void initSobel(); void initPrewitt(); void initBlendedSobel(const Vector4 & scale); private: const uint m_windowSize; float * m_data; }; /// A 1D polyphase kernel class NVIMAGE_CLASS PolyphaseKernel { NV_FORBID_COPY(PolyphaseKernel); public: PolyphaseKernel(const Filter & f, uint srcLength, uint dstLength, int samples = 32); ~PolyphaseKernel(); int windowSize() const { return m_windowSize; } uint length() const { return m_length; } float width() const { return m_width; } float valueAt(uint column, uint x) const { nvDebugCheck(column < m_length); nvDebugCheck(x < (uint)m_windowSize); return m_data[column * m_windowSize + x]; } void debugPrint() const; private: int m_windowSize; uint m_length; float m_width; float * m_data; }; } // nv namespace #endif // NV_IMAGE_FILTER_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/FloatImage.cpp000066400000000000000000000535151173441656100236560ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include "FloatImage.h" #include "Filter.h" #include "Image.h" #include #include #include #include #include using namespace nv; namespace { static int iround(float f) { return int(f); } static int ifloor(float f) { return int(floor(f)); } static float frac(float f) { return f - floor(f); } static int mirror(int x, int w) { x = abs(x); while (x >= w) { x = 2 * w - x - 2; } return x; } } /// Ctor. FloatImage::FloatImage() : m_width(0), m_height(0), m_componentNum(0), m_count(0), m_mem(NULL) { } /// Ctor. Init from image. FloatImage::FloatImage(const Image * img) : m_width(0), m_height(0), m_componentNum(0), m_count(0), m_mem(NULL) { initFrom(img); } /// Dtor. FloatImage::~FloatImage() { free(); } /// Init the floating point image from a regular image. void FloatImage::initFrom(const Image * img) { nvCheck(img != NULL); allocate(4, img->width(), img->height()); float * red_channel = channel(0); float * green_channel = channel(1); float * blue_channel = channel(2); float * alpha_channel = channel(3); const uint count = m_width * m_height; for(uint i = 0; i < count; i++) { Color32 pixel = img->pixel(i); red_channel[i] = float(pixel.r) / 255.0f; green_channel[i] = float(pixel.g) / 255.0f; blue_channel[i] = float(pixel.b) / 255.0f; alpha_channel[i] = float(pixel.a) / 255.0f; } } /// Convert the floating point image to a regular image. Image * FloatImage::createImage(uint base_component/*= 0*/, uint num/*= 4*/) const { nvCheck(num <= 4); nvCheck(base_component + num <= m_componentNum); AutoPtr img(new Image()); img->allocate(m_width, m_height); const uint size = m_width * m_height; for(uint i = 0; i < size; i++) { uint c; uint8 rgba[4]= {0, 0, 0, 0xff}; for(c = 0; c < num; c++) { float f = m_mem[size * (base_component + c) + i]; rgba[c] = nv::clamp(int(255.0f * f), 0, 255); } img->pixel(i) = Color32(rgba[0], rgba[1], rgba[2], rgba[3]); } return img.release(); } /// Convert the floating point image to a regular image. Correct gamma of rgb, but not alpha. Image * FloatImage::createImageGammaCorrect(float gamma/*= 2.2f*/) const { nvCheck(m_componentNum == 4); AutoPtr img(new Image()); img->allocate(m_width, m_height); const float * rChannel = this->channel(0); const float * gChannel = this->channel(1); const float * bChannel = this->channel(2); const float * aChannel = this->channel(3); const uint size = m_width * m_height; for(uint i = 0; i < size; i++) { const uint8 r = nv::clamp(int(255.0f * pow(rChannel[i], 1.0f/gamma)), 0, 255); const uint8 g = nv::clamp(int(255.0f * pow(gChannel[i], 1.0f/gamma)), 0, 255); const uint8 b = nv::clamp(int(255.0f * pow(bChannel[i], 1.0f/gamma)), 0, 255); const uint8 a = nv::clamp(int(255.0f * aChannel[i]), 0, 255); img->pixel(i) = Color32(r, g, b, a); } return img.release(); } /// Allocate a 2d float image of the given format and the given extents. void FloatImage::allocate(uint c, uint w, uint h) { free(); m_width = w; m_height = h; m_componentNum = c; m_count = w * h * c; m_mem = reinterpret_cast(nv::mem::malloc(m_count * sizeof(float))); } /// Free the image, but don't clear the members. void FloatImage::free() { nv::mem::free( reinterpret_cast(m_mem) ); m_mem = NULL; } void FloatImage::clear(float f/*=0.0f*/) { for(uint i = 0; i < m_count; i++) { m_mem[i] = f; } } void FloatImage::normalize(uint base_component) { nvCheck(base_component + 3 <= m_componentNum); float * xChannel = this->channel(base_component + 0); float * yChannel = this->channel(base_component + 1); float * zChannel = this->channel(base_component + 2); const uint size = m_width * m_height; for(uint i = 0; i < size; i++) { Vector3 normal(xChannel[i], yChannel[i], zChannel[i]); normal = normalizeSafe(normal, Vector3(zero), 0.0f); xChannel[i] = normal.x(); yChannel[i] = normal.y(); zChannel[i] = normal.z(); } } void FloatImage::packNormals(uint base_component) { scaleBias(base_component, 3, 0.5f, 1.0f); } void FloatImage::expandNormals(uint base_component) { scaleBias(base_component, 3, 2, -0.5); } void FloatImage::scaleBias(uint base_component, uint num, float scale, float bias) { const uint size = m_width * m_height; for(uint c = 0; c < num; c++) { float * ptr = this->channel(base_component + c); for(uint i = 0; i < size; i++) { ptr[i] = scale * (ptr[i] + bias); } } } /// Clamp the elements of the image. void FloatImage::clamp(float low, float high) { for(uint i = 0; i < m_count; i++) { m_mem[i] = nv::clamp(m_mem[i], low, high); } } /// From gamma to linear space. void FloatImage::toLinear(uint base_component, uint num, float gamma /*= 2.2f*/) { exponentiate(base_component, num, gamma); } /// From linear to gamma space. void FloatImage::toGamma(uint base_component, uint num, float gamma /*= 2.2f*/) { exponentiate(base_component, num, 1.0f/gamma); } /// Exponentiate the elements of the image. void FloatImage::exponentiate(uint base_component, uint num, float power) { const uint size = m_width * m_height; for(uint c = 0; c < num; c++) { float * ptr = this->channel(base_component + c); for(uint i = 0; i < size; i++) { ptr[i] = pow(ptr[i], power); } } } float FloatImage::sampleNearest(const float x, const float y, const int c, const WrapMode wm) const { if( wm == WrapMode_Clamp ) return sampleNearestClamp(x, y, c); else if( wm == WrapMode_Repeat ) return sampleNearestRepeat(x, y, c); else /*if( wm == WrapMode_Mirror )*/ return sampleNearestMirror(x, y, c); } float FloatImage::sampleLinear(const float x, const float y, const int c, const WrapMode wm) const { if( wm == WrapMode_Clamp ) return sampleLinearClamp(x, y, c); else if( wm == WrapMode_Repeat ) return sampleLinearRepeat(x, y, c); else /*if( wm == WrapMode_Mirror )*/ return sampleLinearMirror(x, y, c); } float FloatImage::sampleNearestClamp(const float x, const float y, const int c) const { int ix = ::clamp(iround(x * m_width), 0, m_width-1); int iy = ::clamp(iround(y * m_height), 0, m_height-1); return pixel(ix, iy, c); } float FloatImage::sampleNearestRepeat(const float x, const float y, const int c) const { int ix = iround(frac(x) * m_width); int iy = iround(frac(y) * m_height); return pixel(ix, iy, c); } float FloatImage::sampleNearestMirror(const float x, const float y, const int c) const { int ix = mirror(iround(x * m_width), m_width); int iy = mirror(iround(y * m_height), m_height); return pixel(ix, iy, c); } float FloatImage::sampleLinearClamp(float x, float y, const int c) const { const int w = m_width; const int h = m_height; x *= w; y *= h; const float fracX = frac(x); const float fracY = frac(y); const int ix0 = ::clamp(ifloor(x), 0, w-1); const int iy0 = ::clamp(ifloor(y), 0, h-1); const int ix1 = ::clamp(ifloor(x)+1, 0, w-1); const int iy1 = ::clamp(ifloor(y)+1, 0, h-1); float f1 = pixel(ix0, iy0, c); float f2 = pixel(ix1, iy0, c); float f3 = pixel(ix0, iy1, c); float f4 = pixel(ix1, iy1, c); float i1 = lerp(f1, f2, fracX); float i2 = lerp(f3, f4, fracX); return lerp(i1, i2, fracY); } float FloatImage::sampleLinearRepeat(float x, float y, int c) const { const int w = m_width; const int h = m_height; const float fracX = frac(x * w); const float fracY = frac(y * h); int ix0 = ifloor(frac(x) * w); int iy0 = ifloor(frac(y) * h); int ix1 = ifloor(frac(x + 1.0f/w) * w); int iy1 = ifloor(frac(y + 1.0f/h) * h); float f1 = pixel(ix0, iy0, c); float f2 = pixel(ix1, iy0, c); float f3 = pixel(ix0, iy1, c); float f4 = pixel(ix1, iy1, c); float i1 = lerp(f1, f2, fracX); float i2 = lerp(f3, f4, fracX); return lerp(i1, i2, fracY); } float FloatImage::sampleLinearMirror(float x, float y, int c) const { const int w = m_width; const int h = m_height; x *= w; y *= h; const float fracX = frac(x); const float fracY = frac(y); int ix0 = mirror(iround(x), w); int iy0 = mirror(iround(y), h); int ix1 = mirror(iround(x) + 1, w); int iy1 = mirror(iround(y) + 1, h); float f1 = pixel(ix0, iy0, c); float f2 = pixel(ix1, iy0, c); float f3 = pixel(ix0, iy1, c); float f4 = pixel(ix1, iy1, c); float i1 = lerp(f1, f2, fracX); float i2 = lerp(f3, f4, fracX); return lerp(i1, i2, fracY); } /// Fast downsampling using box filter. /// /// The extents of the image are divided by two and rounded down. /// /// When the size of the image is odd, this uses a polyphase box filter as explained in: /// http://developer.nvidia.com/object/np2_mipmapping.html /// FloatImage * FloatImage::fastDownSample() const { nvDebugCheck(m_width != 1 || m_height != 1); AutoPtr dst_image( new FloatImage() ); const uint w = max(1, m_width / 2); const uint h = max(1, m_height / 2); dst_image->allocate(m_componentNum, w, h); // 1D box filter. if (m_width == 1 || m_height == 1) { const uint n = w * h; if ((m_width * m_height) & 1) { const float scale = 1.0f / (2 * n + 1); for(uint c = 0; c < m_componentNum; c++) { const float * src = this->channel(c); float * dst = dst_image->channel(c); for(uint x = 0; x < n; x++) { const float w0 = float(n - x); const float w1 = float(n - 0); const float w2 = float(1 + x); *dst++ = scale * (w0 * src[0] + w1 * src[1] + w2 * src[2]); src += 2; } } } else { for(uint c = 0; c < m_componentNum; c++) { const float * src = this->channel(c); float * dst = dst_image->channel(c); for(uint x = 0; x < n; x++) { *dst = 0.5f * (src[0] + src[1]); dst++; src += 2; } } } } // Regular box filter. else if ((m_width & 1) == 0 && (m_height & 1) == 0) { for(uint c = 0; c < m_componentNum; c++) { const float * src = this->channel(c); float * dst = dst_image->channel(c); for(uint y = 0; y < h; y++) { for(uint x = 0; x < w; x++) { *dst = 0.25f * (src[0] + src[1] + src[m_width] + src[m_width + 1]); dst++; src += 2; } src += m_width; } } } // Polyphase filters. else if (m_width & 1 && m_height & 1) { nvDebugCheck(m_width == 2 * w + 1); nvDebugCheck(m_height == 2 * h + 1); const float scale = 1.0f / (m_width * m_height); for(uint c = 0; c < m_componentNum; c++) { const float * src = this->channel(c); float * dst = dst_image->channel(c); for(uint y = 0; y < h; y++) { const float v0 = float(h - y); const float v1 = float(h - 0); const float v2 = float(1 + y); for (uint x = 0; x < w; x++) { const float w0 = float(w - x); const float w1 = float(w - 0); const float w2 = float(1 + x); float f = 0.0f; f += v0 * (w0 * src[0 * m_width + 2 * x] + w1 * src[0 * m_width + 2 * x + 1] + w2 * src[0 * m_width + 2 * x + 2]); f += v1 * (w0 * src[1 * m_width + 2 * x] + w1 * src[1 * m_width + 2 * x + 1] + w2 * src[0 * m_width + 2 * x + 2]); f += v2 * (w0 * src[2 * m_width + 2 * x] + w1 * src[2 * m_width + 2 * x + 1] + w2 * src[0 * m_width + 2 * x + 2]); *dst = f * scale; dst++; } src += 2 * m_width; } } } else if (m_width & 1) { nvDebugCheck(m_width == 2 * w + 1); const float scale = 1.0f / (2 * m_width); for(uint c = 0; c < m_componentNum; c++) { const float * src = this->channel(c); float * dst = dst_image->channel(c); for(uint y = 0; y < h; y++) { for (uint x = 0; x < w; x++) { const float w0 = float(w - x); const float w1 = float(w - 0); const float w2 = float(1 + x); float f = 0.0f; f += w0 * (src[2 * x + 0] + src[m_width + 2 * x + 0]); f += w1 * (src[2 * x + 1] + src[m_width + 2 * x + 1]); f += w2 * (src[2 * x + 2] + src[m_width + 2 * x + 2]); *dst = f * scale; dst++; } src += 2 * m_width; } } } else if (m_height & 1) { nvDebugCheck(m_height == 2 * h + 1); const float scale = 1.0f / (2 * m_height); for(uint c = 0; c < m_componentNum; c++) { const float * src = this->channel(c); float * dst = dst_image->channel(c); for(uint y = 0; y < h; y++) { const float v0 = float(h - y); const float v1 = float(h - 0); const float v2 = float(1 + y); for (uint x = 0; x < w; x++) { float f = 0.0f; f += v0 * (src[0 * m_width + 2 * x] + src[0 * m_width + 2 * x + 1]); f += v1 * (src[1 * m_width + 2 * x] + src[1 * m_width + 2 * x + 1]); f += v2 * (src[2 * m_width + 2 * x] + src[2 * m_width + 2 * x + 1]); *dst = f * scale; dst++; } src += 2 * m_width; } } } return dst_image.release(); } /// Downsample applying a 1D kernel separately in each dimension. FloatImage * FloatImage::downSample(const Filter & filter, WrapMode wm) const { const uint w = max(1, m_width / 2); const uint h = max(1, m_height / 2); return resize(filter, w, h, wm); } /// Downsample applying a 1D kernel separately in each dimension. FloatImage * FloatImage::downSample(const Filter & filter, WrapMode wm, uint alpha) const { const uint w = max(1, m_width / 2); const uint h = max(1, m_height / 2); return resize(filter, w, h, wm, alpha); } /// Downsample applying a 1D kernel separately in each dimension. FloatImage * FloatImage::resize(const Filter & filter, uint w, uint h, WrapMode wm) const { // @@ Use monophase filters when frac(m_width / w) == 0 AutoPtr tmp_image( new FloatImage() ); AutoPtr dst_image( new FloatImage() ); PolyphaseKernel xkernel(filter, m_width, w, 32); PolyphaseKernel ykernel(filter, m_height, h, 32); // @@ Select fastest filtering order: //if (w * m_height <= h * m_width) { tmp_image->allocate(m_componentNum, w, m_height); dst_image->allocate(m_componentNum, w, h); Array tmp_column(h); tmp_column.resize(h); for (uint c = 0; c < m_componentNum; c++) { float * tmp_channel = tmp_image->channel(c); for (uint y = 0; y < m_height; y++) { this->applyKernelHorizontal(xkernel, y, c, wm, tmp_channel + y * w); } float * dst_channel = dst_image->channel(c); for (uint x = 0; x < w; x++) { tmp_image->applyKernelVertical(ykernel, x, c, wm, tmp_column.unsecureBuffer()); for (uint y = 0; y < h; y++) { dst_channel[y * w + x] = tmp_column[y]; } } } } /*else { tmp_image->allocate(m_componentNum, m_width, h); dst_image->allocate(m_componentNum, w, h); Array tmp_column(h); tmp_column.resize(h); for (uint c = 0; c < m_componentNum; c++) { float * tmp_channel = tmp_image->channel(c); for (uint x = 0; x < w; x++) { tmp_image->applyKernelVertical(ykernel, x, c, wm, tmp_column.unsecureBuffer()); for (uint y = 0; y < h; y++) { tmp_channel[y * w + x] = tmp_column[y]; } } float * dst_channel = dst_image->channel(c); for (uint y = 0; y < m_height; y++) { this->applyKernelHorizontal(xkernel, y, c, wm, dst_channel + y * w); } } }*/ return dst_image.release(); } /// Downsample applying a 1D kernel separately in each dimension. FloatImage * FloatImage::resize(const Filter & filter, uint w, uint h, WrapMode wm, uint alpha) const { nvCheck(alpha < m_componentNum); AutoPtr tmp_image( new FloatImage() ); AutoPtr dst_image( new FloatImage() ); PolyphaseKernel xkernel(filter, m_width, w, 32); PolyphaseKernel ykernel(filter, m_height, h, 32); { tmp_image->allocate(m_componentNum, w, m_height); dst_image->allocate(m_componentNum, w, h); Array tmp_column(h); tmp_column.resize(h); for (uint c = 0; c < m_componentNum; c++) { float * tmp_channel = tmp_image->channel(c); for (uint y = 0; y < m_height; y++) { this->applyKernelHorizontal(xkernel, y, c, alpha, wm, tmp_channel + y * w); } } // Process all channels before applying vertical kernel to make sure alpha has been computed. for (uint c = 0; c < m_componentNum; c++) { float * dst_channel = dst_image->channel(c); for (uint x = 0; x < w; x++) { tmp_image->applyKernelVertical(ykernel, x, c, alpha, wm, tmp_column.unsecureBuffer()); for (uint y = 0; y < h; y++) { dst_channel[y * w + x] = tmp_column[y]; } } } } return dst_image.release(); } /// Apply 2D kernel at the given coordinates and return result. float FloatImage::applyKernel(const Kernel2 * k, int x, int y, uint c, WrapMode wm) const { nvDebugCheck(k != NULL); const uint kernelWindow = k->windowSize(); const int kernelOffset = int(kernelWindow / 2) - 1; const float * channel = this->channel(c); float sum = 0.0f; for (uint i = 0; i < kernelWindow; i++) { const int src_y = int(y + i) - kernelOffset; for (uint e = 0; e < kernelWindow; e++) { const int src_x = int(x + e) - kernelOffset; int idx = this->index(src_x, src_y, wm); sum += k->valueAt(e, i) * channel[idx]; } } return sum; } /// Apply 1D vertical kernel at the given coordinates and return result. float FloatImage::applyKernelVertical(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const { nvDebugCheck(k != NULL); const uint kernelWindow = k->windowSize(); const int kernelOffset = int(kernelWindow / 2) - 1; const float * channel = this->channel(c); float sum = 0.0f; for (uint i = 0; i < kernelWindow; i++) { const int src_y = int(y + i) - kernelOffset; const int idx = this->index(x, src_y, wm); sum += k->valueAt(i) * channel[idx]; } return sum; } /// Apply 1D horizontal kernel at the given coordinates and return result. float FloatImage::applyKernelHorizontal(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const { nvDebugCheck(k != NULL); const uint kernelWindow = k->windowSize(); const int kernelOffset = int(kernelWindow / 2) - 1; const float * channel = this->channel(c); float sum = 0.0f; for (uint e = 0; e < kernelWindow; e++) { const int src_x = int(x + e) - kernelOffset; const int idx = this->index(src_x, y, wm); sum += k->valueAt(e) * channel[idx]; } return sum; } /// Apply 1D vertical kernel at the given coordinates and return result. void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, uint c, WrapMode wm, float * __restrict output) const { const uint length = k.length(); const float scale = float(length) / float(m_height); const float iscale = 1.0f / scale; const float width = k.width(); const int windowSize = k.windowSize(); const float * channel = this->channel(c); for (uint i = 0; i < length; i++) { const float center = (0.5f + i) * iscale; const int left = (int)floorf(center - width); const int right = (int)ceilf(center + width); nvCheck(right - left <= windowSize); float sum = 0; for (int j = 0; j < windowSize; ++j) { const int idx = this->index(x, j+left, wm); sum += k.valueAt(i, j) * channel[idx]; } output[i] = sum; } } /// Apply 1D horizontal kernel at the given coordinates and return result. void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, WrapMode wm, float * __restrict output) const { const uint length = k.length(); const float scale = float(length) / float(m_width); const float iscale = 1.0f / scale; const float width = k.width(); const int windowSize = k.windowSize(); const float * channel = this->channel(c); for (uint i = 0; i < length; i++) { const float center = (0.5f + i) * iscale; const int left = (int)floorf(center - width); const int right = (int)ceilf(center + width); nvDebugCheck(right - left <= windowSize); float sum = 0; for (int j = 0; j < windowSize; ++j) { const int idx = this->index(left + j, y, wm); sum += k.valueAt(i, j) * channel[idx]; } output[i] = sum; } } /// Apply 1D vertical kernel at the given coordinates and return result. void FloatImage::applyKernelVertical(const PolyphaseKernel & k, int x, uint c, uint a, WrapMode wm, float * __restrict output) const { const uint length = k.length(); const float scale = float(length) / float(m_height); const float iscale = 1.0f / scale; const float width = k.width(); const int windowSize = k.windowSize(); const float * channel = this->channel(c); const float * alpha = this->channel(a); for (uint i = 0; i < length; i++) { const float center = (0.5f + i) * iscale; const int left = (int)floorf(center - width); const int right = (int)ceilf(center + width); nvCheck(right - left <= windowSize); float norm = 0; float sum = 0; for (int j = 0; j < windowSize; ++j) { const int idx = this->index(x, j+left, wm); float w = k.valueAt(i, j) * (alpha[idx] + (1.0f / 256.0f)); norm += w; sum += w * channel[idx]; } output[i] = sum / norm; } } /// Apply 1D horizontal kernel at the given coordinates and return result. void FloatImage::applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, uint a, WrapMode wm, float * __restrict output) const { const uint length = k.length(); const float scale = float(length) / float(m_width); const float iscale = 1.0f / scale; const float width = k.width(); const int windowSize = k.windowSize(); const float * channel = this->channel(c); const float * alpha = this->channel(a); for (uint i = 0; i < length; i++) { const float center = (0.5f + i) * iscale; const int left = (int)floorf(center - width); const int right = (int)ceilf(center + width); nvDebugCheck(right - left <= windowSize); float norm = 0.0f; float sum = 0; for (int j = 0; j < windowSize; ++j) { const int idx = this->index(left + j, y, wm); float w = k.valueAt(i, j) * (alpha[idx] + (1.0f / 256.0f)); norm += w; sum += w * channel[idx]; } output[i] = sum / norm; } } FloatImage* FloatImage::clone() const { FloatImage* copy = new FloatImage(); copy->m_width = m_width; copy->m_height = m_height; copy->m_componentNum = m_componentNum; copy->m_count = m_count; if(m_mem) { copy->allocate(m_componentNum, m_width, m_height); memcpy(copy->m_mem, m_mem, m_count * sizeof(float)); } return copy; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/FloatImage.h000066400000000000000000000162031173441656100233140ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_FLOATIMAGE_H #define NV_IMAGE_FLOATIMAGE_H #include #include #include #include // clamp #include // abs namespace nv { class Vector4; class Matrix; class Image; class Filter; class Kernel1; class Kernel2; class PolyphaseKernel; /// Multicomponent floating point image class. class FloatImage { public: enum WrapMode { WrapMode_Clamp, WrapMode_Repeat, WrapMode_Mirror }; NVIMAGE_API FloatImage(); NVIMAGE_API FloatImage(const Image * img); NVIMAGE_API virtual ~FloatImage(); /** @name Conversion. */ //@{ NVIMAGE_API void initFrom(const Image * img); NVIMAGE_API Image * createImage(uint base_component = 0, uint num = 4) const; NVIMAGE_API Image * createImageGammaCorrect(float gamma = 2.2f) const; //@} /** @name Allocation. */ //@{ NVIMAGE_API void allocate(uint c, uint w, uint h); NVIMAGE_API void free(); // Does not clear members. //@} /** @name Manipulation. */ //@{ NVIMAGE_API void clear(float f=0.0f); NVIMAGE_API void normalize(uint base_component); NVIMAGE_API void packNormals(uint base_component); NVIMAGE_API void expandNormals(uint base_component); NVIMAGE_API void scaleBias(uint base_component, uint num, float scale, float add); //NVIMAGE_API void clamp(uint base_component, uint num); NVIMAGE_API void clamp(float low, float high); NVIMAGE_API void toLinear(uint base_component, uint num, float gamma = 2.2f); NVIMAGE_API void toGamma(uint base_component, uint num, float gamma = 2.2f); NVIMAGE_API void exponentiate(uint base_component, uint num, float power); NVIMAGE_API FloatImage * fastDownSample() const; NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm) const; NVIMAGE_API FloatImage * downSample(const Filter & filter, WrapMode wm, uint alpha) const; NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm) const; NVIMAGE_API FloatImage * resize(const Filter & filter, uint w, uint h, WrapMode wm, uint alpha) const; //@} NVIMAGE_API float applyKernel(const Kernel2 * k, int x, int y, uint c, WrapMode wm) const; NVIMAGE_API float applyKernelVertical(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const; NVIMAGE_API float applyKernelHorizontal(const Kernel1 * k, int x, int y, uint c, WrapMode wm) const; NVIMAGE_API void applyKernelVertical(const PolyphaseKernel & k, int x, uint c, WrapMode wm, float * output) const; NVIMAGE_API void applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, WrapMode wm, float * output) const; NVIMAGE_API void applyKernelVertical(const PolyphaseKernel & k, int x, uint c, uint a, WrapMode wm, float * output) const; NVIMAGE_API void applyKernelHorizontal(const PolyphaseKernel & k, int y, uint c, uint a, WrapMode wm, float * output) const; uint width() const { return m_width; } uint height() const { return m_height; } uint componentNum() const { return m_componentNum; } uint count() const { return m_count; } /** @name Pixel access. */ //@{ const float * channel(uint c) const; float * channel(uint c); const float * scanline(uint y, uint c) const; float * scanline(uint y, uint c); void setPixel(float f, uint x, uint y, uint c); void addPixel(float f, uint x, uint y, uint c); float pixel(uint x, uint y, uint c) const; void setPixel(float f, uint idx); float pixel(uint idx) const; float sampleNearest(float x, float y, int c, WrapMode wm) const; float sampleLinear(float x, float y, int c, WrapMode wm) const; float sampleNearestClamp(float x, float y, int c) const; float sampleNearestRepeat(float x, float y, int c) const; float sampleNearestMirror(float x, float y, int c) const; float sampleLinearClamp(float x, float y, int c) const; float sampleLinearRepeat(float x, float y, int c) const; float sampleLinearMirror(float x, float y, int c) const; //@} FloatImage* clone() const; public: uint index(uint x, uint y) const; uint indexClamp(int x, int y) const; uint indexRepeat(int x, int y) const; uint indexMirror(int x, int y) const; uint index(int x, int y, WrapMode wm) const; public: uint16 m_width; ///< Width of the texture. uint16 m_height; ///< Height of the texture. uint32 m_componentNum; ///< Number of components. uint32 m_count; ///< Image pixel count. float * m_mem; }; /// Get const channel pointer. inline const float * FloatImage::channel(uint c) const { nvDebugCheck(m_mem != NULL); nvDebugCheck(c < m_componentNum); return m_mem + c * m_width * m_height; } /// Get channel pointer. inline float * FloatImage::channel(uint c) { nvDebugCheck(m_mem != NULL); nvDebugCheck(c < m_componentNum); return m_mem + c * m_width * m_height; } /// Get const scanline pointer. inline const float * FloatImage::scanline(uint y, uint c) const { nvDebugCheck(y < m_height); return channel(c) + y * m_width; } /// Get scanline pointer. inline float * FloatImage::scanline(uint y, uint c) { nvDebugCheck(y < m_height); return channel(c) + y * m_width; } /// Set pixel component. inline void FloatImage::setPixel(float f, uint x, uint y, uint c) { nvDebugCheck(m_mem != NULL); nvDebugCheck(x < m_width); nvDebugCheck(y < m_height); nvDebugCheck(c < m_componentNum); m_mem[(c * m_height + y) * m_width + x] = f; } /// Add to pixel component. inline void FloatImage::addPixel(float f, uint x, uint y, uint c) { nvDebugCheck(m_mem != NULL); nvDebugCheck(x < m_width); nvDebugCheck(y < m_height); nvDebugCheck(c < m_componentNum); m_mem[(c * m_height + y) * m_width + x] += f; } /// Get pixel component. inline float FloatImage::pixel(uint x, uint y, uint c) const { nvDebugCheck(m_mem != NULL); nvDebugCheck(x < m_width); nvDebugCheck(y < m_height); nvDebugCheck(c < m_componentNum); return m_mem[(c * m_height + y) * m_width + x]; } /// Set pixel component. inline void FloatImage::setPixel(float f, uint idx) { nvDebugCheck(idx < m_count); m_mem[idx] = f; } /// Get pixel component. inline float FloatImage::pixel(uint idx) const { nvDebugCheck(idx < m_count); return m_mem[idx]; } inline uint FloatImage::index(uint x, uint y) const { nvDebugCheck(x < m_width); nvDebugCheck(y < m_height); return y * m_width + x; } inline uint FloatImage::indexClamp(int x, int y) const { return nv::clamp(y, int(0), int(m_height-1)) * m_width + nv::clamp(x, int(0), int(m_width-1)); } inline int repeat_remainder(int a, int b) { if (a >= 0) return a % b; else return (a + 1) % b + b - 1; } inline uint FloatImage::indexRepeat(int x, int y) const { return repeat_remainder(y, m_height) * m_width + repeat_remainder(x, m_width); } inline uint FloatImage::indexMirror(int x, int y) const { if (m_width == 1) x = 0; x = abs(x); while (x >= m_width) { x = abs(m_width + m_width - x - 2); } if (m_height == 1) y = 0; y = abs(y); while (y >= m_height) { y = abs(m_height + m_height - y - 2); } return index(x, y); } inline uint FloatImage::index(int x, int y, WrapMode wm) const { if (wm == WrapMode_Clamp) return indexClamp(x, y); if (wm == WrapMode_Repeat) return indexRepeat(x, y); /*if (wm == WrapMode_Mirror)*/ return indexMirror(x, y); } } // nv namespace #endif // NV_IMAGE_FLOATIMAGE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/HoleFilling.cpp000066400000000000000000000403071173441656100240350ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include #include #include #include using namespace nv; // This is a variation of Sapiro's inpainting method. void nv::fillExtrapolate(int passCount, FloatImage * img, BitMap * bmap) { nvCheck(img != NULL); nvCheck(bmap != NULL); const int w = img->width(); const int h = img->height(); const int count = img->componentNum(); nvCheck(bmap->width() == uint(w)); nvCheck(bmap->height() == uint(h)); AutoPtr newbmap(new BitMap(w, h)); for(int p = 0; p < passCount; p++) { for(int c = 0; c < count; c++) { float * channel = img->channel(c); for(int y = 0; y < h; y++) { for(int x = 0; x < w; x++) { if (bmap->bitAt(x, y)) { // Not a hole. newbmap->setBitAt(x, y); continue; } const bool west = bmap->bitAt(img->indexClamp(x-1, y)); const bool east = bmap->bitAt(img->indexClamp(x+1, y)); const bool north = bmap->bitAt(img->indexClamp(x, y-1)); const bool south = bmap->bitAt(img->indexClamp(x, y+1)); const bool northwest = bmap->bitAt(img->indexClamp(x-1, y-1)); const bool northeast = bmap->bitAt(img->indexClamp(x+1, y-1)); const bool southwest = bmap->bitAt(img->indexClamp(x-1, y+1)); const bool southeast = bmap->bitAt(img->indexClamp(x+1, y+1)); int num = west + east + north + south + northwest + northeast + southwest + southeast; if (num != 0) { float average = 0.0f; if (num == 3 && west && northwest && southwest) { average = channel[img->indexClamp(x-1, y)]; } else if (num == 3 && east && northeast && southeast) { average = channel[img->indexClamp(x+1, y)]; } else if (num == 3 && north && northwest && northeast) { average = channel[img->indexClamp(x, y-1)]; } else if (num == 3 && south && southwest && southeast) { average = channel[img->indexClamp(x, y+1)]; } else { float total = 0.0f; if (west) { average += 1 * channel[img->indexClamp(x-1, y)]; total += 1; } if (east) { average += 1 * channel[img->indexClamp(x+1, y)]; total += 1; } if (north) { average += 1 * channel[img->indexClamp(x, y-1)]; total += 1; } if (south) { average += 1 * channel[img->indexClamp(x, y+1)]; total += 1; } if (northwest) { average += channel[img->indexClamp(x-1, y-1)]; ++total; } if (northeast) { average += channel[img->indexClamp(x+1, y-1)]; ++total; } if (southwest) { average += channel[img->indexClamp(x-1, y+1)]; ++total; } if (southeast) { average += channel[img->indexClamp(x+1, y+1)]; ++total; } average /= total; } channel[img->indexClamp(x, y)] = average; newbmap->setBitAt(x, y); } } } } // Update the bit mask. swap(*newbmap, *bmap); } } namespace { struct Neighbor { uint16 x; uint16 y; uint32 d; }; // Compute euclidean squared distance. static uint dist( uint16 ax, uint16 ay, uint16 bx, uint16 by ) { int dx = bx - ax; int dy = by - ay; return uint(dx*dx + dy*dy); } // Check neighbour, this is the core of the EDT algorithm. static void checkNeighbour( int x, int y, Neighbor * e, const Neighbor & n ) { nvDebugCheck(e != NULL); uint d = dist( x, y, n.x, n.y ); if( d < e->d ) { e->x = n.x; e->y = n.y; e->d = d; } } } // namespace // Voronoi filling using EDT-4 void nv::fillVoronoi(FloatImage * img, const BitMap * bmap) { nvCheck(img != NULL); const int w = img->width(); const int h = img->height(); const int count = img->componentNum(); nvCheck(bmap->width() == uint(w)); nvCheck(bmap->height() == uint(h)); Array edm; edm.resize(w * h); int x, y; int x0, x1, y0, y1; // Init edm. for( y = 0; y < h; y++ ) { for( x = 0; x < w; x++ ) { if( bmap->bitAt(x, y) ) { edm[y * w + x].x = x; edm[y * w + x].y = y; edm[y * w + x].d = 0; } else { edm[y * w + x].x = w; edm[y * w + x].y = h; edm[y * w + x].d = w*w + h*h; } } } // First pass. for( y = 0; y < h; y++ ) { for( x = 0; x < w; x++ ) { x0 = clamp(x-1, 0, w-1); // @@ Wrap? x1 = clamp(x+1, 0, w-1); y0 = clamp(y-1, 0, h-1); Neighbor & e = edm[y * w + x]; checkNeighbour(x, y, &e, edm[y0 * w + x0]); checkNeighbour(x, y, &e, edm[y0 * w + x]); checkNeighbour(x, y, &e, edm[y0 * w + x1]); checkNeighbour(x, y, &e, edm[y * w + x0]); } for( x = w-1; x >= 0; x-- ) { x1 = clamp(x+1, 0, w-1); Neighbor & e = edm[y * w + x]; checkNeighbour(x, y, &e, edm[y * w + x1]); } } // Third pass. for( y = h-1; y >= 0; y-- ) { for( x = w-1; x >= 0; x-- ) { x0 = clamp(x-1, 0, w-1); x1 = clamp(x+1, 0, w-1); y1 = clamp(y+1, 0, h-1); Neighbor & e = edm[y * w + x]; checkNeighbour(x, y, &e, edm[y * w + x1]); checkNeighbour(x, y, &e, edm[y1 * w + x0]); checkNeighbour(x, y, &e, edm[y1 * w + x]); checkNeighbour(x, y, &e, edm[y1 * w + x1]); } for( x = 0; x < w; x++ ) { x0 = clamp(x-1, 0, w-1); Neighbor & e = edm[y * w + x]; checkNeighbour(x, y, &e, edm[y * w + x0]); } } // Fill empty holes. for( y = 0; y < h; y++ ) { for( x = 0; x < w; x++ ) { const int sx = edm[y * w + x].x; const int sy = edm[y * w + x].y; nvDebugCheck(sx < w && sy < h); if( sx != x || sy != y ) { for(int c = 0; c < count; c++ ) { img->setPixel(img->pixel(sx, sy, c), x, y, c); } } } } } void nv::fillBlur(FloatImage * img, const BitMap * bmap) { nvCheck(img != NULL); // @@ Apply a 3x3 kernel. } static bool downsample(const FloatImage * src, const BitMap * srcMask, const FloatImage ** _dst, const BitMap ** _dstMask) { const uint w = src->width(); const uint h = src->height(); const uint count = src->componentNum(); // count holes in srcMask, return false if fully filled. uint holes = 0; for(uint y = 0; y < h; y++) { for(uint x = 0; x < w; x++) { holes += srcMask->bitAt(x, y) == 0; } } if (holes == 0 || (w == 2 || h == 2)) { // Stop when no holes or when the texture is very small. return false; } // Apply box filter to image and mask and return true. const uint nw = w / 2; const uint nh = h / 2; FloatImage * dst = new FloatImage(); dst->allocate(count, nw, nh); BitMap * dstMask = new BitMap(nw, nh); for(uint c = 0; c < count; c++) { for(uint y = 0; y < nh; y++) { for(uint x = 0; x < nw; x++) { const uint x0 = 2 * x + 0; const uint x1 = 2 * x + 1; const uint y0 = 2 * y + 0; const uint y1 = 2 * y + 1; const float f0 = src->pixel(x0, y0, c); const float f1 = src->pixel(x1, y0, c); const float f2 = src->pixel(x0, y1, c); const float f3 = src->pixel(x1, y1, c); const bool b0 = srcMask->bitAt(x0, y0); const bool b1 = srcMask->bitAt(x1, y0); const bool b2 = srcMask->bitAt(x0, y1); const bool b3 = srcMask->bitAt(x1, y1); if (b0 || b1 || b2 || b3) { // Set bit mask. dstMask->setBitAt(x, y); // Set pixel. float value = 0.0f; int total = 0; if (b0) { value += f0; total++; } if (b1) { value += f1; total++; } if (b2) { value += f2; total++; } if (b3) { value += f3; total++; } dst->setPixel(value / total, x, y, c); } } } } *_dst = dst; *_dstMask = dstMask; return true; } // This is the filter used in the Lumigraph paper. void nv::fillPullPush(FloatImage * img, const BitMap * bmap) { nvCheck(img != NULL); const uint count = img->componentNum(); const uint w = img->width(); const uint h = img->height(); const uint num = log2(max(w,h)); // Build mipmap chain. Array mipmaps(num); Array mipmapMasks(num); mipmaps.append(img); mipmapMasks.append(bmap); const FloatImage * current; const BitMap * currentMask; // Compute mipmap chain. while(downsample(mipmaps.back(), mipmapMasks.back(), ¤t, ¤tMask)) { mipmaps.append(current); mipmapMasks.append(currentMask); } // Sample mipmaps until non-hole is found. for(uint y = 0; y < h; y++) { for(uint x = 0; x < w; x++) { int sx = x; int sy = y; //float sx = x; //float sy = y; const uint levelCount = mipmaps.count(); for (uint l = 0; l < levelCount; l++) { //const float fx = sx / mipmaps[l]->width(); //const float fy = sy / mipmaps[l]->height(); if (mipmapMasks[l]->bitAt(sx, sy)) { // Sample mipmaps[l](sx, sy) and copy to img(x, y) for(uint c = 0; c < count; c++) { //img->setPixel(mipmaps[l]->linear_clamp(fx, fy, c), x, y, c); img->setPixel(mipmaps[l]->pixel(sx, sy, c), x, y, c); } break; } sx /= 2; sy /= 2; } } } // Don't delete the original image and mask. mipmaps[0] = NULL; mipmapMasks[0] = NULL; // Delete the mipmaps. deleteAll(mipmaps); deleteAll(mipmapMasks); } /* This Code is from Charles Bloom: DoPixelSeamFix 10-20-02 Looks in the 5x5 local neighborhood (LocalPixels) of the desired pixel to fill. It tries to build a quadratic model of the neighborhood surface to use in extrapolating. You need 5 pixels to establish a 2d quadratic curve. This is really just a nice generic way to extrapolate pixels. It also happens to work great for seam-fixing. Note that I'm working on normals, but I treat them just as 3 scalars and normalize at the end. To be more correct, I would work on the surface of a sphere, but that just seems like way too much work. */ struct LocalPixels { // 5x5 neighborhood // the center is at result // index [y][x] bool fill[5][5]; float data[5][5]; mutable float result; mutable float weight; bool Quad3SubH(float * pQ, int row) const { const bool * pFill = fill[row]; const float * pDat = data[row]; if ( pFill[1] && pFill[2] && pFill[3] ) { // good row *pQ = pDat[1] - 2.f * pDat[2] + pDat[3]; return true; } else if ( pFill[0] && pFill[1] && pFill[2] ) { // good row *pQ = pDat[0] - 2.f * pDat[1] + pDat[2]; return true; } else if ( pFill[2] && pFill[3] && pFill[4] ) { // good row *pQ = pDat[2] - 2.f * pDat[3] + pDat[4]; return true; } return false; } // improve result with a horizontal quad in row 1 and/or bool Quad3SubV(float * pQ, int col) const { if ( fill[1][col] && fill[2][col] && fill[3][col] ) { // good row *pQ = data[1][col] - 2.f * data[2][col] + data[3][col]; return true; } else if ( fill[0][col] && fill[1][col] && fill[2][col] ) { // good row *pQ = data[0][col] - 2.f * data[1][col] + data[2][col]; return true; } else if ( fill[2][col] && fill[3][col] && fill[4][col] ) { // good row *pQ = data[2][col] - 2.f * data[3][col] + data[4][col]; return true; } return false; } bool Quad3H(float * pQ) const { if (!Quad3SubH(pQ,1)) { return Quad3SubH(pQ,3); } float q = 0.0f; // initializer not needed, just make it shut up if (Quad3SubH(&q, 3)) { // got q and pQ *pQ = (*pQ+q)*0.5f; } return true; } bool Quad3V(float * pQ) const { if (!Quad3SubV(pQ, 1)) { return Quad3SubV(pQ, 3); } float q = 0.0f; // initializer not needed, just make it shut up if (Quad3SubV(&q, 3)) { // got q and pQ *pQ = (*pQ + q) * 0.5f; } return true; } // Quad returns ([0]+[2] - 2.f*[1]) // a common want is [1] - ([0]+[2])*0.5f ; // so use -0.5f*Quad bool tryQuads() const { bool res = false; // look for a pair that straddles the middle: if ( fill[2][1] && fill[2][3] ) { // got horizontal straddle float q; if ( Quad3H(&q) ) { result += (data[2][1] + data[2][3] - q) * 0.5f; weight += 1.f; res = true; } } if ( fill[1][2] && fill[3][2] ) { // got vertical straddle float q; if ( Quad3V(&q) ) { result += (data[1][2] + data[3][2] - q) * 0.5f; weight += 1.f; res = true; } } // look for pairs that lead into the middle : if ( fill[2][0] && fill[2][1] ) { // got left-side pair float q; if ( Quad3H(&q) ) { result += data[2][1]*2.f - data[2][0] + q; weight += 1.f; res = true; } } if ( fill[2][3] && fill[2][4] ) { // got right-side pair float q; if ( Quad3H(&q) ) { result += data[2][3]*2.f - data[2][4] + q; weight += 1.f; res = true; } } if ( fill[0][2] && fill[1][2] ) { // got left-side pair float q; if ( Quad3V(&q) ) { result += data[1][2]*2.f - data[0][2] + q; weight += 1.f; res = true; } } if ( fill[3][2] && fill[4][2] ) { // got right-side pair float q; if ( Quad3V(&q) ) { result += data[3][2]*2.f - data[4][2] + q; weight += 1.f; res = true; } } return res; } bool tryPlanar() const { // four cases : const int indices[] = { 2,1, 1,2, 1,1, 2,1, 3,2, 3,1, 2,3, 1,2, 1,3, 2,3, 3,2, 3,3 }; bool res = false; for (int i = 0; i < 4; i++) { const int * I = indices + i*6; if (!fill[ I[0] ][ I[1] ]) continue; if (!fill[ I[2] ][ I[3] ]) continue; if (!fill[ I[4] ][ I[5] ]) continue; result += data[ I[0] ][ I[1] ] + data[ I[2] ][ I[3] ] - data[ I[4] ][ I[5] ]; weight += 1.0f; res = true; } return res; } bool tryTwos() const { bool res = false; if (fill[2][1] && fill[2][3]) { result += (data[2][1] + data[2][3]) * 0.5f; weight += 1.0f; res = true; } if (fill[1][2] && fill[3][2]) { result += (data[1][2] + data[3][2]) * 0.5f; weight += 1.0f; res = true; } // four side-rotates : const int indices[] = { 2,1, 2,0, 2,3, 2,4, 1,2, 0,2, 3,2, 4,2, }; for (int i = 0; i < 4; i++) { const int * I = indices + i*4; if (!fill[ I[0] ][ I[1] ]) continue; if (!fill[ I[2] ][ I[3] ]) continue; result += data[ I[0] ][ I[1] ]*2.0f - data[ I[2] ][ I[3] ]; weight += 1.0f; res = true; } return res; } bool doLocalPixelFill() const { result = 0.0f; weight = 0.0f; if (tryQuads()) { return true; } if (tryPlanar()) { return true; } return tryTwos(); } }; // struct LocalPixels // This is a quadratic extrapolation filter from Charles Bloom (DoPixelSeamFix). Used with his permission. void nv::fillQuadraticExtrapolate(int passCount, FloatImage * img, BitMap * bmap, int coverageIndex /*= -1*/) { nvCheck(passCount > 0); nvCheck(img != NULL); nvCheck(bmap != NULL); const int w = img->width(); const int h = img->height(); const int count = img->componentNum(); nvCheck(bmap->width() == uint(w)); nvCheck(bmap->height() == uint(h)); AutoPtr newbmap( new BitMap(w, h) ); float * coverageChannel = NULL; if (coverageIndex != -1) { coverageChannel = img->channel(coverageIndex); } int firstChannel = -1; for (int p = 0; p < passCount; p++) { for (int c = 0; c < count; c++) { if (c == coverageIndex) continue; if (firstChannel == -1) firstChannel = c; float * channel = img->channel(c); for (int yb = 0; yb < h; yb++) { for (int xb = 0; xb < w; xb++) { if (bmap->bitAt(xb, yb)) { // Not a hole. newbmap->setBitAt(xb, yb); continue; } int numFill = 0; LocalPixels lp; for (int ny = 0; ny < 5; ny++) { int y = (yb + ny - 2); if ( y < 0 || y >= h ) { // out of range for(int i = 0; i < 5; i++) { lp.fill[ny][i] = false; } continue; } for (int nx = 0; nx < 5; nx++) { int x = (xb + nx - 2); if (x < 0 || x >= w) { lp.fill[ny][nx] = false; } else { int idx = img->index(x, y); if (!bmap->bitAt(idx)) { lp.fill[ny][nx] = false; } else { lp.fill[ny][nx] = true; lp.data[ny][nx] = channel[idx]; numFill++; } } } } // need at least 3 to do anything decent if (numFill < 2) continue; nvDebugCheck(lp.fill[2][2] == false); if (lp.doLocalPixelFill()) { const int idx = img->index(xb, yb); channel[idx] = lp.result / lp.weight; if (c == firstChannel) { //coverageChannel[idx] /= lp.weight; // @@ Not sure what this was for, coverageChannel[idx] is always zero. newbmap->setBitAt(xb, yb); } } } } } // Update the bit mask. swap(*newbmap, *bmap); } } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/HoleFilling.h000066400000000000000000000040211173441656100234730ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_HOLEFILLING_H #define NV_IMAGE_HOLEFILLING_H #include #include namespace nv { class FloatImage; /// Bit mask. class BitMap { public: BitMap(uint w, uint h) : m_width(w), m_height(h), m_bitArray(w*h) { } const uint width() const { return m_width; } const uint height() const { return m_height; } bool bitAt(uint x, uint y) const { nvDebugCheck(x < m_width && y < m_height); return m_bitArray.bitAt(y * m_width + x); } bool bitAt(uint idx) const { return m_bitArray.bitAt(idx); } void setBitAt(uint x, uint y) { nvDebugCheck(x < m_width && y < m_height); m_bitArray.setBitAt(y * m_width + x); } void setBitAt(uint idx) { m_bitArray.setBitAt(idx); } void clearBitAt(uint x, uint y) { nvDebugCheck(x < m_width && y < m_height); m_bitArray.clearBitAt(y * m_width + x); } void clearBitAt(uint idx) { m_bitArray.clearBitAt(idx); } void clearAll() { m_bitArray.clearAll(); } void setAll() { m_bitArray.setAll(); } void toggleAll() { m_bitArray.toggleAll(); } friend void swap(BitMap & a, BitMap & b) { nvCheck(a.m_width == b.m_width); nvCheck(a.m_height == b.m_height); //swap(const_cast(a.m_width), const_cast(b.m_width)); //swap(const_cast(a.m_height), const_cast(b.m_height)); swap(a.m_bitArray, b.m_bitArray); } private: const uint m_width; const uint m_height; BitArray m_bitArray; }; NVIMAGE_API void fillVoronoi(FloatImage * img, const BitMap * bmap); NVIMAGE_API void fillBlur(FloatImage * img, const BitMap * bmap); NVIMAGE_API void fillPullPush(FloatImage * img, const BitMap * bmap); NVIMAGE_API void fillExtrapolate(int passCount, FloatImage * img, BitMap * bmap); NVIMAGE_API void fillQuadraticExtrapolate(int passCount, FloatImage * img, BitMap * bmap, int coverageIndex = -1); } // nv namespace #endif // NV_IMAGE_HOLEFILLING_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/Image.cpp000066400000000000000000000043041173441656100226600ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include #include #include #include using namespace nv; Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(NULL) { } Image::Image(const Image & img) : m_data(NULL) { allocate(img.m_width, img.m_height); m_format = img.m_format; memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height); } Image::~Image() { free(); } const Image & Image::operator=(const Image & img) { allocate(img.m_width, img.m_height); m_format = img.m_format; memcpy(m_data, img.m_data, sizeof(Color32) * m_width * m_height); return *this; } void Image::allocate(uint w, uint h) { m_width = w; m_height = h; m_data = (Color32 *)realloc(m_data, w * h * sizeof(Color32)); } bool Image::load(const char * name) { free(); AutoPtr img(ImageIO::load(name)); if (img == NULL) { return false; } swap(m_width, img->m_width); swap(m_height, img->m_height); swap(m_format, img->m_format); swap(m_data, img->m_data); return true; } void Image::wrap(void * data, uint w, uint h) { free(); m_data = (Color32 *)data; m_width = w; m_height = h; } void Image::unwrap() { m_data = NULL; m_width = 0; m_height = 0; } void Image::free() { nv::mem::free(m_data); m_data = NULL; } uint Image::width() const { return m_width; } uint Image::height() const { return m_height; } const Color32 * Image::scanline(uint h) const { nvDebugCheck(h < m_height); return m_data + h * m_width; } Color32 * Image::scanline(uint h) { nvDebugCheck(h < m_height); return m_data + h * m_width; } const Color32 * Image::pixels() const { return m_data; } Color32 * Image::pixels() { return m_data; } const Color32 & Image::pixel(uint idx) const { nvDebugCheck(idx < m_width * m_height); return m_data[idx]; } Color32 & Image::pixel(uint idx) { nvDebugCheck(idx < m_width * m_height); return m_data[idx]; } Image::Format Image::format() const { return m_format; } void Image::setFormat(Image::Format f) { m_format = f; } void Image::fill(Color32 c) { const uint size = m_width * m_height; for (uint i = 0; i < size; ++i) { m_data[i] = c; } } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/Image.h000066400000000000000000000026061173441656100223300ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_IMAGE_H #define NV_IMAGE_IMAGE_H #include #include namespace nv { class Color32; /// 32 bit RGBA image. class NVIMAGE_CLASS Image { public: enum Format { Format_RGB, Format_ARGB, }; Image(); Image(const Image & img); ~Image(); const Image & operator=(const Image & img); void allocate(uint w, uint h); bool load(const char * name); void wrap(void * data, uint w, uint h); void unwrap(); uint width() const; uint height() const; const Color32 * scanline(uint h) const; Color32 * scanline(uint h); const Color32 * pixels() const; Color32 * pixels(); const Color32 & pixel(uint idx) const; Color32 & pixel(uint idx); const Color32 & pixel(uint x, uint y) const; Color32 & pixel(uint x, uint y); Format format() const; void setFormat(Format f); void fill(Color32 c); private: void free(); private: uint m_width; uint m_height; Format m_format; Color32 * m_data; }; inline const Color32 & Image::pixel(uint x, uint y) const { nvDebugCheck(x < width() && y < height()); return pixel(y * width() + x); } inline Color32 & Image::pixel(uint x, uint y) { nvDebugCheck(x < width() && y < height()); return pixel(y * width() + x); } } // nv namespace #endif // NV_IMAGE_IMAGE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/ImageIO.cpp000066400000000000000000001020321173441656100231050ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include #include #include //#include // @@ Disable temporarily #include #include #include "ImageIO.h" #include "Image.h" #include "FloatImage.h" #include "TgaFile.h" #include "PsdFile.h" // Extern #if defined(HAVE_JPEG) extern "C" { # include } #endif #if defined(HAVE_PNG) # include #endif #if defined(HAVE_TIFF) # define _TIFF_DATA_TYPEDEFS_ # include #endif #if defined(HAVE_OPENEXR) # include # include # include # include # include # include #endif using namespace nv; namespace { // Array of image load plugins. // static HashMap s_plugin_load_map; // Array of image save plugins. // static HashMap s_plugin_save_map; struct Color555 { uint16 b : 5; uint16 g : 5; uint16 r : 5; }; } // namespace Image * nv::ImageIO::load(const char * fileName) { nvDebugCheck(fileName != NULL); StdInputStream stream(fileName); if (stream.isError()) { return NULL; } return ImageIO::load(fileName, stream); } Image * nv::ImageIO::load(const char * fileName, Stream & s) { nvDebugCheck(fileName != NULL); nvDebugCheck(s.isLoading()); const char * extension = Path::extension(fileName); if (strCaseCmp(extension, ".tga") == 0) { return ImageIO::loadTGA(s); } #if defined(HAVE_JPEG) if (strCaseCmp(extension, ".jpg") == 0 || strCaseCmp(extension, ".jpeg") == 0) { return loadJPG(s); } #endif #if defined(HAVE_PNG) if (strCaseCmp(extension, ".png") == 0) { return loadPNG(s); } #endif if (strCaseCmp(extension, ".psd") == 0) { return loadPSD(s); } // @@ use image plugins? return NULL; } bool nv::ImageIO::save(const char * fileName, Stream & s, Image * img) { nvDebugCheck(fileName != NULL); nvDebugCheck(s.isSaving()); nvDebugCheck(img != NULL); const char * extension = Path::extension(fileName); if (strCaseCmp(extension, ".tga") == 0) { return ImageIO::saveTGA(s, img); } return false; } bool nv::ImageIO::save(const char * fileName, Image * img) { nvDebugCheck(fileName != NULL); nvDebugCheck(img != NULL); StdOutputStream stream(fileName); if (stream.isError()) { return false; } return ImageIO::save(fileName, stream, img); } FloatImage * nv::ImageIO::loadFloat(const char * fileName) { nvDebugCheck(fileName != NULL); StdInputStream stream(fileName); if (stream.isError()) { return false; } return loadFloat(fileName, stream); } FloatImage * nv::ImageIO::loadFloat(const char * fileName, Stream & s) { nvDebugCheck(fileName != NULL); const char * extension = Path::extension(fileName); #if defined(HAVE_TIFF) if (strCaseCmp(extension, ".tif") == 0 || strCaseCmp(extension, ".tiff") == 0) { return loadFloatTIFF(fileName, s); } #endif #if defined(HAVE_OPENEXR) if (strCaseCmp(extension, ".exr") == 0) { return loadFloatEXR(fileName, s); } #endif /* // @@ Disable temporarily if (strCaseCmp(extension, ".pfm") == 0) { return loadFloatPFM(fileName, s); } */ return NULL; } bool nv::ImageIO::saveFloat(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components) { const char * extension = Path::extension(fileName); #if defined(HAVE_OPENEXR) if (strCaseCmp(extension, ".exr") == 0) { return ImageIO::saveFloatEXR(fileName, fimage, base_component, num_components); } #endif #if defined(HAVE_TIFF) if (strCaseCmp(extension, ".tif") == 0 || strCaseCmp(extension, ".tiff") == 0) { return ImageIO::saveFloatTIFF(fileName, fimage, base_component, num_components); } #endif /* // @@ Disable Temporarily if (strCaseCmp(extension, ".pfm") == 0) { // return ImageIO::saveFloatPFM(fileName, fimage, base_component, num_components); } */ if (num_components == 3 || num_components == 4) { AutoPtr image(fimage->createImage(base_component, num_components)); nvCheck(image != NULL); if (num_components == 4) { image->setFormat(Image::Format_ARGB); } return ImageIO::save(fileName, image.ptr()); } return false; } /// Load TGA image. Image * nv::ImageIO::loadTGA(Stream & s) { nvCheck(!s.isError()); nvCheck(s.isLoading()); TgaHeader tga; s << tga; s.seek(TgaHeader::Size + tga.id_length); // Get header info. bool rle = false; bool pal = false; bool rgb = false; bool grey = false; switch( tga.image_type ) { case TGA_TYPE_RLE_INDEXED: rle = true; // no break is intended! case TGA_TYPE_INDEXED: if( tga.colormap_type!=1 || tga.colormap_size!=24 || tga.colormap_length>256 ) { nvDebug( "*** ImageIO::loadTGA: Error, only 24bit paletted images are supported.\n" ); return false; } pal = true; break; case TGA_TYPE_RLE_RGB: rle = true; // no break is intended! case TGA_TYPE_RGB: rgb = true; break; case TGA_TYPE_RLE_GREY: rle = true; // no break is intended! case TGA_TYPE_GREY: grey = true; break; default: nvDebug( "*** ImageIO::loadTGA: Error, unsupported image type.\n" ); return false; } const uint pixel_size = (tga.pixel_size/8); nvDebugCheck(pixel_size <= 4); const uint size = tga.width * tga.height * pixel_size; // Read palette uint8 palette[768]; if( pal ) { nvDebugCheck(tga.colormap_length < 256); s.serialize(palette, 3 * tga.colormap_length); } // Decode image. uint8 * mem = new uint8[size]; if( rle ) { // Decompress image in src. uint8 * dst = mem; int num = size; while (num > 0) { // Get packet header uint8 c; s << c; uint count = (c & 0x7f) + 1; num -= count * pixel_size; if (c & 0x80) { // RLE pixels. uint8 pixel[4]; // uint8 pixel[pixel_size]; s.serialize( pixel, pixel_size ); do { memcpy(dst, pixel, pixel_size); dst += pixel_size; } while (--count); } else { // Raw pixels. count *= pixel_size; //file->Read8(dst, count); s.serialize(dst, count); dst += count; } } } else { s.serialize(mem, size); } // Allocate image. AutoPtr img(new Image()); img->allocate(tga.width, tga.height); int lstep; Color32 * dst; if( tga.flags & TGA_ORIGIN_UPPER ) { lstep = tga.width; dst = img->pixels(); } else { lstep = - tga.width; dst = img->pixels() + (tga.height-1) * tga.width; } // Write image. uint8 * src = mem; if( pal ) { for( int y = 0; y < tga.height; y++ ) { for( int x = 0; x < tga.width; x++ ) { uint8 idx = *src++; dst[x].setBGRA(palette[3*idx+0], palette[3*idx+1], palette[3*idx+2], 0xFF); } dst += lstep; } } else if( grey ) { img->setFormat(Image::Format_ARGB); for( int y = 0; y < tga.height; y++ ) { for( int x = 0; x < tga.width; x++ ) { dst[x].setBGRA(*src, *src, *src, *src); src++; } dst += lstep; } } else { if( tga.pixel_size == 16 ) { for( int y = 0; y < tga.height; y++ ) { for( int x = 0; x < tga.width; x++ ) { Color555 c = *reinterpret_cast(src); uint8 b = (c.b << 3) | (c.b >> 2); uint8 g = (c.g << 3) | (c.g >> 2); uint8 r = (c.r << 3) | (c.r >> 2); dst[x].setBGRA(b, g, r, 0xFF); src += 2; } dst += lstep; } } else if( tga.pixel_size == 24 ) { for( int y = 0; y < tga.height; y++ ) { for( int x = 0; x < tga.width; x++ ) { dst[x].setBGRA(src[0], src[1], src[2], 0xFF); src += 3; } dst += lstep; } } else if( tga.pixel_size == 32 ) { img->setFormat(Image::Format_ARGB); for( int y = 0; y < tga.height; y++ ) { for( int x = 0; x < tga.width; x++ ) { dst[x].setBGRA(src[0], src[1], src[2], src[3]); src += 4; } dst += lstep; } } } // free uncompressed data. delete [] mem; return img.release(); } /// Save TGA image. bool nv::ImageIO::saveTGA(Stream & s, const Image * img) { nvCheck(!s.isError()); nvCheck(img != NULL); nvCheck(img->pixels() != NULL); TgaFile tga; tga.head.id_length = 0; tga.head.colormap_type = 0; tga.head.image_type = TGA_TYPE_RGB; tga.head.colormap_index = 0; tga.head.colormap_length = 0; tga.head.colormap_size = 0; tga.head.x_origin = 0; tga.head.y_origin = 0; tga.head.width = img->width(); tga.head.height = img->height(); if(img->format() == Image::Format_ARGB) { tga.head.pixel_size = 32; tga.head.flags = TGA_ORIGIN_UPPER | TGA_HAS_ALPHA; } else { tga.head.pixel_size = 24; tga.head.flags = TGA_ORIGIN_UPPER; } // @@ Serialize directly. tga.allocate(); const uint n = img->width() * img->height(); if(img->format() == Image::Format_ARGB) { for(uint i = 0; i < n; i++) { Color32 color = img->pixel(i); tga.mem[4 * i + 0] = color.b; tga.mem[4 * i + 1] = color.g; tga.mem[4 * i + 2] = color.r; tga.mem[4 * i + 3] = color.a; } } else { for(uint i = 0; i < n; i++) { Color32 color = img->pixel(i); tga.mem[3 * i + 0] = color.b; tga.mem[3 * i + 1] = color.g; tga.mem[3 * i + 2] = color.r; } } s << tga; tga.free(); return true; } /// Load PSD image. Image * nv::ImageIO::loadPSD(Stream & s) { nvCheck(!s.isError()); nvCheck(s.isLoading()); s.setByteOrder(Stream::BigEndian); PsdHeader header; s << header; if (!header.isValid()) { printf("invalid header!\n"); return NULL; } if (!header.isSupported()) { printf("unsupported file!\n"); return NULL; } int tmp; // Skip mode data. s << tmp; s.seek(s.tell() + tmp); // Skip image resources. s << tmp; s.seek(s.tell() + tmp); // Skip the reserved data. s << tmp; s.seek(s.tell() + tmp); // Find out if the data is compressed. // Known values: // 0: no compression // 1: RLE compressed uint16 compression; s << compression; if (compression > 1) { // Unknown compression type. return NULL; } uint channel_num = header.channel_count; AutoPtr img(new Image()); img->allocate(header.width, header.height); if (channel_num < 4) { // Clear the image. img->fill(Color32(0, 0, 0, 0xFF)); } else { // Enable alpha. img->setFormat(Image::Format_ARGB); // Ignore remaining channels. channel_num = 4; } const uint pixel_count = header.height * header.width; static const uint components[4] = {2, 1, 0, 3}; if (compression) { s.seek(s.tell() + header.height * header.channel_count * sizeof(uint16)); // Read RLE data. for (uint channel = 0; channel < channel_num; channel++) { uint8 * ptr = (uint8 *)img->pixels() + components[channel]; uint count = 0; while( count < pixel_count ) { if (s.isAtEnd()) return NULL; uint8 c; s << c; uint len = c; if (len < 128) { // Copy next len+1 bytes literally. len++; count += len; if (count > pixel_count) return NULL; while (len != 0) { s << *ptr; ptr += 4; len--; } } else if (len > 128) { // Next -len+1 bytes in the dest are replicated from next source byte. // (Interpret len as a negative 8-bit int.) len ^= 0xFF; len += 2; count += len; if (s.isAtEnd() || count > pixel_count) return NULL; uint8 val; s << val; while( len != 0 ) { *ptr = val; ptr += 4; len--; } } else if( len == 128 ) { // No-op. } } } } else { // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) // where each channel consists of an 8-bit value for each pixel in the image. // Read the data by channel. for (uint channel = 0; channel < channel_num; channel++) { uint8 * ptr = (uint8 *)img->pixels() + components[channel]; // Read the data. uint count = pixel_count; while (count != 0) { s << *ptr; ptr += 4; count--; } } } return img.release(); } #if defined(HAVE_PNG) static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { nvDebugCheck(png_ptr != NULL); Stream * s = (Stream *)png_ptr->io_ptr; s->serialize(data, (int)length); if (s->isError()) { png_error(png_ptr, "Read Error"); } } Image * nv::ImageIO::loadPNG(Stream & s) { nvCheck(!s.isError()); // Set up a read buffer and check the library version png_structp png_ptr; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { // nvDebug( "*** LoadPNG: Error allocating read buffer in file '%s'.\n", name ); return false; } // Allocate/initialize a memory block for the image information png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); // nvDebug( "*** LoadPNG: Error allocating image information for '%s'.\n", name ); return false; } // Set up the error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); // nvDebug( "*** LoadPNG: Error reading png file '%s'.\n", name ); return false; } // Set up the I/O functions. png_set_read_fn(png_ptr, (void*)&s, user_read_data); // Retrieve the image header information png_uint_32 width, height; int bit_depth, color_type, interlace_type; png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) { // Convert indexed images to RGB. png_set_expand(png_ptr); } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { // Convert grayscale to RGB. png_set_expand(png_ptr); } else if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { // Expand images with transparency to full alpha channels // so the data will be available as RGBA quartets. png_set_expand(png_ptr); } else if (bit_depth < 8) { // If we have < 8 scale it up to 8. //png_set_expand(png_ptr); png_set_packing(png_ptr); } // Reduce bit depth. if (bit_depth == 16) { png_set_strip_16(png_ptr); } // Represent gray as RGB if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); } // Convert to RGBA filling alpha with 0xFF. if (!(color_type & PNG_COLOR_MASK_ALPHA)) { png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); } // @todo Choose gamma according to the platform? double screen_gamma = 2.2; int intent; if (png_get_sRGB(png_ptr, info_ptr, &intent)) { png_set_gamma(png_ptr, screen_gamma, 0.45455); } else { double image_gamma; if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) { png_set_gamma(png_ptr, screen_gamma, image_gamma); } else { png_set_gamma(png_ptr, screen_gamma, 0.45455); } } // Perform the selected transforms. png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); AutoPtr img(new Image()); img->allocate(width, height); // Set internal format flags. if(color_type & PNG_COLOR_MASK_COLOR) { //img->flags |= PI_IF_HAS_COLOR; } if(color_type & PNG_COLOR_MASK_ALPHA) { //img->flags |= PI_IF_HAS_ALPHA; img->setFormat(Image::Format_ARGB); } // Read the image uint8 * pixels = (uint8 *)img->pixels(); png_bytep * row_data = new png_bytep[sizeof(png_byte) * height]; for (uint i = 0; i < height; i++) { row_data[i] = &(pixels[width * 4 * i]); } png_read_image(png_ptr, row_data); delete [] row_data; // Finish things up png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); // RGBA to BGRA. uint num = width * height; for(uint i = 0; i < num; i++) { Color32 c = img->pixel(i); img->pixel(i) = Color32(c.b, c.g, c.r, c.a); } // Compute alpha channel if needed. /*if( img->flags & PI_IU_BUMPMAP || img->flags & PI_IU_ALPHAMAP ) { if( img->flags & PI_IF_HAS_COLOR && !(img->flags & PI_IF_HAS_ALPHA)) { img->ComputeAlphaFromColor(); } }*/ return img.release(); } #endif // defined(HAVE_PNG) #if defined(HAVE_JPEG) static void init_source (j_decompress_ptr /*cinfo*/){ } static boolean fill_input_buffer (j_decompress_ptr cinfo){ struct jpeg_source_mgr * src = cinfo->src; static JOCTET FakeEOI[] = { 0xFF, JPEG_EOI }; // Generate warning nvDebug("jpeglib: Premature end of file\n"); // Insert a fake EOI marker src->next_input_byte = FakeEOI; src->bytes_in_buffer = 2; return TRUE; } static void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { struct jpeg_source_mgr * src = cinfo->src; if(num_bytes >= (long)src->bytes_in_buffer) { fill_input_buffer(cinfo); return; } src->bytes_in_buffer -= num_bytes; src->next_input_byte += num_bytes; } static void term_source (j_decompress_ptr /*cinfo*/){ // no work necessary here } Image * nv::ImageIO::loadJPG(Stream & s) { nvCheck(!s.isError()); // Read the entire file. Array byte_array; byte_array.resize(s.size()); s.serialize(byte_array.unsecureBuffer(), s.size()); jpeg_decompress_struct cinfo; jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof(struct jpeg_source_mgr)); cinfo.src->init_source = init_source; cinfo.src->fill_input_buffer = fill_input_buffer; cinfo.src->skip_input_data = skip_input_data; cinfo.src->resync_to_restart = jpeg_resync_to_restart; // use default method cinfo.src->term_source = term_source; cinfo.src->bytes_in_buffer = byte_array.size(); cinfo.src->next_input_byte = byte_array.buffer(); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); /* cinfo.do_fancy_upsampling = FALSE; // fast decompression cinfo.dct_method = JDCT_FLOAT; // Choose floating point DCT method. */ uint8 * tmp_buffer = new uint8 [cinfo.output_width * cinfo.output_height * cinfo.num_components]; uint8 * scanline = tmp_buffer; while( cinfo.output_scanline < cinfo.output_height ){ int num_scanlines = jpeg_read_scanlines (&cinfo, &scanline, 1); scanline += num_scanlines * cinfo.output_width * cinfo.num_components; } jpeg_finish_decompress(&cinfo); AutoPtr img(new Image()); img->allocate(cinfo.output_width, cinfo.output_height); Color32 * dst = img->pixels(); const int size = img->height() * img->width(); const uint8 * src = tmp_buffer; if( cinfo.num_components == 3 ) { img->setFormat(Image::Format_RGB); for( int i = 0; i < size; i++ ) { *dst++ = Color32(src[0], src[1], src[2]); src += 3; } } else { img->setFormat(Image::Format_ARGB); for( int i = 0; i < size; i++ ) { *dst++ = Color32(*src, *src, *src, *src); src++; } } delete [] tmp_buffer; jpeg_destroy_decompress (&cinfo); return img.release(); } #endif // defined(HAVE_JPEG) #if defined(HAVE_TIFF) /* static tsize_t tiffReadWriteProc(thandle_t h, tdata_t ptr, tsize_t size) { Stream * s = (Stream *)h; nvDebugCheck(s != NULL); s->serialize(ptr, size); return size; } static toff_t tiffSeekProc(thandle_t h, toff_t offset, int whence) { Stream * s = (Stream *)h; nvDebugCheck(s != NULL); if (!s->isSeekable()) { return (toff_t)-1; } if (whence == SEEK_SET) { s->seek(offset); } else if (whence == SEEK_CUR) { s->seek(s->tell() + offset); } else if (whence == SEEK_END) { s->seek(s->size() + offset); } return s->tell(); } static int tiffCloseProc(thandle_t) { return 0; } static toff_t tiffSizeProc(thandle_t h) { Stream * s = (Stream *)h; nvDebugCheck(s != NULL); return s->size(); } static int tiffMapFileProc(thandle_t, tdata_t*, toff_t*) { // @@ TODO, Implement these functions. return -1; } static void tiffUnmapFileProc(thandle_t, tdata_t, toff_t) { // @@ TODO, Implement these functions. } */ FloatImage * nv::ImageIO::loadFloatTIFF(const char * fileName, Stream & s) { nvCheck(!s.isError()); TIFF * tif = TIFFOpen(fileName, "r"); //TIFF * tif = TIFFClientOpen(fileName, "r", &s, tiffReadWriteProc, tiffReadWriteProc, tiffSeekProc, tiffCloseProc, tiffSizeProc, tiffMapFileProc, tiffUnmapFileProc); if (!tif) { nvDebug("Can't open '%s' for reading\n", fileName); return NULL; } ::uint16 spp, bpp, format; ::uint32 width, height; TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp); TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp); TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &format); if (bpp != 8 && bpp != 16 && bpp != 32) { nvDebug("Can't load '%s', only 1 sample per pixel supported\n", fileName); TIFFClose(tif); return NULL; } AutoPtr fimage(new FloatImage()); fimage->allocate(spp, width, height); int linesize = TIFFScanlineSize(tif); tdata_t buf = (::uint8 *)nv::mem::malloc(linesize); for (uint y = 0; y < height; y++) { TIFFReadScanline(tif, buf, y, 0); for (uint c=0; cscanline(y, c); for(uint x = 0; x < width; x++) { if (bpp == 8) { dst[x] = float(((::uint8 *)buf)[x*spp+c]) / float(0xFF); } else if (bpp == 16) { dst[x] = float(((::uint16 *)buf)[x*spp+c]) / float(0xFFFF); } else if (bpp == 32) { if (format==SAMPLEFORMAT_IEEEFP) { dst[x] = float(((float *)buf)[x*spp+c]); } else { dst[x] = float(((::uint32 *)buf)[x*spp+c] >> 8) / float(0xFFFFFF); } } } } } nv::mem::free(buf); TIFFClose(tif); return fimage.release(); } bool nv::ImageIO::saveFloatTIFF(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components) { nvCheck(fileName != NULL); nvCheck(fimage != NULL); nvCheck(base_component + num_components <= fimage->componentNum()); const int iW = fimage->width(); const int iH = fimage->height(); const int iC = num_components; TIFF * image = TIFFOpen(fileName, "w"); // Open the TIFF file if (image == NULL) { nvDebug("Could not open '%s' for writing\n", fileName); return false; } TIFFSetField(image, TIFFTAG_IMAGEWIDTH, iW); TIFFSetField(image, TIFFTAG_IMAGELENGTH, iH); TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, iC); TIFFSetField(image, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 32); uint32 rowsperstrip = TIFFDefaultStripSize(image, (uint32)-1); TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, rowsperstrip); TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS); if (num_components == 3) { // Set this so that it can be visualized with pfstools. TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); } TIFFSetField(image, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); float * scanline = new float[iW * iC]; for (int y = 0; y < iH; y++) { for (int c = 0; c < iC; c++) { const float * src = fimage->scanline(y, base_component + c); for (int x = 0; x < iW; x++) scanline[x * iC + c] = src[x]; } if (TIFFWriteScanline(image, scanline, y, 0)==-1) { nvDebug("Error writing scanline %d\n", y); return false; } } delete [] scanline; // Close the file TIFFClose(image); return true; } #endif #if defined(HAVE_OPENEXR) namespace { class ExrStream : public Imf::IStream { public: ExrStream(const char * name, Stream & s) : Imf::IStream(name), m_stream(s) { nvDebugCheck(s.isLoading()); } virtual bool read(char c[], int n) { m_stream.serialize(c, n); if (m_stream.isError()) { throw Iex::InputExc("I/O error."); } return m_stream.isAtEnd(); } virtual Imf::Int64 tellg() { return m_stream.tell(); } virtual void seekg(Imf::Int64 pos) { m_stream.seek(pos); } virtual void clear() { m_stream.clearError(); } private: Stream & m_stream; }; } // namespace FloatImage * nv::ImageIO::loadFloatEXR(const char * fileName, Stream & s) { nvCheck(s.isLoading()); nvCheck(!s.isError()); ExrStream stream(fileName, s); Imf::InputFile inputFile(stream); Imath::Box2i box = inputFile.header().dataWindow(); int width = box.max.x - box.min.y + 1; int height = box.max.x - box.min.y + 1; const Imf::ChannelList & channels = inputFile.header().channels(); // Count channels. uint channelCount= 0; for (Imf::ChannelList::ConstIterator it = channels.begin(); it != channels.end(); ++it) { channelCount++; } // Allocate FloatImage. AutoPtr fimage(new FloatImage()); fimage->allocate(channelCount, width, height); // Describe image's layout with a framebuffer. Imf::FrameBuffer frameBuffer; uint i = 0; for (Imf::ChannelList::ConstIterator it = channels.begin(); it != channels.end(); ++it, ++i) { frameBuffer.insert(it.name(), Imf::Slice(Imf::FLOAT, (char *)fimage->channel(i), sizeof(float), sizeof(float) * width)); } // Read it. inputFile.setFrameBuffer (frameBuffer); inputFile.readPixels (box.min.y, box.max.y); return fimage.release(); } bool nv::ImageIO::saveFloatEXR(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components) { nvCheck(fileName != NULL); nvCheck(fimage != NULL); nvCheck(base_component + num_components <= fimage->componentNum()); nvCheck(num_components > 0 && num_components <= 4); const int w = fimage->width(); const int h = fimage->height(); const char * channelNames[] = {"R", "G", "B", "A"}; Imf::Header header (w, h); for (uint c = 0; c < num_components; c++) { header.channels().insert(channelNames[c], Imf::Channel(Imf::FLOAT)); } Imf::OutputFile file(fileName, header); Imf::FrameBuffer frameBuffer; for (uint c = 0; c < num_components; c++) { char * channel = (char *) fimage->channel(base_component + c); frameBuffer.insert(channelNames[c], Imf::Slice(Imf::FLOAT, channel, sizeof(float), sizeof(float) * w)); } file.setFrameBuffer(frameBuffer); file.writePixels(h); return true; } #endif // defined(HAVE_OPENEXR) #if 0 // @@ Disable temporarily. FloatImage * nv::ImageIO::loadFloatPFM(const char * fileName, Stream & s) { nvCheck(s.isLoading()); nvCheck(!s.isError()); Tokenizer parser(&s); parser.nextToken(); bool grayscale; if (parser.token() == "PF") { grayscale = false; } else if (parser.token() == "Pf") { grayscale = true; } else { // Invalid file. return NULL; } parser.nextLine(); int width = parser.token().toInt(); parser.nextToken(); int height = parser.token().toInt(); parser.nextLine(); float scaleFactor = parser.token().toFloat(); if (scaleFactor >= 0) { s.setByteOrder(Stream::BigEndian); } else { s.setByteOrder(Stream::LittleEndian); } scaleFactor = fabsf(scaleFactor); // Allocate image. AutoPtr fimage(new FloatImage()); if (grayscale) { fimage->allocate(1, width, height); float * channel = fimage->channel(0); for (int i = 0; i < width * height; i++) { s << channel[i]; } } else { fimage->allocate(3, width, height); float * rchannel = fimage->channel(0); float * gchannel = fimage->channel(1); float * bchannel = fimage->channel(2); for (int i = 0; i < width * height; i++) { s << rchannel[i] << gchannel[i] << bchannel[i]; } } return fimage.release(); } bool nv::ImageIO::saveFloatPFM(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components) { nvCheck(fileName != NULL); nvCheck(fimage != NULL); nvCheck(fimage->componentNum() <= base_component + num_components); nvCheck(num_components == 1 || num_components == 3); StdOutputStream stream(fileName); TextWriter writer(&stream); if (num_components == 1) writer.write("Pf\n"); else /*if (num_components == 3)*/ writer.write("PF\n"); int w = fimage->width(); int h = fimage->height(); writer.write("%d %d\n", w, h); writer.write("%f\n", -1.0f); // little endian with 1.0 scale. if (num_components == 1) { float * channel = const_cast(fimage->channel(0)); for (int i = 0; i < w * h; i++) { stream << channel[i]; } } else { float * rchannel = const_cast(fimage->channel(0)); float * gchannel = const_cast(fimage->channel(1)); float * bchannel = const_cast(fimage->channel(2)); for (int i = 0; i < w * h; i++) { stream << rchannel[i] << gchannel[i] << bchannel[i]; } } return true; } #endif #if 0 /** Save PNG*/ static bool SavePNG(const PiImage * img, const char * name) { nvCheck( img != NULL ); nvCheck( img->mem != NULL ); if( piStrCmp(piExtension(name), ".png" ) != 0 ) { return false; } if( img->flags & PI_IT_CUBEMAP ) { nvDebug("*** Cannot save cubemaps as PNG."); return false; } if( img->flags & PI_IT_DDS ) { nvDebug("*** Cannot save DDS surface as PNG."); return false; } nvDebug( "--- Saving '%s'.\n", name ); PiAutoPtr ar( PiFileSystem::CreateFileWriter( name ) ); if( ar == NULL ) { nvDebug( "*** SavePNG: Error, cannot save file '%s'.\n", name ); return false; } /* public class PNGEnc { public static function encode(img:BitmapData):ByteArray { // Create output byte array var png:ByteArray = new ByteArray(); // Write PNG signature png.writeUnsignedInt(0x89504e47); png.writeUnsignedInt(0x0D0A1A0A); // Build IHDR chunk var IHDR:ByteArray = new ByteArray(); IHDR.writeInt(img.width); IHDR.writeInt(img.height); IHDR.writeUnsignedInt(0x08060000); // 32bit RGBA IHDR.writeByte(0); writeChunk(png,0x49484452,IHDR); // Build IDAT chunk var IDAT:ByteArray= new ByteArray(); for(var i:int=0;i < img.height;i++) { // no filter IDAT.writeByte(0); var p:uint; if ( !img.transparent ) { for(var j:int=0;j < img.width;j++) { p = img.getPixel(j,i); IDAT.writeUnsignedInt( uint(((p&0xFFFFFF) << 8)|0xFF)); } } else { for(var j:int=0;j < img.width;j++) { p = img.getPixel32(j,i); IDAT.writeUnsignedInt( uint(((p&0xFFFFFF) << 8)| (shr(p,24)))); } } } IDAT.compress(); writeChunk(png,0x49444154,IDAT); // Build IEND chunk writeChunk(png,0x49454E44,null); // return PNG return png; } private static var crcTable:Array; private static var crcTableComputed:Boolean = false; private static function writeChunk(png:ByteArray, type:uint, data:ByteArray) { if (!crcTableComputed) { crcTableComputed = true; crcTable = []; for (var n:uint = 0; n < 256; n++) { var c:uint = n; for (var k:uint = 0; k < 8; k++) { if (c & 1) { c = uint(uint(0xedb88320) ^ uint(c >>> 1)); } else { c = uint(c >>> 1); } } crcTable[n] = c; } } var len:uint = 0; if (data != null) { len = data.length; } png.writeUnsignedInt(len); var p:uint = png.position; png.writeUnsignedInt(type); if ( data != null ) { png.writeBytes(data); } var e:uint = png.position; png.position = p; var c:uint = 0xffffffff; for (var i:int = 0; i < (e-p); i++) { c = uint(crcTable[ (c ^ png.readUnsignedByte()) & uint(0xff)] ^ uint(c >>> 8)); } c = uint(c^uint(0xffffffff)); png.position = e; png.writeUnsignedInt(c); } } */ } #endif // 0 #if 0 namespace ImageIO { /** Init ImageIO plugins. */ void InitPlugins() { // AddInputPlugin( "", LoadANY ); AddInputPlugin( "tga", LoadTGA ); #if HAVE_PNG AddInputPlugin( "png", LoadPNG ); #endif #if HAVE_JPEG AddInputPlugin( "jpg", LoadJPG ); #endif AddInputPlugin( "dds", LoadDDS ); AddOutputPlugin( "tga", SaveTGA ); } /** Reset ImageIO plugins. */ void ResetPlugins() { s_plugin_load_map.Clear(); s_plugin_save_map.Clear(); } /** Add an input plugin. */ void AddInputPlugin( const char * ext, ImageInput_Plugin plugin ) { s_plugin_load_map.Add(ext, plugin); } /** Add an output plugin. */ void AddOutputPlugin( const char * ext, ImageOutput_Plugin plugin ) { s_plugin_save_map.Add(ext, plugin); } bool Load(PiImage * img, const char * name, PiStream & stream) { // Get name extension. const char * extension = piExtension(name); // Skip the dot. if( *extension == '.' ) { extension++; } // Lookup plugin in the map. ImageInput_Plugin plugin = NULL; if( s_plugin_load_map.Get(extension, &plugin) ) { return plugin(img, stream); } /*foreach(i, s_plugin_load_map) { nvDebug("%s %s %d\n", s_plugin_load_map[i].key.GetStr(), extension, 0 == strcmp(extension, s_plugin_load_map[i].key)); } nvDebug("No plugin found for '%s' %d.\n", extension, s_plugin_load_map.Size());*/ return false; } bool Save(const PiImage * img, const char * name, PiStream & stream) { // Get name extension. const char * extension = piExtension(name); // Skip the dot. if( *extension == '.' ) { extension++; } // Lookup plugin in the map. ImageOutput_Plugin plugin = NULL; if( s_plugin_save_map.Get(extension, &plugin) ) { return plugin(img, stream); } return false; } } // ImageIO #endif // 0 nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/ImageIO.h000066400000000000000000000033751173441656100225640ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_IMAGEIO_H #define NV_IMAGE_IMAGEIO_H #include namespace nv { class Image; class FloatImage; class Stream; namespace ImageIO { NVIMAGE_API Image * load(const char * fileName); NVIMAGE_API Image * load(const char * fileName, Stream & s); NVIMAGE_API FloatImage * loadFloat(const char * fileName); NVIMAGE_API FloatImage * loadFloat(const char * fileName, Stream & s); NVIMAGE_API bool save(const char * fileName, Stream & s, Image * img); NVIMAGE_API bool save(const char * fileName, Image * img); NVIMAGE_API bool saveFloat(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components); NVIMAGE_API Image * loadTGA(Stream & s); NVIMAGE_API bool saveTGA(Stream & s, const Image * img); NVIMAGE_API Image * loadPSD(Stream & s); #if defined(HAVE_PNG) NVIMAGE_API Image * loadPNG(Stream & s); #endif #if defined(HAVE_JPEG) NVIMAGE_API Image * loadJPG(Stream & s); #endif #if defined(HAVE_TIFF) NVIMAGE_API FloatImage * loadFloatTIFF(const char * fileName, Stream & s); NVIMAGE_API bool saveFloatTIFF(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components); #endif #if defined(HAVE_OPENEXR) NVIMAGE_API FloatImage * loadFloatEXR(const char * fileName, Stream & s); NVIMAGE_API bool saveFloatEXR(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components); #endif // NVIMAGE_API FloatImage * loadFloatPFM(const char * fileName, Stream & s); // NVIMAGE_API bool saveFloatPFM(const char * fileName, const FloatImage * fimage, uint base_component, uint num_components); } // ImageIO namespace } // nv namespace #endif // NV_IMAGE_IMAGEIO_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/NormalMap.cpp000066400000000000000000000074761173441656100235410ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include using namespace nv; // Create normal map using the given kernels. static FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, const Kernel2 * kdu, const Kernel2 * kdv) { nvCheck(kdu != NULL); nvCheck(kdv != NULL); nvCheck(img != NULL); const uint w = img->width(); const uint h = img->height(); AutoPtr fimage(new FloatImage()); fimage->allocate(4, w, h); // Compute height and store in alpha channel: float * alphaChannel = fimage->channel(3); for(uint i = 0; i < w*h; i++) { Vector4 color = toVector4(img->pixel(i)); alphaChannel[i] = dot(color, heightWeights); } float heightScale = 1.0f / 16.0f; // @@ Use a user defined factor. for(uint y = 0; y < h; y++) { for(uint x = 0; x < w; x++) { const float du = fimage->applyKernel(kdu, x, y, 3, wm); const float dv = fimage->applyKernel(kdv, x, y, 3, wm); Vector3 n = normalize(Vector3(du, dv, heightScale)); fimage->setPixel(0.5f * n.x() + 0.5f, x, y, 0); fimage->setPixel(0.5f * n.y() + 0.5f, x, y, 1); fimage->setPixel(0.5f * n.z() + 0.5f, x, y, 2); } } return fimage.release(); } /// Create normal map using the given filter. FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, NormalMapFilter filter /*= Sobel3x3*/) { nvCheck(img != NULL); // Init the kernels. Kernel2 * kdu = NULL; Kernel2 * kdv = NULL; switch(filter) { case NormalMapFilter_Sobel3x3: kdu = new Kernel2(3); break; case NormalMapFilter_Sobel5x5: kdu = new Kernel2(5); break; case NormalMapFilter_Sobel7x7: kdu = new Kernel2(7); break; case NormalMapFilter_Sobel9x9: kdu = new Kernel2(9); break; default: nvDebugCheck(false); }; kdu->initSobel(); kdu->normalize(); kdv = new Kernel2(*kdu); kdv->transpose(); return ::createNormalMap(img, wm, heightWeights, kdu, kdv); } /// Create normal map combining multiple sobel filters. FloatImage * nv::createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, Vector4::Arg filterWeights) { nvCheck(img != NULL); Kernel2 * kdu = NULL; Kernel2 * kdv = NULL; kdu = new Kernel2(9); kdu->initBlendedSobel(filterWeights); kdu->normalize(); kdv = new Kernel2(*kdu); kdv->transpose(); return ::createNormalMap(img, wm, heightWeights, kdu, kdv); } /// Normalize the given image in place. void nv::normalizeNormalMap(FloatImage * img) { nvCheck(img != NULL); img->expandNormals(0); img->normalize(0); img->packNormals(0); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/NormalMap.h000066400000000000000000000036621173441656100231770ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_IMAGE_NORMALMAP_H #define NV_IMAGE_NORMALMAP_H #include #include #include namespace nv { class Image; enum NormalMapFilter { NormalMapFilter_Sobel3x3, // fine detail NormalMapFilter_Sobel5x5, // medium detail NormalMapFilter_Sobel7x7, // large detail NormalMapFilter_Sobel9x9, // very large }; FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, NormalMapFilter filter = NormalMapFilter_Sobel3x3); FloatImage * createNormalMap(const Image * img, FloatImage::WrapMode wm, Vector4::Arg heightWeights, Vector4::Arg filterWeights); void normalizeNormalMap(FloatImage * img); // @@ Add generation of DU/DV maps. } // nv namespace #endif // NV_IMAGE_NORMALMAP_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/NormalMipmap.cpp000066400000000000000000000040351173441656100242330ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include #include #include #include using namespace nv; FloatImage * nv::createNormalMipmapMap(const FloatImage * img) { nvDebugCheck(img != NULL); uint w = img->width(); uint h = img->height(); uint hw = w / 2; uint hh = h / 2; FloatImage dotImg; dotImg.allocate(1, w, h); FloatImage shImg; shImg.allocate(9, hw, hh); SampleDistribution distribution(256); const uint sampleCount = distribution.sampleCount(); for (uint d = 0; d < sampleCount; d++) { const float * xChannel = img->channel(0); const float * yChannel = img->channel(1); const float * zChannel = img->channel(2); Vector3 dir = distribution.sampleDir(d); Sh2 basis; basis.eval(dir); for(uint i = 0; i < w*h; i++) { Vector3 normal(xChannel[i], yChannel[i], zChannel[i]); normal = normalizeSafe(normal, Vector3(zero), 0.0f); dotImg.setPixel(dot(dir, normal), d); } // @@ It would be nice to have a fastDownSample that took an existing image as an argument, to avoid allocations. AutoPtr dotMip(dotImg.fastDownSample()); for(uint p = 0; p < hw*hh; p++) { float f = dotMip->pixel(p); // Project irradiance to sh basis and accumulate. for (uint i = 0; i < 9; i++) { float & sum = shImg.channel(i)[p]; sum += f * basis.elemAt(i); } } } FloatImage * normalMipmap = new FloatImage; normalMipmap->allocate(4, hw, hh); // Precompute the clamped cosine radiance transfer. Sh2 prt; prt.cosineTransfer(); // Allocate outside the loop. Sh2 sh; for(uint p = 0; p < hw*hh; p++) { for (uint i = 0; i < 9; i++) { sh.elemAt(i) = shImg.channel(i)[p]; } // Convolve sh irradiance by radiance transfer. sh *= prt; // Now sh(0) is the ambient occlusion. // and sh(1) is the normal direction. // Should we use SVD to fit only the normals to the SH? } return normalMipmap; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/NormalMipmap.h000066400000000000000000000004611173441656100236770ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_NORMALMIPMAP_H #define NV_IMAGE_NORMALMIPMAP_H #include namespace nv { class FloatImage; FloatImage * createNormalMipmapMap(const FloatImage * img); } // nv namespace #endif // NV_IMAGE_NORMALMIPMAP_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/PixelFormat.h000066400000000000000000000041451173441656100235400ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_IMAGE_PIXELFORMAT_H #define NV_IMAGE_PIXELFORMAT_H #include namespace nv { namespace PixelFormat { // Convert component @a c having @a inbits to the returned value having @a outbits. inline uint convert(uint c, uint inbits, uint outbits) { if (inbits == 0) { return 0; } else if (inbits >= outbits) { // truncate return c >> (inbits - outbits); } else { // bitexpand return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); } } // Get pixel component shift and size given its mask. inline void maskShiftAndSize(uint mask, uint * shift, uint * size) { if (!mask) { *shift = 0; *size = 0; return; } *shift = 0; while((mask & 1) == 0) { ++(*shift); mask >>= 1; } *size = 0; while((mask & 1) == 1) { ++(*size); mask >>= 1; } } } // PixelFormat namespace } // nv namespace #endif // NV_IMAGE_PIXELFORMAT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/PsdFile.h000066400000000000000000000024321173441656100226310ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_PSDFILE_H #define NV_IMAGE_PSDFILE_H #include namespace nv { enum PsdColorMode { PsdColorMode_Bitmap = 0, PsdColorMode_GrayScale = 1, PsdColorMode_Indexed = 2, PsdColorMode_RGB = 3, PsdColorMode_CMYK = 4, PsdColorMode_MultiChannel = 7, PsdColorMode_DuoTone = 8, PsdColorMode_LabColor = 9 }; /// PSD header. struct PsdHeader { uint32 signature; uint16 version; uint8 reserved[6]; uint16 channel_count; uint32 height; uint32 width; uint16 depth; uint16 color_mode; bool isValid() const { return signature == 0x38425053; // '8BPS' } bool isSupported() const { if (version != 1) { nvDebug("*** bad version number %u\n", version); return false; } if (channel_count > 4) { return false; } if (depth != 8) { return false; } if (color_mode != PsdColorMode_RGB) { return false; } return true; } }; inline Stream & operator<< (Stream & s, PsdHeader & head) { s << head.signature << head.version; for (int i = 0; i < 6; i++) { s << head.reserved[i]; } return s << head.channel_count << head.height << head.width << head.depth << head.color_mode; } } // nv namespace #endif // NV_IMAGE_PSDFILE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/Quantize.cpp000066400000000000000000000121771173441656100234450ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es /* http://www.visgraf.impa.br/Courses/ip00/proj/Dithering1/floyd_steinberg_dithering.html http://www.gamedev.net/reference/articles/article341.asp @@ Look at LPS: http://www.cs.rit.edu/~pga/pics2000/i.html This is a really nice guide to dithering algorithms: http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT @@ This code needs to be reviewed, I'm not sure it's correct. */ #include #include #include #include #include // swap using namespace nv; // Simple quantization. void nv::Quantize::BinaryAlpha( Image * image, int alpha_threshold /*= 127*/ ) { nvCheck(image != NULL); const uint w = image->width(); const uint h = image->height(); for(uint y = 0; y < h; y++) { for(uint x = 0; x < w; x++) { Color32 pixel = image->pixel(x, y); // Convert color. if( pixel.a > alpha_threshold ) pixel.a = 255; else pixel.a = 0; // Store color. image->pixel(x, y) = pixel; } } } // Simple quantization. void nv::Quantize::RGB16( Image * image ) { Truncate(image, 5, 6, 5, 8); } // Alpha quantization. void nv::Quantize::Alpha4( Image * image ) { Truncate(image, 8, 8, 8, 4); } // Error diffusion. Floyd Steinberg. void nv::Quantize::FloydSteinberg_RGB16( Image * image ) { FloydSteinberg(image, 5, 6, 5, 8); } // Error diffusion. Floyd Steinberg. void nv::Quantize::FloydSteinberg_BinaryAlpha( Image * image, int alpha_threshold /*= 127*/ ) { nvCheck(image != NULL); const uint w = image->width(); const uint h = image->height(); // @@ Use fixed point? float * row0 = new float[(w+2)]; float * row1 = new float[(w+2)]; memset(row0, 0, sizeof(float)*(w+2)); memset(row1, 0, sizeof(float)*(w+2)); for(uint y = 0; y < h; y++) { for(uint x = 0; x < w; x++) { Color32 pixel = image->pixel(x, y); // Add error. int alpha = int(pixel.a) + int(row0[1+x]); // Convert color. if( alpha > alpha_threshold ) pixel.a = 255; else pixel.a = 0; // Store color. image->pixel(x, y) = pixel; // Compute new error. float diff = float(alpha - pixel.a); // Propagate new error. row0[1+x+1] += 7.0f / 16.0f * diff; row1[1+x-1] += 3.0f / 16.0f * diff; row1[1+x+0] += 5.0f / 16.0f * diff; row1[1+x+1] += 1.0f / 16.0f * diff; } swap(row0, row1); memset(row1, 0, sizeof(float)*(w+2)); } delete [] row0; delete [] row1; } // Error diffusion. Floyd Steinberg. void nv::Quantize::FloydSteinberg_Alpha4( Image * image ) { FloydSteinberg(image, 8, 8, 8, 4); } void nv::Quantize::Truncate(Image * image, uint rsize, uint gsize, uint bsize, uint asize) { nvCheck(image != NULL); const uint w = image->width(); const uint h = image->height(); for(uint y = 0; y < h; y++) { for(uint x = 0; x < w; x++) { Color32 pixel = image->pixel(x, y); // Convert to our desired size, and reconstruct. pixel.r = PixelFormat::convert(pixel.r, 8, rsize); pixel.r = PixelFormat::convert(pixel.r, rsize, 8); pixel.g = PixelFormat::convert(pixel.g, 8, gsize); pixel.g = PixelFormat::convert(pixel.g, gsize, 8); pixel.b = PixelFormat::convert(pixel.b, 8, bsize); pixel.b = PixelFormat::convert(pixel.b, bsize, 8); pixel.a = PixelFormat::convert(pixel.a, 8, asize); pixel.a = PixelFormat::convert(pixel.a, asize, 8); // Store color. image->pixel(x, y) = pixel; } } } // Error diffusion. Floyd Steinberg. void nv::Quantize::FloydSteinberg(Image * image, uint rsize, uint gsize, uint bsize, uint asize) { nvCheck(image != NULL); const uint w = image->width(); const uint h = image->height(); Vector4 * row0 = new Vector4[w+2]; Vector4 * row1 = new Vector4[w+2]; memset(row0, 0, sizeof(Vector4)*(w+2)); memset(row1, 0, sizeof(Vector4)*(w+2)); for (uint y = 0; y < h; y++) { for (uint x = 0; x < w; x++) { Color32 pixel = image->pixel(x, y); // Add error. pixel.r = clamp(int(pixel.r) + int(row0[1+x].x()), 0, 255); pixel.g = clamp(int(pixel.g) + int(row0[1+x].y()), 0, 255); pixel.b = clamp(int(pixel.b) + int(row0[1+x].z()), 0, 255); pixel.a = clamp(int(pixel.a) + int(row0[1+x].w()), 0, 255); int r = pixel.r; int g = pixel.g; int b = pixel.b; int a = pixel.a; // Convert to our desired size, and reconstruct. r = PixelFormat::convert(r, 8, rsize); r = PixelFormat::convert(r, rsize, 8); g = PixelFormat::convert(g, 8, gsize); g = PixelFormat::convert(g, gsize, 8); b = PixelFormat::convert(b, 8, bsize); b = PixelFormat::convert(b, bsize, 8); a = PixelFormat::convert(a, 8, asize); a = PixelFormat::convert(a, asize, 8); // Store color. image->pixel(x, y) = Color32(r, g, b, a); // Compute new error. Vector4 diff(float(int(pixel.r) - r), float(int(pixel.g) - g), float(int(pixel.b) - b), float(int(pixel.a) - a)); // Propagate new error. row0[1+x+1] += 7.0f / 16.0f * diff; row1[1+x-1] += 3.0f / 16.0f * diff; row1[1+x+0] += 5.0f / 16.0f * diff; row1[1+x+1] += 1.0f / 16.0f * diff; } swap(row0, row1); memset(row1, 0, sizeof(Vector4)*(w+2)); } delete [] row0; delete [] row1; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/Quantize.h000066400000000000000000000013301173441656100230770ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_QUANTIZE_H #define NV_IMAGE_QUANTIZE_H #include namespace nv { class Image; namespace Quantize { void RGB16(Image * img); void BinaryAlpha(Image * img, int alpha_threshold = 127); void Alpha4(Image * img); void FloydSteinberg_RGB16(Image * img); void FloydSteinberg_BinaryAlpha(Image * img, int alpha_threshold = 127); void FloydSteinberg_Alpha4(Image * img); void Truncate(Image * image, uint rsize, uint gsize, uint bsize, uint asize); void FloydSteinberg(Image * image, uint rsize, uint gsize, uint bsize, uint asize); // @@ Add palette quantization algorithms! } } #endif // NV_IMAGE_QUANTIZE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/TgaFile.h000066400000000000000000000035011173441656100226140ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_TGAFILE_H #define NV_IMAGE_TGAFILE_H #include namespace nv { // TGA types enum TGAType { TGA_TYPE_INDEXED = 1, TGA_TYPE_RGB = 2, TGA_TYPE_GREY = 3, TGA_TYPE_RLE_INDEXED = 9, TGA_TYPE_RLE_RGB = 10, TGA_TYPE_RLE_GREY = 11 }; #define TGA_INTERLEAVE_MASK 0xc0 #define TGA_INTERLEAVE_NONE 0x00 #define TGA_INTERLEAVE_2WAY 0x40 #define TGA_INTERLEAVE_4WAY 0x80 #define TGA_ORIGIN_MASK 0x30 #define TGA_ORIGIN_LEFT 0x00 #define TGA_ORIGIN_RIGHT 0x10 #define TGA_ORIGIN_LOWER 0x00 #define TGA_ORIGIN_UPPER 0x20 #define TGA_HAS_ALPHA 0x0F /// Tga Header. struct TgaHeader { uint8 id_length; uint8 colormap_type; uint8 image_type; uint16 colormap_index; uint16 colormap_length; uint8 colormap_size; uint16 x_origin; uint16 y_origin; uint16 width; uint16 height; uint8 pixel_size; uint8 flags; enum { Size = 18 }; //const static int SIZE = 18; }; /// Tga File. struct TgaFile { TgaFile() { mem = NULL; } ~TgaFile() { free(); } uint size() const { return head.width * head.height * (head.pixel_size / 8); } void allocate() { nvCheck( mem == NULL ); mem = new uint8[size()]; } void free() { delete [] mem; mem = NULL; } TgaHeader head; uint8 * mem; }; inline Stream & operator<< (Stream & s, TgaHeader & head) { s << head.id_length << head.colormap_type << head.image_type; s << head.colormap_index << head.colormap_length << head.colormap_size; s << head.x_origin << head.y_origin << head.width << head.height; s << head.pixel_size << head.flags; return s; } inline Stream & operator<< (Stream & s, TgaFile & tga) { s << tga.head; if( s.isLoading() ) { tga.allocate(); } s.serialize( tga.mem, tga.size() ); return s; } } // nv namespace #endif // NV_IMAGE_TGAFILE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvimage/nvimage.h000066400000000000000000000006341173441656100227330ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_IMAGE_H #define NV_IMAGE_H #include // Function linkage #if NVIMAGE_SHARED #ifdef NVIMAGE_EXPORTS #define NVIMAGE_API DLL_EXPORT #define NVIMAGE_CLASS DLL_EXPORT_CLASS #else #define NVIMAGE_API DLL_IMPORT #define NVIMAGE_CLASS DLL_IMPORT #endif #else #define NVIMAGE_API #define NVIMAGE_CLASS #endif #endif // NV_IMAGE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/000077500000000000000000000000001173441656100210005ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Basis.cpp000066400000000000000000000105051173441656100225460ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include using namespace nv; /// Normalize basis vectors. void Basis::normalize(float epsilon /*= NV_EPSILON*/) { normal = ::normalize(normal, epsilon); tangent = ::normalize(tangent, epsilon); bitangent = ::normalize(bitangent, epsilon); } /// Gram-Schmidt orthogonalization. /// @note Works only if the vectors are close to orthogonal. void Basis::orthonormalize(float epsilon /*= NV_EPSILON*/) { // N' = |N| // T' = |T - (N' dot T) N'| // B' = |B - (N' dot B) N' - (T' dot B) T'| normal = ::normalize(normal, epsilon); tangent -= normal * dot(normal, tangent); tangent = ::normalize(tangent, epsilon); bitangent -= normal * dot(normal, bitangent); bitangent -= tangent * dot(tangent, bitangent); bitangent = ::normalize(bitangent, epsilon); } /// Robust orthonormalization. /// Returns an orthonormal basis even when the original is degenerate. void Basis::robustOrthonormalize(float epsilon /*= NV_EPSILON*/) { if (length(normal) < epsilon) { normal = cross(tangent, bitangent); if (length(normal) < epsilon) { tangent = Vector3(1, 0, 0); bitangent = Vector3(0, 1, 0); normal = Vector3(0, 0, 1); return; } } normal = ::normalize(normal, epsilon); tangent -= normal * dot(normal, tangent); bitangent -= normal * dot(normal, bitangent); if (length(tangent) < epsilon) { if (length(bitangent) < epsilon) { buildFrameForDirection(normal); } else { tangent = cross(bitangent, normal); nvCheck(isNormalized(tangent, epsilon)); } } else { tangent = ::normalize(tangent, epsilon); bitangent -= tangent * dot(tangent, bitangent); if (length(bitangent) < epsilon) { bitangent = cross(tangent, normal); nvCheck(isNormalized(bitangent)); } else { tangent = ::normalize(tangent, epsilon); } } // Check vector lengths. nvCheck(isNormalized(normal, epsilon)); nvCheck(isNormalized(tangent, epsilon)); nvCheck(isNormalized(bitangent, epsilon)); // Check vector angles. nvCheck(equal(dot(normal, tangent), 0.0f, epsilon)); nvCheck(equal(dot(normal, bitangent), 0.0f, epsilon)); nvCheck(equal(dot(tangent, bitangent), 0.0f, epsilon)); // Check vector orientation. const float det = dot(cross(normal, tangent), bitangent); nvCheck(equal(det, 1.0f, epsilon) || equal(det, -1.0f, epsilon)); } /// Build an arbitrary frame for the given direction. void Basis::buildFrameForDirection(Vector3::Arg d) { nvCheck(isNormalized(d)); normal = d; // Choose minimum axis. if (fabsf(normal.x()) < fabsf(normal.y()) && fabsf(normal.x()) < fabsf(normal.z())) { tangent = Vector3(1, 0, 0); } else if (fabsf(normal.y()) < fabsf(normal.z())) { tangent = Vector3(0, 1, 0); } else { tangent = Vector3(0, 0, 1); } // Ortogonalize tangent -= normal * dot(normal, tangent); tangent = ::normalize(tangent); bitangent = cross(normal, tangent); } /* /// Transform by this basis. (From this basis to object space). Vector3 Basis::transform(Vector3::Arg v) const { Vector3 o = tangent * v.x(); o += bitangent * v.y(); o += normal * v.z(); return o; } /// Transform by the transpose. (From object space to this basis). Vector3 Basis::transformT(Vector3::Arg v) { return Vector3(dot(tangent, v), dot(bitangent, v), dot(normal, v)); } /// Transform by the inverse. (From object space to this basis). /// @note Uses Kramer's rule so the inverse is not accurate if the basis is ill-conditioned. Vector3 Basis::transformI(Vector3::Arg v) const { const float det = determinant(); nvCheck(!equalf(det, 0.0f)); const float idet = 1.0f / det; // Rows of the inverse matrix. Vector3 r0, r1, r2; r0.x = (bitangent.y() * normal.z() - bitangent.z() * normal.y()) * idet; r0.y = -(bitangent.x() * normal.z() - bitangent.z() * normal.x()) * idet; r0.z = (bitangent.x() * normal.y() - bitangent.y() * normal.x()) * idet; r1.x = -(tangent.y() * normal.z() - tangent.z() * normal.y()) * idet; r1.y = (tangent.x() * normal.z() - tangent.z() * normal.x()) * idet; r1.z = -(tangent.x() * normal.y() - tangent.y() * normal.x()) * idet; r2.x = (tangent.y() * bitangent.z() - tangent.z() * bitangent.y()) * idet; r2.y = -(tangent.x() * bitangent.z() - tangent.z() * bitangent.x()) * idet; r2.z = (tangent.x() * bitangent.y() - tangent.y() * bitangent.x()) * idet; return Vector3(dot(v, r0), dot(v, r1), dot(v, r2)); } */ nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Basis.h000066400000000000000000000043221173441656100222130ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_BASIS_H #define NV_MATH_BASIS_H #include #include #include namespace nv { /// Basis class to compute tangent space basis, ortogonalizations and to /// transform vectors from one space to another. struct Basis { /// Create a null basis. Basis() : tangent(0, 0, 0), bitangent(0, 0, 0), normal(0, 0, 0) {} /// Create a basis given three vectors. Basis(Vector3::Arg n, Vector3::Arg t, Vector3::Arg b) : tangent(t), bitangent(b), normal(n) {} /// Create a basis with the given tangent vectors and the handness. Basis(Vector3::Arg n, Vector3::Arg t, float sign) { build(n, t, sign); } NVMATH_API void normalize(float epsilon = NV_EPSILON); NVMATH_API void orthonormalize(float epsilon = NV_EPSILON); NVMATH_API void robustOrthonormalize(float epsilon = NV_EPSILON); NVMATH_API void buildFrameForDirection(Vector3::Arg d); /// Calculate the determinant [ F G N ] to obtain the handness of the basis. float handness() const { return determinant() > 0.0f ? 1.0f : -1.0f; } /// Build a basis from 2 vectors and a handness flag. void build(Vector3::Arg n, Vector3::Arg t, float sign) { normal = n; tangent = t; bitangent = sign * cross(t, n); } /// Compute the determinant of this basis. float determinant() const { return tangent.x() * bitangent.y() * normal.z() - tangent.z() * bitangent.y() * normal.x() + tangent.y() * bitangent.z() * normal.x() - tangent.y() * bitangent.x() * normal.z() + tangent.z() * bitangent.x() * normal.y() - tangent.x() * bitangent.z() * normal.y(); } /* // Get transform matrix for this basis. NVMATH_API Matrix matrix() const; // Transform by this basis. (From this basis to object space). NVMATH_API Vector3 transform(Vector3::Arg v) const; // Transform by the transpose. (From object space to this basis). NVMATH_API Vector3 transformT(Vector3::Arg v); // Transform by the inverse. (From object space to this basis). NVMATH_API Vector3 transformI(Vector3::Arg v) const; */ Vector3 tangent; Vector3 bitangent; Vector3 normal; }; } // nv namespace #endif // NV_MATH_BASIS_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Box.h000066400000000000000000000052141173441656100217030ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_BOX_H #define NV_MATH_BOX_H #include #include // FLT_MAX namespace nv { /// Axis Aligned Bounding Box. class Box { public: /// Default ctor. Box() { }; /// Copy ctor. Box( const Box & b ) : m_mins(b.m_mins), m_maxs(b.m_maxs) { } /// Init ctor. Box( Vector3::Arg mins, Vector3::Arg maxs ) : m_mins(mins), m_maxs(maxs) { } // Cast operators. operator const float * () const { return reinterpret_cast(this); } /// Min corner of the box. Vector3 mins() const { return m_mins; } /// Max corner of the box. Vector3 maxs() const { return m_maxs; } /// Clear the bounds. void clearBounds() { m_mins.set(FLT_MAX, FLT_MAX, FLT_MAX); m_maxs.set(-FLT_MAX, -FLT_MAX, -FLT_MAX); } /// Build a cube centered on center and with edge = 2*dist void cube(Vector3::Arg center, float dist) { setCenterExtents(center, Vector3(dist, dist, dist)); } /// Build a box, given center and extents. void setCenterExtents(Vector3::Arg center, Vector3::Arg extents) { m_mins = center - extents; m_maxs = center + extents; } /// Get box center. Vector3 center() const { return (m_mins + m_maxs) * 0.5f; } /// Return extents of the box. Vector3 extents() const { return (m_maxs - m_mins) * 0.5f; } /// Return extents of the box. scalar extents(uint axis) const { nvDebugCheck(axis < 3); if (axis == 0) return (m_maxs.x() - m_mins.x()) * 0.5f; if (axis == 1) return (m_maxs.y() - m_mins.y()) * 0.5f; if (axis == 2) return (m_maxs.z() - m_mins.z()) * 0.5f; nvAssume(false); return 0.0f; } /// Add a point to this box. void addPointToBounds(Vector3::Arg p) { m_mins = min(m_mins, p); m_maxs = max(m_maxs, p); } /// Add a box to this box. void addBoxToBounds(const Box & b) { m_mins = min(m_mins, b.m_mins); m_maxs = max(m_maxs, b.m_maxs); } /// Translate box. void translate(Vector3::Arg v) { m_mins += v; m_maxs += v; } /// Scale the box. void scale(float s) { m_mins *= s; m_maxs *= s; } /// Get the area of the box. float area() const { const Vector3 d = extents(); return 8.0f * (d.x()*d.y() + d.x()*d.z() + d.y()*d.z()); } /// Get the volume of the box. float volume() const { Vector3 d = extents(); return 8.0f * (d.x() * d.y() * d.z()); } /// Return true if the box contains the given point. bool contains(Vector3::Arg p) const { return m_mins.x() < p.x() && m_mins.y() < p.y() && m_mins.z() < p.z() && m_maxs.x() > p.x() && m_maxs.y() > p.y() && m_maxs.z() > p.z(); } private: Vector3 m_mins; Vector3 m_maxs; }; } // nv namespace #endif // NV_MATH_BOX_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/CMakeLists.txt000066400000000000000000000012231173441656100235360ustar00rootroot00000000000000PROJECT(nvmath) SET(MATH_SRCS nvmath.h Vector.h Matrix.h Quaternion.h Box.h Color.h Montecarlo.h Montecarlo.cpp Random.h Random.cpp SphericalHarmonic.h SphericalHarmonic.cpp Basis.h Basis.cpp Triangle.h Triangle.cpp TriBox.cpp) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) # targets ADD_DEFINITIONS(-DNVMATH_EXPORTS) IF(NVMATH_SHARED) ADD_DEFINITIONS(-DNVMATH_SHARED=1) ADD_LIBRARY(nvmath SHARED ${MATH_SRCS}) ELSE(NVMATH_SHARED) ADD_LIBRARY(nvmath ${MATH_SRCS}) ENDIF(NVMATH_SHARED) TARGET_LINK_LIBRARIES(nvmath ${LIBS} nvcore) INSTALL(TARGETS nvmath RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib/static) nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Color.h000066400000000000000000000065011173441656100222310ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_COLOR_H #define NV_MATH_COLOR_H #include #include namespace nv { /// 64 bit color stored as BGRA. class NVMATH_CLASS Color64 { public: Color64() { } Color64(const Color64 & c) : u(c.u) { } Color64(uint16 R, uint16 G, uint16 B, uint16 A) { setRGBA(R, G, B, A); } explicit Color64(uint64 U) : u(U) { } void setRGBA(uint16 R, uint16 G, uint16 B, uint16 A) { r = R; g = G; b = B; a = A; } operator uint64 () const { return u; } union { struct { #if NV_LITTLE_ENDIAN uint16 r, a, b, g; #else uint16 a: 16; uint16 r: 16; uint16 g: 16; uint16 b: 16; #endif }; uint64 u; }; }; /// 32 bit color stored as BGRA. class NVMATH_CLASS Color32 { public: Color32() { } Color32(const Color32 & c) : u(c.u) { } Color32(uint8 R, uint8 G, uint8 B) { setRGBA(R, G, B, 0xFF); } Color32(uint8 R, uint8 G, uint8 B, uint8 A) { setRGBA( R, G, B, A); } //Color32(uint8 c[4]) { setRGBA(c[0], c[1], c[2], c[3]); } //Color32(float R, float G, float B) { setRGBA(uint(R*255), uint(G*255), uint(B*255), 0xFF); } //Color32(float R, float G, float B, float A) { setRGBA(uint(R*255), uint(G*255), uint(B*255), uint(A*255)); } explicit Color32(uint32 U) : u(U) { } void setRGBA(uint8 R, uint8 G, uint8 B, uint8 A) { r = R; g = G; b = B; a = A; } void setBGRA(uint8 B, uint8 G, uint8 R, uint8 A = 0xFF) { r = R; g = G; b = B; a = A; } operator uint32 () const { return u; } union { struct { #if NV_LITTLE_ENDIAN uint8 b, g, r, a; #else uint8 a: 8; uint8 r: 8; uint8 g: 8; uint8 b: 8; #endif }; uint32 u; }; }; /// 16 bit 565 BGR color. class NVMATH_CLASS Color16 { public: Color16() { } Color16(const Color16 & c) : u(c.u) { } explicit Color16(uint16 U) : u(U) { } union { struct { #if NV_LITTLE_ENDIAN uint16 b : 5; uint16 g : 6; uint16 r : 5; #else uint16 r : 5; uint16 g : 6; uint16 b : 5; #endif }; uint16 u; }; }; /// Clamp color components. inline Vector3 colorClamp(Vector3::Arg c) { return Vector3(clamp(c.x(), 0.0f, 1.0f), clamp(c.y(), 0.0f, 1.0f), clamp(c.z(), 0.0f, 1.0f)); } /// Clamp without allowing the hue to change. inline Vector3 colorNormalize(Vector3::Arg c) { float scale = 1.0f; if (c.x() > scale) scale = c.x(); if (c.y() > scale) scale = c.y(); if (c.z() > scale) scale = c.z(); return c / scale; } /// Convert Color32 to Color16. inline Color16 toColor16(Color32 c) { Color16 color; // rrrrrggggggbbbbb // rrrrr000gggggg00bbbbb000 // color.u = (c.u >> 3) & 0x1F; // color.u |= (c.u >> 5) & 0x7E0; // color.u |= (c.u >> 8) & 0xF800; color.r = c.r >> 3; color.g = c.g >> 2; color.b = c.b >> 3; return color; } /// Promote 16 bit color to 32 bit using regular bit expansion. inline Color32 toColor32(Color16 c) { Color32 color; // c.u = ((col0.u << 3) & 0xf8) | ((col0.u << 5) & 0xfc00) | ((col0.u << 8) & 0xf80000); // c.u |= (c.u >> 5) & 0x070007; // c.u |= (c.u >> 6) & 0x000300; color.b = (c.b << 3) | (c.b >> 2); color.g = (c.g << 2) | (c.g >> 4); color.r = (c.r << 3) | (c.r >> 2); color.a = 0xFF; return color; } inline Vector4 toVector4(Color32 c) { const float scale = 1.0f / 255.0f; return Vector4(c.r * scale, c.g * scale, c.b * scale, c.a * scale); } } // nv namespace #endif // NV_MATH_COLOR_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Matrix.h000066400000000000000000001015711173441656100224220ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_MATRIX_H #define NV_MATH_MATRIX_H #include #include namespace nv { // @@ Use scalar defined in Vector.h, but should use a template instead. /// 4x4 transformation matrix. /// -# Matrices are stored in memory in column major order. /// -# Points are to be though of as column vectors. /// -# Transformation of a point p by a matrix M is: p' = M * p class NVMATH_CLASS Matrix { public: typedef Matrix const & Arg; Matrix(); Matrix(zero_t); Matrix(identity_t); Matrix(const Matrix & m); scalar data(uint idx) const; scalar & data(uint idx); scalar get(uint row, uint col) const; scalar operator()(uint row, uint col) const; scalar & operator()(uint row, uint col); const scalar * ptr() const; Vector4 row(uint i) const; Vector4 column(uint i) const; void scale(scalar s); void scale(Vector3::Arg s); void translate(Vector3::Arg t); void rotate(scalar theta, scalar v0, scalar v1, scalar v2); scalar determinant() const; void apply(Matrix::Arg m); private: scalar m_data[16]; }; inline Matrix::Matrix() { } inline Matrix::Matrix(zero_t) { for(int i = 0; i < 16; i++) { m_data[i] = 0.0f; } } inline Matrix::Matrix(identity_t) { for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { m_data[4*j+i] = (i == j) ? 1.0f : 0.0f; } } } inline Matrix::Matrix(const Matrix & m) { for(int i = 0; i < 16; i++) { m_data[i] = m.m_data[i]; } } // Accessors inline scalar Matrix::data(uint idx) const { nvDebugCheck(idx < 16); return m_data[idx]; } inline scalar & Matrix::data(uint idx) { nvDebugCheck(idx < 16); return m_data[idx]; } inline scalar Matrix::get(uint row, uint col) const { nvDebugCheck(row < 4 && col < 4); return m_data[col * 4 + row]; } inline scalar Matrix::operator()(uint row, uint col) const { nvDebugCheck(row < 4 && col < 4); return m_data[col * 4 + row]; } inline scalar & Matrix::operator()(uint row, uint col) { nvDebugCheck(row < 4 && col < 4); return m_data[col * 4 + row]; } inline const scalar * Matrix::ptr() const { return m_data; } inline Vector4 Matrix::row(uint i) const { nvDebugCheck(i < 4); return Vector4(get(i, 0), get(i, 1), get(i, 2), get(i, 3)); } inline Vector4 Matrix::column(uint i) const { nvDebugCheck(i < 4); return Vector4(get(0, i), get(1, i), get(2, i), get(3, i)); } /// Apply scale. inline void Matrix::scale(scalar s) { m_data[0] *= s; m_data[1] *= s; m_data[2] *= s; m_data[3] *= s; m_data[4] *= s; m_data[5] *= s; m_data[6] *= s; m_data[7] *= s; m_data[8] *= s; m_data[9] *= s; m_data[10] *= s; m_data[11] *= s; m_data[12] *= s; m_data[13] *= s; m_data[14] *= s; m_data[15] *= s; } /// Apply scale. inline void Matrix::scale(Vector3::Arg s) { m_data[0] *= s.x(); m_data[1] *= s.x(); m_data[2] *= s.x(); m_data[3] *= s.x(); m_data[4] *= s.y(); m_data[5] *= s.y(); m_data[6] *= s.y(); m_data[7] *= s.y(); m_data[8] *= s.z(); m_data[9] *= s.z(); m_data[10] *= s.z(); m_data[11] *= s.z(); } /// Apply translation. inline void Matrix::translate(Vector3::Arg t) { m_data[12] = m_data[0] * t.x() + m_data[4] * t.y() + m_data[8] * t.z() + m_data[12]; m_data[13] = m_data[1] * t.x() + m_data[5] * t.y() + m_data[9] * t.z() + m_data[13]; m_data[14] = m_data[2] * t.x() + m_data[6] * t.y() + m_data[10] * t.z() + m_data[14]; m_data[15] = m_data[3] * t.x() + m_data[7] * t.y() + m_data[11] * t.z() + m_data[15]; } Matrix rotation(scalar theta, scalar v0, scalar v1, scalar v2); /// Apply rotation. inline void Matrix::rotate(scalar theta, scalar v0, scalar v1, scalar v2) { Matrix R(rotation(theta, v0, v1, v2)); apply(R); } /// Apply transform. inline void Matrix::apply(Matrix::Arg m) { nvDebugCheck(this != &m); for(int i = 0; i < 4; i++) { const scalar ai0 = get(i,0), ai1 = get(i,1), ai2 = get(i,2), ai3 = get(i,3); m_data[0 + i] = ai0 * m(0,0) + ai1 * m(1,0) + ai2 * m(2,0) + ai3 * m(3,0); m_data[4 + i] = ai0 * m(0,1) + ai1 * m(1,1) + ai2 * m(2,1) + ai3 * m(3,1); m_data[8 + i] = ai0 * m(0,2) + ai1 * m(1,2) + ai2 * m(2,2) + ai3 * m(3,2); m_data[12+ i] = ai0 * m(0,3) + ai1 * m(1,3) + ai2 * m(2,3) + ai3 * m(3,3); } } /// Get scale matrix. inline Matrix scale(Vector3::Arg s) { Matrix m(identity); m(0,0) = s.x(); m(1,1) = s.y(); m(2,2) = s.z(); return m; } /// Get scale matrix. inline Matrix scale(scalar s) { Matrix m(identity); m(0,0) = m(1,1) = m(2,2) = s; return m; } /// Get translation matrix. inline Matrix translation(Vector3::Arg t) { Matrix m(identity); m(0,3) = t.x(); m(1,3) = t.y(); m(2,3) = t.z(); return m; } /// Get rotation matrix. inline Matrix rotation(scalar theta, scalar v0, scalar v1, scalar v2) { scalar cost = cosf(theta); scalar sint = sinf(theta); Matrix m(identity); if( 1 == v0 && 0 == v1 && 0 == v2 ) { m(1,1) = cost; m(2,1) = -sint; m(1,2) = sint; m(2,2) = cost; } else if( 0 == v0 && 1 == v1 && 0 == v2 ) { m(0,0) = cost; m(2,0) = sint; m(1,2) = -sint; m(2,2) = cost; } else if( 0 == v0 && 0 == v1 && 1 == v2 ) { m(0,0) = cost; m(1,0) = -sint; m(0,1) = sint; m(1,1) = cost; } else { scalar a2, b2, c2; a2 = v0 * v0; b2 = v1 * v1; c2 = v2 * v2; scalar iscale = 1.0f / sqrtf(a2 + b2 + c2); v0 *= iscale; v1 *= iscale; v2 *= iscale; scalar abm, acm, bcm; scalar mcos, asin, bsin, csin; mcos = 1.0f - cost; abm = v0 * v1 * mcos; acm = v0 * v2 * mcos; bcm = v1 * v2 * mcos; asin = v0 * sint; bsin = v1 * sint; csin = v2 * sint; m(0,0) = a2 * mcos + cost; m(1,0) = abm - csin; m(2,0) = acm + bsin; m(3,0) = abm + csin; m(1,1) = b2 * mcos + cost; m(2,1) = bcm - asin; m(3,1) = acm - bsin; m(1,2) = bcm + asin; m(2,2) = c2 * mcos + cost; } return m; } //Matrix rotation(scalar yaw, scalar pitch, scalar roll); //Matrix skew(scalar angle, Vector3::Arg v1, Vector3::Arg v2); /// Get frustum matrix. inline Matrix frustum(scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear, scalar zFar) { Matrix m(zero); scalar doubleznear = 2.0f * zNear; scalar one_deltax = 1.0f / (xmax - xmin); scalar one_deltay = 1.0f / (ymax - ymin); scalar one_deltaz = 1.0f / (zFar - zNear); m(0,0) = doubleznear * one_deltax; m(1,1) = doubleznear * one_deltay; m(0,2) = (xmax + xmin) * one_deltax; m(1,2) = (ymax + ymin) * one_deltay; m(2,2) = -(zFar + zNear) * one_deltaz; m(3,2) = -1.0f; m(2,3) = -(zFar * doubleznear) * one_deltaz; return m; } /// Get infinite frustum matrix. inline Matrix frustum(scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear) { Matrix m(zero); scalar doubleznear = 2.0f * zNear; scalar one_deltax = 1.0f / (xmax - xmin); scalar one_deltay = 1.0f / (ymax - ymin); scalar nudge = 1.0; // 0.999; m(0,0) = doubleznear * one_deltax; m(1,1) = doubleznear * one_deltay; m(0,2) = (xmax + xmin) * one_deltax; m(1,2) = (ymax + ymin) * one_deltay; m(2,2) = -1.0f * nudge; m(3,2) = -1.0f; m(2,3) = -doubleznear * nudge; return m; } /// Get perspective matrix. inline Matrix perspective(scalar fovy, scalar aspect, scalar zNear, scalar zFar) { scalar xmax = zNear * tan(fovy / 2); scalar xmin = -xmax; scalar ymax = xmax / aspect; scalar ymin = -ymax; return frustum(xmin, xmax, ymin, ymax, zNear, zFar); } /// Get infinite perspective matrix. inline Matrix perspective(scalar fovy, scalar aspect, scalar zNear) { scalar x = zNear * tan(fovy / 2); scalar y = x / aspect; return frustum( -x, x, -y, y, zNear ); } /// Get matrix determinant. inline scalar Matrix::determinant() const { return m_data[3] * m_data[6] * m_data[ 9] * m_data[12] - m_data[2] * m_data[7] * m_data[ 9] * m_data[12] - m_data[3] * m_data[5] * m_data[10] * m_data[12] + m_data[1] * m_data[7] * m_data[10] * m_data[12] + m_data[2] * m_data[5] * m_data[11] * m_data[12] - m_data[1] * m_data[6] * m_data[11] * m_data[12] - m_data[3] * m_data[6] * m_data[ 8] * m_data[13] + m_data[2] * m_data[7] * m_data[ 8] * m_data[13] + m_data[3] * m_data[4] * m_data[10] * m_data[13] - m_data[0] * m_data[7] * m_data[10] * m_data[13] - m_data[2] * m_data[4] * m_data[11] * m_data[13] + m_data[0] * m_data[6] * m_data[11] * m_data[13] + m_data[3] * m_data[5] * m_data[ 8] * m_data[14] - m_data[1] * m_data[7] * m_data[ 8] * m_data[14] - m_data[3] * m_data[4] * m_data[ 9] * m_data[14] + m_data[0] * m_data[7] * m_data[ 9] * m_data[14] + m_data[1] * m_data[4] * m_data[11] * m_data[14] - m_data[0] * m_data[5] * m_data[11] * m_data[14] - m_data[2] * m_data[5] * m_data[ 8] * m_data[15] + m_data[1] * m_data[6] * m_data[ 8] * m_data[15] + m_data[2] * m_data[4] * m_data[ 9] * m_data[15] - m_data[0] * m_data[6] * m_data[ 9] * m_data[15] - m_data[1] * m_data[4] * m_data[10] * m_data[15] + m_data[0] * m_data[5] * m_data[10] * m_data[15]; } inline Matrix transpose(Matrix::Arg m) { Matrix r; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { r(i, j) = m(j, i); } } return r; } inline Matrix inverse(Matrix::Arg m) { Matrix r; r.data( 0) = m.data(6)*m.data(11)*m.data(13) - m.data(7)*m.data(10)*m.data(13) + m.data(7)*m.data(9)*m.data(14) - m.data(5)*m.data(11)*m.data(14) - m.data(6)*m.data(9)*m.data(15) + m.data(5)*m.data(10)*m.data(15); r.data( 1) = m.data(3)*m.data(10)*m.data(13) - m.data(2)*m.data(11)*m.data(13) - m.data(3)*m.data(9)*m.data(14) + m.data(1)*m.data(11)*m.data(14) + m.data(2)*m.data(9)*m.data(15) - m.data(1)*m.data(10)*m.data(15); r.data( 2) = m.data(2)*m.data( 7)*m.data(13) - m.data(3)*m.data( 6)*m.data(13) + m.data(3)*m.data(5)*m.data(14) - m.data(1)*m.data( 7)*m.data(14) - m.data(2)*m.data(5)*m.data(15) + m.data(1)*m.data( 6)*m.data(15); r.data( 3) = m.data(3)*m.data( 6)*m.data( 9) - m.data(2)*m.data( 7)*m.data( 9) - m.data(3)*m.data(5)*m.data(10) + m.data(1)*m.data( 7)*m.data(10) + m.data(2)*m.data(5)*m.data(11) - m.data(1)*m.data( 6)*m.data(11); r.data( 4) = m.data(7)*m.data(10)*m.data(12) - m.data(6)*m.data(11)*m.data(12) - m.data(7)*m.data(8)*m.data(14) + m.data(4)*m.data(11)*m.data(14) + m.data(6)*m.data(8)*m.data(15) - m.data(4)*m.data(10)*m.data(15); r.data( 5) = m.data(2)*m.data(11)*m.data(12) - m.data(3)*m.data(10)*m.data(12) + m.data(3)*m.data(8)*m.data(14) - m.data(0)*m.data(11)*m.data(14) - m.data(2)*m.data(8)*m.data(15) + m.data(0)*m.data(10)*m.data(15); r.data( 6) = m.data(3)*m.data( 6)*m.data(12) - m.data(2)*m.data( 7)*m.data(12) - m.data(3)*m.data(4)*m.data(14) + m.data(0)*m.data( 7)*m.data(14) + m.data(2)*m.data(4)*m.data(15) - m.data(0)*m.data( 6)*m.data(15); r.data( 7) = m.data(2)*m.data( 7)*m.data( 8) - m.data(3)*m.data( 6)*m.data( 8) + m.data(3)*m.data(4)*m.data(10) - m.data(0)*m.data( 7)*m.data(10) - m.data(2)*m.data(4)*m.data(11) + m.data(0)*m.data( 6)*m.data(11); r.data( 8) = m.data(5)*m.data(11)*m.data(12) - m.data(7)*m.data( 9)*m.data(12) + m.data(7)*m.data(8)*m.data(13) - m.data(4)*m.data(11)*m.data(13) - m.data(5)*m.data(8)*m.data(15) + m.data(4)*m.data( 9)*m.data(15); r.data( 9) = m.data(3)*m.data( 9)*m.data(12) - m.data(1)*m.data(11)*m.data(12) - m.data(3)*m.data(8)*m.data(13) + m.data(0)*m.data(11)*m.data(13) + m.data(1)*m.data(8)*m.data(15) - m.data(0)*m.data( 9)*m.data(15); r.data(10) = m.data(1)*m.data( 7)*m.data(12) - m.data(3)*m.data( 5)*m.data(12) + m.data(3)*m.data(4)*m.data(13) - m.data(0)*m.data( 7)*m.data(13) - m.data(1)*m.data(4)*m.data(15) + m.data(0)*m.data( 5)*m.data(15); r.data(11) = m.data(3)*m.data( 5)*m.data( 8) - m.data(1)*m.data( 7)*m.data( 8) - m.data(3)*m.data(4)*m.data( 9) + m.data(0)*m.data( 7)*m.data( 9) + m.data(1)*m.data(4)*m.data(11) - m.data(0)*m.data( 5)*m.data(11); r.data(12) = m.data(6)*m.data( 9)*m.data(12) - m.data(5)*m.data(10)*m.data(12) - m.data(6)*m.data(8)*m.data(13) + m.data(4)*m.data(10)*m.data(13) + m.data(5)*m.data(8)*m.data(14) - m.data(4)*m.data( 9)*m.data(14); r.data(13) = m.data(1)*m.data(10)*m.data(12) - m.data(2)*m.data( 9)*m.data(12) + m.data(2)*m.data(8)*m.data(13) - m.data(0)*m.data(10)*m.data(13) - m.data(1)*m.data(8)*m.data(14) + m.data(0)*m.data( 9)*m.data(14); r.data(14) = m.data(2)*m.data( 5)*m.data(12) - m.data(1)*m.data( 6)*m.data(12) - m.data(2)*m.data(4)*m.data(13) + m.data(0)*m.data( 6)*m.data(13) + m.data(1)*m.data(4)*m.data(14) - m.data(0)*m.data( 5)*m.data(14); r.data(15) = m.data(1)*m.data( 6)*m.data( 8) - m.data(2)*m.data( 5)*m.data( 8) + m.data(2)*m.data(4)*m.data( 9) - m.data(0)*m.data( 6)*m.data( 9) - m.data(1)*m.data(4)*m.data(10) + m.data(0)*m.data( 5)*m.data(10); r.scale(1.0f / m.determinant()); return r; } inline Matrix isometryInverse(Matrix::Arg m) { Matrix r(identity); // transposed 3x3 upper left matrix for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { r(i, j) = m(j, i); } } // translate by the negative offsets r.translate(-Vector3(m.data(12), m.data(13), m.data(14))); return r; } //Matrix affineInverse(Matrix::Arg m); /// Transform the given 3d point with the given matrix. inline Vector3 transformPoint(Matrix::Arg m, Vector3::Arg p) { return Vector3( p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2) + m(0,3), p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2) + m(1,3), p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2) + m(2,3)); } /// Transform the given 3d vector with the given matrix. inline Vector3 transformVector(Matrix::Arg m, Vector3::Arg p) { return Vector3( p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2), p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2), p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2)); } /// Transform the given 4d vector with the given matrix. inline Vector4 transform(Matrix::Arg m, Vector4::Arg p) { return Vector4( p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2) + p.w() * m(0,3), p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2) + p.w() * m(1,3), p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2) + p.w() * m(2,3), p.x() * m(3,0) + p.y() * m(3,1) + p.z() * m(3,2) + p.w() * m(3,3)); } inline Matrix mul(Matrix::Arg a, Matrix::Arg b) { // @@ Is this the right order? mul(a, b) = b * a Matrix m = a; m.apply(b); return m; } } // nv namespace #if 0 /** @name Special matrices. */ //@{ /** Generate a translation matrix. */ void TranslationMatrix(const Vec3 & v) { data[0] = 1; data[1] = 0; data[2] = 0; data[3] = 0; data[4] = 0; data[5] = 1; data[6] = 0; data[7] = 0; data[8] = 0; data[9] = 0; data[10] = 1; data[11] = 0; data[12] = v.x; data[13] = v.y; data[14] = v.z; data[15] = 1; } /** Rotate theta degrees around v. */ void RotationMatrix( scalar theta, scalar v0, scalar v1, scalar v2 ) { scalar cost = cos(theta); scalar sint = sin(theta); if( 1 == v0 && 0 == v1 && 0 == v2 ) { data[0] = 1.0f; data[1] = 0.0f; data[2] = 0.0f; data[3] = 0.0f; data[4] = 0.0f; data[5] = cost; data[6] = -sint;data[7] = 0.0f; data[8] = 0.0f; data[9] = sint; data[10] = cost;data[11] = 0.0f; data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; } else if( 0 == v0 && 1 == v1 && 0 == v2 ) { data[0] = cost; data[1] = 0.0f; data[2] = sint; data[3] = 0.0f; data[4] = 0.0f; data[5] = 1.0f; data[6] = 0.0f; data[7] = 0.0f; data[8] = -sint;data[9] = 0.0f;data[10] = cost; data[11] = 0.0f; data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; } else if( 0 == v0 && 0 == v1 && 1 == v2 ) { data[0] = cost; data[1] = -sint;data[2] = 0.0f; data[3] = 0.0f; data[4] = sint; data[5] = cost; data[6] = 0.0f; data[7] = 0.0f; data[8] = 0.0f; data[9] = 0.0f; data[10] = 1.0f;data[11] = 0.0f; data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; } else { //we need scale a,b,c to unit length. scalar a2, b2, c2; a2 = v0 * v0; b2 = v1 * v1; c2 = v2 * v2; scalar iscale = 1.0f / sqrtf(a2 + b2 + c2); v0 *= iscale; v1 *= iscale; v2 *= iscale; scalar abm, acm, bcm; scalar mcos, asin, bsin, csin; mcos = 1.0f - cost; abm = v0 * v1 * mcos; acm = v0 * v2 * mcos; bcm = v1 * v2 * mcos; asin = v0 * sint; bsin = v1 * sint; csin = v2 * sint; data[0] = a2 * mcos + cost; data[1] = abm - csin; data[2] = acm + bsin; data[3] = abm + csin; data[4] = 0.0f; data[5] = b2 * mcos + cost; data[6] = bcm - asin; data[7] = acm - bsin; data[8] = 0.0f; data[9] = bcm + asin; data[10] = c2 * mcos + cost; data[11] = 0.0f; data[12] = 0.0f; data[13] = 0.0f; data[14] = 0.0f; data[15] = 1.0f; } } /* void SkewMatrix(scalar angle, const Vec3 & v1, const Vec3 & v2) { v1.Normalize(); v2.Normalize(); Vec3 v3; v3.Cross(v1, v2); v3.Normalize(); // Get skew factor. scalar costheta = Vec3DotProduct(v1, v2); scalar sintheta = Real.Sqrt(1 - costheta * costheta); scalar skew = tan(Trig.DegreesToRadians(angle) + acos(sintheta)) * sintheta - costheta; // Build orthonormal matrix. v1 = FXVector3.Cross(v3, v2); v1.Normalize(); Matrix R = Matrix::Identity; R[0, 0] = v3.X; // Not sure this is in the correct order... R[1, 0] = v3.Y; R[2, 0] = v3.Z; R[0, 1] = v1.X; R[1, 1] = v1.Y; R[2, 1] = v1.Z; R[0, 2] = v2.X; R[1, 2] = v2.Y; R[2, 2] = v2.Z; // Build skew matrix. Matrix S = Matrix::Identity; S[2, 1] = -skew; // Return skew transform. return R * S * R.Transpose; // Not sure this is in the correct order... } */ /** * Generate rotation matrix for the euler angles. This is the same as computing * 3 rotation matrices and multiplying them together in our custom order. * * @todo Have to recompute this code for our new convention. **/ void RotationMatrix( scalar yaw, scalar pitch, scalar roll ) { scalar sy = sin(yaw+ToRadian(90)); scalar cy = cos(yaw+ToRadian(90)); scalar sp = sin(pitch-ToRadian(90)); scalar cp = cos(pitch-ToRadian(90)); scalar sr = sin(roll); scalar cr = cos(roll); data[0] = cr*cy + sr*sp*sy; data[1] = cp*sy; data[2] = -sr*cy + cr*sp*sy; data[3] = 0; data[4] = -cr*sy + sr*sp*cy; data[5] = cp*cy; data[6] = sr*sy + cr*sp*cy; data[7] = 0; data[8] = sr*cp; data[9] = -sp; data[10] = cr*cp; data[11] = 0; data[12] = 0; data[13] = 0; data[14] = 0; data[15] = 1; } /** Create a frustum matrix with the far plane at the infinity. */ void Frustum( scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear, scalar zFar ) { scalar one_deltax, one_deltay, one_deltaz, doubleznear; doubleznear = 2.0f * zNear; one_deltax = 1.0f / (xmax - xmin); one_deltay = 1.0f / (ymax - ymin); one_deltaz = 1.0f / (zFar - zNear); data[0] = (scalar)(doubleznear * one_deltax); data[1] = 0.0f; data[2] = 0.0f; data[3] = 0.0f; data[4] = 0.0f; data[5] = (scalar)(doubleznear * one_deltay); data[6] = 0.f; data[7] = 0.f; data[8] = (scalar)((xmax + xmin) * one_deltax); data[9] = (scalar)((ymax + ymin) * one_deltay); data[10] = (scalar)(-(zFar + zNear) * one_deltaz); data[11] = -1.f; data[12] = 0.f; data[13] = 0.f; data[14] = (scalar)(-(zFar * doubleznear) * one_deltaz); data[15] = 0.f; } /** Create a frustum matrix with the far plane at the infinity. */ void FrustumInf( scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear ) { scalar one_deltax, one_deltay, doubleznear, nudge; doubleznear = 2.0f * zNear; one_deltax = 1.0f / (xmax - xmin); one_deltay = 1.0f / (ymax - ymin); nudge = 1.0; // 0.999; data[0] = doubleznear * one_deltax; data[1] = 0.0f; data[2] = 0.0f; data[3] = 0.0f; data[4] = 0.0f; data[5] = doubleznear * one_deltay; data[6] = 0.f; data[7] = 0.f; data[8] = (xmax + xmin) * one_deltax; data[9] = (ymax + ymin) * one_deltay; data[10] = -1.0f * nudge; data[11] = -1.0f; data[12] = 0.f; data[13] = 0.f; data[14] = -doubleznear * nudge; data[15] = 0.f; } /** Create an inverse frustum matrix with the far plane at the infinity. */ void FrustumInfInv( scalar left, scalar right, scalar bottom, scalar top, scalar zNear ) { // this matrix is wrong (not tested scalarly) I think it should be transposed. data[0] = (right - left) / (2 * zNear); data[1] = 0; data[2] = 0; data[3] = (right + left) / (2 * zNear); data[4] = 0; data[5] = (top - bottom) / (2 * zNear); data[6] = 0; data[7] = (top + bottom) / (2 * zNear); data[8] = 0; data[9] = 0; data[10] = 0; data[11] = -1; data[12] = 0; data[13] = 0; data[14] = -1 / (2 * zNear); data[15] = 1 / (2 * zNear); } /** Create an homogeneous projection matrix. */ void Perspective( scalar fov, scalar aspect, scalar zNear, scalar zFar ) { scalar xmin, xmax, ymin, ymax; xmax = zNear * tan( fov/2 ); xmin = -xmax; ymax = xmax / aspect; ymin = -ymax; Frustum(xmin, xmax, ymin, ymax, zNear, zFar); } /** Create a projection matrix with the far plane at the infinity. */ void PerspectiveInf( scalar fov, scalar aspect, scalar zNear ) { scalar x = zNear * tan( fov/2 ); scalar y = x / aspect; FrustumInf( -x, x, -y, y, zNear ); } /** Create an inverse projection matrix with far plane at the infinity. */ void PerspectiveInfInv( scalar fov, scalar aspect, scalar zNear ) { scalar x = zNear * tan( fov/2 ); scalar y = x / aspect; FrustumInfInv( -x, x, -y, y, zNear ); } /** Build bone matrix from quatertion and offset. */ void BoneMatrix(const Quat & q, const Vec3 & offset) { scalar x2, y2, z2, xx, xy, xz, yy, yz, zz, wx, wy, wz; // calculate coefficients x2 = q.x + q.x; y2 = q.y + q.y; z2 = q.z + q.z; xx = q.x * x2; xy = q.x * y2; xz = q.x * z2; yy = q.y * y2; yz = q.y * z2; zz = q.z * z2; wx = q.w * x2; wy = q.w * y2; wz = q.w * z2; data[0] = 1.0f - (yy + zz); data[1] = xy - wz; data[2] = xz + wy; data[3] = 0.0f; data[4] = xy + wz; data[5] = 1.0f - (xx + zz); data[6] = yz - wx; data[7] = 0.0f; data[8] = xz - wy; data[9] = yz + wx; data[10] = 1.0f - (xx + yy); data[11] = 0.0f; data[12] = offset.x; data[13] = offset.y; data[14] = offset.z; data[15] = 1.0f; } //@} /** @name Transformations: */ //@{ /** Apply a general scale. */ void Scale( scalar x, scalar y, scalar z ) { data[0] *= x; data[4] *= y; data[8] *= z; data[1] *= x; data[5] *= y; data[9] *= z; data[2] *= x; data[6] *= y; data[10] *= z; data[3] *= x; data[7] *= y; data[11] *= z; } /** Apply a rotation of theta degrees around the axis v*/ void Rotate( scalar theta, const Vec3 & v ) { Matrix b; b.RotationMatrix( theta, v[0], v[1], v[2] ); Multiply4x3( b ); } /** Apply a rotation of theta degrees around the axis v*/ void Rotate( scalar theta, scalar v0, scalar v1, scalar v2 ) { Matrix b; b.RotationMatrix( theta, v0, v1, v2 ); Multiply4x3( b ); } /** * Translate the matrix by t. This is the same as multiplying by a * translation matrix with the given offset. * this = T * this */ void Translate( const Vec3 &t ) { data[12] = data[0] * t.x + data[4] * t.y + data[8] * t.z + data[12]; data[13] = data[1] * t.x + data[5] * t.y + data[9] * t.z + data[13]; data[14] = data[2] * t.x + data[6] * t.y + data[10] * t.z + data[14]; data[15] = data[3] * t.x + data[7] * t.y + data[11] * t.z + data[15]; } /** * Translate the matrix by x, y, z. This is the same as multiplying by a * translation matrix with the given offsets. */ void Translate( scalar x, scalar y, scalar z ) { data[12] = data[0] * x + data[4] * y + data[8] * z + data[12]; data[13] = data[1] * x + data[5] * y + data[9] * z + data[13]; data[14] = data[2] * x + data[6] * y + data[10] * z + data[14]; data[15] = data[3] * x + data[7] * y + data[11] * z + data[15]; } /** Compute the transposed matrix. */ void Transpose() { piSwap(data[1], data[4]); piSwap(data[2], data[8]); piSwap(data[6], data[9]); piSwap(data[3], data[12]); piSwap(data[7], data[13]); piSwap(data[11], data[14]); } /** Compute the inverse of a rigid-body/isometry/orthonormal matrix. */ void IsometryInverse() { // transposed 3x3 upper left matrix piSwap(data[1], data[4]); piSwap(data[2], data[8]); piSwap(data[6], data[9]); // translate by the negative offsets Vec3 v(-data[12], -data[13], -data[14]); data[12] = data[13] = data[14] = 0; Translate(v); } /** Compute the inverse of the affine portion of this matrix. */ void AffineInverse() { data[12] = data[13] = data[14] = 0; Transpose(); } //@} /** @name Matrix operations: */ //@{ /** Return the determinant of this matrix. */ scalar Determinant() const { return data[0] * data[5] * data[10] * data[15] + data[1] * data[6] * data[11] * data[12] + data[2] * data[7] * data[ 8] * data[13] + data[3] * data[4] * data[ 9] * data[14] - data[3] * data[6] * data[ 9] * data[12] - data[2] * data[5] * data[ 8] * data[15] - data[1] * data[4] * data[11] * data[14] - data[0] * data[7] * data[10] * data[12]; } /** Standard matrix product: this *= B. */ void Multiply4x4( const Matrix & restrict B ) { Multiply4x4(*this, B); } /** Standard matrix product: this = A * B. this != B*/ void Multiply4x4( const Matrix & A, const Matrix & restrict B ) { piDebugCheck(this != &B); for(int i = 0; i < 4; i++) { const scalar ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3); GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); } /* Unrolled but does not allow this == A data[0] = A.data[0] * B.data[0] + A.data[4] * B.data[1] + A.data[8] * B.data[2] + A.data[12] * B.data[3]; data[1] = A.data[1] * B.data[0] + A.data[5] * B.data[1] + A.data[9] * B.data[2] + A.data[13] * B.data[3]; data[2] = A.data[2] * B.data[0] + A.data[6] * B.data[1] + A.data[10] * B.data[2] + A.data[14] * B.data[3]; data[3] = A.data[3] * B.data[0] + A.data[7] * B.data[1] + A.data[11] * B.data[2] + A.data[15] * B.data[3]; data[4] = A.data[0] * B.data[4] + A.data[4] * B.data[5] + A.data[8] * B.data[6] + A.data[12] * B.data[7]; data[5] = A.data[1] * B.data[4] + A.data[5] * B.data[5] + A.data[9] * B.data[6] + A.data[13] * B.data[7]; data[6] = A.data[2] * B.data[4] + A.data[6] * B.data[5] + A.data[10] * B.data[6] + A.data[14] * B.data[7]; data[7] = A.data[3] * B.data[4] + A.data[7] * B.data[5] + A.data[11] * B.data[6] + A.data[15] * B.data[7]; data[8] = A.data[0] * B.data[8] + A.data[4] * B.data[9] + A.data[8] * B.data[10] + A.data[12] * B.data[11]; data[9] = A.data[1] * B.data[8] + A.data[5] * B.data[9] + A.data[9] * B.data[10] + A.data[13] * B.data[11]; data[10]= A.data[2] * B.data[8] + A.data[6] * B.data[9] + A.data[10] * B.data[10] + A.data[14] * B.data[11]; data[11]= A.data[3] * B.data[8] + A.data[7] * B.data[9] + A.data[11] * B.data[10] + A.data[15] * B.data[11]; data[12]= A.data[0] * B.data[12] + A.data[4] * B.data[13] + A.data[8] * B.data[14] + A.data[12] * B.data[15]; data[13]= A.data[1] * B.data[12] + A.data[5] * B.data[13] + A.data[9] * B.data[14] + A.data[13] * B.data[15]; data[14]= A.data[2] * B.data[12] + A.data[6] * B.data[13] + A.data[10] * B.data[14] + A.data[14] * B.data[15]; data[15]= A.data[3] * B.data[12] + A.data[7] * B.data[13] + A.data[11] * B.data[14] + A.data[15] * B.data[15]; */ } /** Standard matrix product: this *= B. */ void Multiply4x3( const Matrix & restrict B ) { Multiply4x3(*this, B); } /** Standard product of matrices, where the last row is [0 0 0 1]. */ void Multiply4x3( const Matrix & A, const Matrix & restrict B ) { piDebugCheck(this != &B); for(int i = 0; i < 3; i++) { const scalar ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3); GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); } data[3] = 0.0f; data[7] = 0.0f; data[11] = 0.0f; data[15] = 1.0f; /* Unrolled but does not allow this == A data[0] = a.data[0] * b.data[0] + a.data[4] * b.data[1] + a.data[8] * b.data[2] + a.data[12] * b.data[3]; data[1] = a.data[1] * b.data[0] + a.data[5] * b.data[1] + a.data[9] * b.data[2] + a.data[13] * b.data[3]; data[2] = a.data[2] * b.data[0] + a.data[6] * b.data[1] + a.data[10] * b.data[2] + a.data[14] * b.data[3]; data[3] = 0.0f; data[4] = a.data[0] * b.data[4] + a.data[4] * b.data[5] + a.data[8] * b.data[6] + a.data[12] * b.data[7]; data[5] = a.data[1] * b.data[4] + a.data[5] * b.data[5] + a.data[9] * b.data[6] + a.data[13] * b.data[7]; data[6] = a.data[2] * b.data[4] + a.data[6] * b.data[5] + a.data[10] * b.data[6] + a.data[14] * b.data[7]; data[7] = 0.0f; data[8] = a.data[0] * b.data[8] + a.data[4] * b.data[9] + a.data[8] * b.data[10] + a.data[12] * b.data[11]; data[9] = a.data[1] * b.data[8] + a.data[5] * b.data[9] + a.data[9] * b.data[10] + a.data[13] * b.data[11]; data[10]= a.data[2] * b.data[8] + a.data[6] * b.data[9] + a.data[10] * b.data[10] + a.data[14] * b.data[11]; data[11]= 0.0f; data[12]= a.data[0] * b.data[12] + a.data[4] * b.data[13] + a.data[8] * b.data[14] + a.data[12] * b.data[15]; data[13]= a.data[1] * b.data[12] + a.data[5] * b.data[13] + a.data[9] * b.data[14] + a.data[13] * b.data[15]; data[14]= a.data[2] * b.data[12] + a.data[6] * b.data[13] + a.data[10] * b.data[14] + a.data[14] * b.data[15]; data[15]= 1.0f; */ } //@} /** @name Vector operations: */ //@{ /** Transform 3d vector (w=0). */ void TransformVec3(const Vec3 & restrict orig, Vec3 * restrict dest) const { piDebugCheck(&orig != dest); dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8]; dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9]; dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10]; } /** Transform 3d vector by the transpose (w=0). */ void TransformVec3T(const Vec3 & restrict orig, Vec3 * restrict dest) const { piDebugCheck(&orig != dest); dest->x = orig.x * data[0] + orig.y * data[1] + orig.z * data[2]; dest->y = orig.x * data[4] + orig.y * data[5] + orig.z * data[6]; dest->z = orig.x * data[8] + orig.y * data[9] + orig.z * data[10]; } /** Transform a 3d homogeneous vector, where the fourth coordinate is assumed to be 1. */ void TransformPoint(const Vec3 & restrict orig, Vec3 * restrict dest) const { piDebugCheck(&orig != dest); dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; } /** Transform a point, normalize it, and return w. */ scalar TransformPointAndNormalize(const Vec3 & restrict orig, Vec3 * restrict dest) const { piDebugCheck(&orig != dest); scalar w; dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; w = 1 / (orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]); *dest *= w; return w; } /** Transform a point and return w. */ scalar TransformPointReturnW(const Vec3 & restrict orig, Vec3 * restrict dest) const { piDebugCheck(&orig != dest); dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; return orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]; } /** Transform a normalized 3d point by a 4d matrix and return the resulting 4d vector. */ void TransformVec4(const Vec3 & orig, Vec4 * dest) const { dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; dest->w = orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]; } //@} /** @name Matrix analysis. */ //@{ /** Get the ZYZ euler angles from the matrix. Assumes the matrix is orthonormal. */ void GetEulerAnglesZYZ(scalar * s, scalar * t, scalar * r) const { if( GetElem(2,2) < 1.0f ) { if( GetElem(2,2) > -1.0f ) { // cs*ct*cr-ss*sr -ss*ct*cr-cs*sr st*cr // cs*ct*sr+ss*cr -ss*ct*sr+cs*cr st*sr // -cs*st ss*st ct *s = atan2(GetElem(1,2), -GetElem(0,2)); *t = acos(GetElem(2,2)); *r = atan2(GetElem(2,1), GetElem(2,0)); } else { // -c(s-r) s(s-r) 0 // s(s-r) c(s-r) 0 // 0 0 -1 *s = atan2(GetElem(0, 1), -GetElem(0, 0)); // = s-r *t = PI; *r = 0; } } else { // c(s+r) -s(s+r) 0 // s(s+r) c(s+r) 0 // 0 0 1 *s = atan2(GetElem(0, 1), GetElem(0, 0)); // = s+r *t = 0; *r = 0; } } //@} MATHLIB_API friend PiStream & operator<< ( PiStream & s, Matrix & m ); /** Print to debug output. */ void Print() const { piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[0], data[4], data[8], data[12] ); piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[1], data[5], data[9], data[13] ); piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[2], data[6], data[10], data[14] ); piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[3], data[7], data[11], data[15] ); } public: scalar data[16]; }; #endif #endif // NV_MATH_MATRIX_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Montecarlo.cpp000066400000000000000000000071031173441656100236100ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include using namespace nv; void SampleDistribution::redistribute(Method method/*=Method_NRook*/, Distribution dist/*=Distribution_Cosine*/) { switch(method) { case Method_Random: redistributeRandom(dist); break; case Method_Stratified: redistributeStratified(dist); break; case Method_NRook: redistributeNRook(dist); break; }; } void SampleDistribution::redistributeRandom(const Distribution dist) { const uint sampleCount = m_sampleArray.count(); // This is the worst method possible! for(uint i = 0; i < sampleCount; i++) { float x = m_rand.getFloat(); float y = m_rand.getFloat(); // Map uniform distribution in the square to the (hemi)sphere. if( dist == Distribution_Uniform ) { m_sampleArray[i].setUV(acosf(1 - 2 * x), 2 * PI * y); } else { nvDebugCheck(dist == Distribution_Cosine); m_sampleArray[i].setUV(acosf(sqrtf(x)), 2 * PI * y); } } } void SampleDistribution::redistributeStratified(const Distribution dist) { const uint sampleCount = m_sampleArray.count(); const uint sqrtSampleCount = uint(sqrtf(float(sampleCount))); nvDebugCheck(sqrtSampleCount*sqrtSampleCount == sampleCount); // Must use exact powers! // Create a uniform distribution of points on the hemisphere with low variance. for(uint v = 0, i = 0; v < sqrtSampleCount; v++) { for(uint u = 0; u < sqrtSampleCount; u++, i++) { float x = (u + m_rand.getFloat()) / float(sqrtSampleCount); float y = (v + m_rand.getFloat()) / float(sqrtSampleCount); // Map uniform distribution in the square to the (hemi)sphere. if( dist == Distribution_Uniform ) { m_sampleArray[i].setUV(acosf(1 - 2 * x), 2 * PI * y); } else { nvDebugCheck(dist == Distribution_Cosine); m_sampleArray[i].setUV(acosf(sqrtf(x)), 2 * PI * y); } } } } /** Multi-Stage N-rooks Sampling Method. * See: http://www.acm.org/jgt/papers/WangSung9/9 */ void SampleDistribution::multiStageNRooks(const int size, int* cells) { if (size == 1) { return; } int size1 = size >> 1; int size2 = size >> 1; if (size & 1) { if (m_rand.getFloat() > 0.5) { size1++; } else { size2++; } } int* upper_cells = new int[size1]; int* lower_cells = new int[size2]; int i, j; for(i = 0, j = 0; i < size - 1; i += 2, j++) { if (m_rand.get() & 1) { upper_cells[j] = cells[i]; lower_cells[j] = cells[i + 1]; } else { upper_cells[j] = cells[i + 1]; lower_cells[j] = cells[i]; } } if (size1 != size2) { if (size1 > size2) { upper_cells[j] = cells[i]; } else { lower_cells[j] = cells[i]; } } multiStageNRooks(size1, upper_cells); memcpy(cells, upper_cells, size1 * sizeof(int)); delete [] upper_cells; multiStageNRooks(size2, lower_cells); memcpy(cells + size1, lower_cells, size2 * sizeof(int)); delete [] lower_cells; } void SampleDistribution::redistributeNRook(const Distribution dist) { const uint sampleCount = m_sampleArray.count(); // Generate nrook cells int * cells = new int[sampleCount]; for(uint32 i = 0; i < sampleCount; i++) { cells[i] = i; } multiStageNRooks(sampleCount, cells); for(uint i = 0; i < sampleCount; i++) { float x = (i + m_rand.getFloat()) / sampleCount; float y = (cells[i] + m_rand.getFloat()) / sampleCount; // Map uniform distribution in the square to the (hemi)sphere. if( dist == Distribution_Uniform ) { m_sampleArray[i].setUV(acosf(1 - 2 * x), 2 * PI * y); } else { nvDebugCheck(dist == Distribution_Cosine); m_sampleArray[i].setUV(acosf(sqrtf(x)), 2 * PI * y); } } delete [] cells; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Montecarlo.h000066400000000000000000000032221173441656100232530ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_MONTECARLO_H #define NV_MATH_MONTECARLO_H #include #include namespace nv { /// A random sample distribution. class SampleDistribution { public: // Sampling method. enum Method { Method_Random, Method_Stratified, Method_NRook }; // Distribution functions. enum Distribution { Distribution_Uniform, Distribution_Cosine }; /// Constructor. SampleDistribution(int num) { m_sampleArray.resize(num); } void redistribute(Method method=Method_NRook, Distribution dist=Distribution_Cosine); /// Get parametric coordinates of the sample. Vector2 sample(int i) { return m_sampleArray[i].uv; } /// Get sample direction. Vector3 sampleDir(int i) { return m_sampleArray[i].dir; } /// Get number of samples. uint sampleCount() const { return m_sampleArray.count(); } private: void redistributeRandom(const Distribution dist); void redistributeStratified(const Distribution dist); void multiStageNRooks(const int size, int* cells); void redistributeNRook(const Distribution dist); /// A sample of the random distribution. struct Sample { /// Set sample given the 3d coordinates. void setDir(float x, float y, float z) { dir.set(x, y, z); uv.set(acosf(z), atan2f(y, x)); } /// Set sample given the 2d parametric coordinates. void setUV(float u, float v) { uv.set(u, v); dir.set(sinf(u) * cosf(v), sinf(u) * sinf(v), cosf(u)); } Vector2 uv; Vector3 dir; }; /// Random seed. MTRand m_rand; /// Samples. Array m_sampleArray; }; } // nv namespace #endif // NV_MATH_MONTECARLO_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Plane.cpp000066400000000000000000000005421173441656100225440ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include "Plane.h" #include "Matrix.h" namespace nv { Plane transformPlane(const Matrix& m, Plane::Arg p) { Vector3 newVec = transformVector(m, p.vector()); Vector3 ptInPlane = p.offset() * p.vector(); ptInPlane = transformPoint(m, ptInPlane); return Plane(newVec, ptInPlane); } } nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Plane.h000066400000000000000000000035041173441656100222120ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_PLANE_H #define NV_MATH_PLANE_H #include #include namespace nv { class Matrix; class NVMATH_CLASS Plane { public: typedef Plane const & Arg; Plane(); Plane(float x, float y, float z, float w); Plane(Vector4::Arg v); Plane(Vector3::Arg v, float d); Plane(Vector3::Arg normal, Vector3::Arg point); const Plane & operator=(Plane::Arg v); Vector3 vector() const; scalar offset() const; const Vector4 & asVector() const; Vector4 & asVector(); void operator*=(scalar s); private: Vector4 p; }; inline Plane::Plane() {} inline Plane::Plane(float x, float y, float z, float w) : p(x, y, z, w) {} inline Plane::Plane(Vector4::Arg v) : p(v) {} inline Plane::Plane(Vector3::Arg v, float d) : p(v, d) {} inline Plane::Plane(Vector3::Arg normal, Vector3::Arg point) : p(normal, dot(normal, point)) {} inline const Plane & Plane::operator=(Plane::Arg v) { p = v.p; return *this; } inline Vector3 Plane::vector() const { return p.xyz(); } inline scalar Plane::offset() const { return p.w(); } inline const Vector4 & Plane::asVector() const { return p; } inline Vector4 & Plane::asVector() { return p; } // Normalize plane. inline Plane normalize(Plane::Arg plane, float epsilon = NV_EPSILON) { const float len = length(plane.vector()); nvDebugCheck(!isZero(len, epsilon)); const float inv = 1.0f / len; return Plane(plane.asVector() * inv); } // Get the distance from the given point to this plane. inline float distance(Plane::Arg plane, Vector3::Arg point) { return dot(plane.vector(), point) - plane.offset(); } inline void Plane::operator*=(scalar s) { scale(p, s); } Plane transformPlane(const Matrix&, Plane::Arg); } // nv namespace #endif // NV_MATH_PLANE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Quaternion.h000066400000000000000000000061141173441656100233000ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_QUATERNION_H #define NV_MATH_QUATERNION_H #include #include namespace nv { class NVMATH_CLASS Quaternion { public: typedef Quaternion const & Arg; Quaternion(); explicit Quaternion(zero_t); Quaternion(float x, float y, float z, float w); Quaternion(Vector4::Arg v); const Quaternion & operator=(Quaternion::Arg v); scalar x() const; scalar y() const; scalar z() const; scalar w() const; const Vector4 & asVector() const; Vector4 & asVector(); private: Vector4 q; }; inline Quaternion::Quaternion() {} inline Quaternion::Quaternion(zero_t) : q(zero) {} inline Quaternion::Quaternion(float x, float y, float z, float w) : q(x, y, z, w) {} inline Quaternion::Quaternion(Vector4::Arg v) : q(v) {} inline const Quaternion & Quaternion::operator=(Quaternion::Arg v) { q = v.q; return *this; } inline scalar Quaternion::x() const { return q.x(); } inline scalar Quaternion::y() const { return q.y(); } inline scalar Quaternion::z() const { return q.z(); } inline scalar Quaternion::w() const { return q.w(); } inline const Vector4 & Quaternion::asVector() const { return q; } inline Vector4 & Quaternion::asVector() { return q; } inline Quaternion mul(Quaternion::Arg a, Quaternion::Arg b) { // @@ Efficient SIMD implementation? return Quaternion( + a.x() * b.w() + a.y()*b.z() - a.z()*b.y() + a.w()*b.x(), - a.x() * b.z() + a.y()*b.w() + a.z()*b.x() + a.w()*b.y(), + a.x() * b.y() - a.y()*b.x() + a.z()*b.w() + a.w()*b.z(), - a.x() * b.x() - a.y()*b.y() - a.z()*b.z() + a.w()*b.w()); } inline Quaternion scale(Quaternion::Arg q, float s) { return scale(q.asVector(), s); } inline Quaternion operator *(Quaternion::Arg q, float s) { return scale(q, s); } inline Quaternion operator *(float s, Quaternion::Arg q) { return scale(q, s); } inline Quaternion scale(Quaternion::Arg q, Vector4::Arg s) { return scale(q.asVector(), s); } /*inline Quaternion operator *(Quaternion::Arg q, Vector4::Arg s) { return scale(q, s); } inline Quaternion operator *(Vector4::Arg s, Quaternion::Arg q) { return scale(q, s); }*/ inline Quaternion conjugate(Quaternion::Arg q) { return scale(q, Vector4(-1, -1, -1, 1)); } inline float length(Quaternion::Arg q) { return length(q.asVector()); } inline bool isNormalized(Quaternion::Arg q, float epsilon = NV_NORMAL_EPSILON) { return equal(length(q), 1, epsilon); } inline Quaternion normalize(Quaternion::Arg q, float epsilon = NV_EPSILON) { float l = length(q); nvDebugCheck(!isZero(l, epsilon)); Quaternion n = scale(q, 1.0f / l); nvDebugCheck(isNormalized(n)); return n; } inline Quaternion inverse(Quaternion::Arg q) { return conjugate(normalize(q)); } /// Create a rotation quaternion for @a angle alpha around normal vector @a v. inline Quaternion axisAngle(Vector3::Arg v, float alpha) { float s = sinf(alpha * 0.5f); float c = cosf(alpha * 0.5f); return Quaternion(Vector4(v * s, c)); } } // nv namespace #endif // NV_MATH_QUATERNION_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Random.cpp000066400000000000000000000022671173441656100227330ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include #include using namespace nv; // Statics const uint16 Rand48::a0 = 0xE66D; const uint16 Rand48::a1 = 0xDEEC; const uint16 Rand48::a2 = 0x0005; const uint16 Rand48::c0 = 0x000B; /// Get a random seed based on the current time. uint Rand::randomSeed() { return (uint)time(NULL); } void MTRand::initialize( uint32 seed ) { // Initialize generator state with seed // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. // In previous versions, most significant bits (MSBs) of the seed affect // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. uint32 *s = state; uint32 *r = state; int i = 1; *s++ = seed & 0xffffffffUL; for( ; i < N; ++i ) { *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL; r++; } } void MTRand::reload() { // Generate N new values in state // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) uint32 *p = state; int i; for( i = N - M; i--; ++p ) *p = twist( p[M], p[0], p[1] ); for( i = M; --i; ++p ) *p = twist( p[M-N], p[0], p[1] ); *p = twist( p[M-N], p[0], state[0] ); left = N, next = state; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Random.h000066400000000000000000000165351173441656100224030ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_RANDOM_H #define NV_MATH_RANDOM_H #include // nextPowerOfTwo #include namespace nv { /// Interface of the random number generators. class Rand { public: virtual ~Rand() {} enum time_e { Time }; /// Provide a new seed. virtual void seed( uint s ) { /* empty */ }; /// Get an integer random number. virtual uint get() = 0; /// Get a random number on [0, max] interval. uint getRange( uint max ) { uint n; // uint mask = Bitmask( max ); // do { n = Get() & mask; } while( n > max ); uint np2 = nextPowerOfTwo( max ); do { n = get() & (np2-1); } while( n > max ); return n; } /// Random number on [0.0, 1.0] interval. float getFloat() { union { uint32 i; float f; } pun; pun.i = 0x3f800000UL | (get() & 0x007fffffUL); return pun.f - 1.0f; } /* /// Random number on [0.0, 1.0] interval. double getReal() { return double(get()) * (1.0/4294967295.0); // 2^32-1 } /// Random number on [0.0, 1.0) interval. double getRealExclusive() { return double(get()) * (1.0/4294967296.0); // 2^32 } */ /// Get the max value of the random number. uint max() const { return 4294967295U; } // Get a random seed. static uint randomSeed(); }; /// Very simple random number generator with low storage requirements. class SimpleRand : public Rand { public: /// Constructor that uses the current time as the seed. SimpleRand( time_e ) { seed(randomSeed()); } /// Constructor that uses the given seed. SimpleRand( uint s = 0 ) { seed(s); } /// Set the given seed. virtual void seed( uint s ) { current = s; } /// Get a random number. virtual uint get() { return current = current * 1103515245 + 12345; } private: uint current; }; /// Mersenne twister random number generator. class MTRand : public Rand { public: enum { N = 624 }; // length of state vector enum { M = 397 }; /// Constructor that uses the current time as the seed. MTRand( time_e ) { seed(randomSeed()); } /// Constructor that uses the given seed. MTRand( uint s = 0 ) { seed(s); } /// Constructor that uses the given seeds. NVMATH_API MTRand( const uint * seed_array, uint length ); /// Provide a new seed. virtual void seed( uint s ) { initialize(s); reload(); } /// Get a random number between 0 - 65536. virtual uint get() { // Pull a 32-bit integer from the generator state // Every other access function simply transforms the numbers extracted here if( left == 0 ) { reload(); } left--; uint s1; s1 = *next++; s1 ^= (s1 >> 11); s1 ^= (s1 << 7) & 0x9d2c5680U; s1 ^= (s1 << 15) & 0xefc60000U; return ( s1 ^ (s1 >> 18) ); }; private: NVMATH_API void initialize( uint32 seed ); NVMATH_API void reload(); uint hiBit( uint u ) const { return u & 0x80000000U; } uint loBit( uint u ) const { return u & 0x00000001U; } uint loBits( uint u ) const { return u & 0x7fffffffU; } uint mixBits( uint u, uint v ) const { return hiBit(u) | loBits(v); } uint twist( uint m, uint s0, uint s1 ) const { return m ^ (mixBits(s0,s1)>>1) ^ ((~loBit(s1)+1) & 0x9908b0dfU); } private: uint state[N]; // internal state uint * next; // next value to get from state int left; // number of values left before reload needed }; /** George Marsaglia's random number generator. * Code based on Thatcher Ulrich public domain source code: * http://cvs.sourceforge.net/viewcvs.py/tu-testbed/tu-testbed/base/tu_random.cpp?rev=1.7&view=auto * * PRNG code adapted from the complimentary-multiply-with-carry * code in the article: George Marsaglia, "Seeds for Random Number * Generators", Communications of the ACM, May 2003, Vol 46 No 5, * pp90-93. * * The article says: * * "Any one of the choices for seed table size and multiplier will * provide a RNG that has passed extensive tests of randomness, * particularly those in [3], yet is simple and fast -- * approximately 30 million random 32-bit integers per second on a * 850MHz PC. The period is a*b^n, where a is the multiplier, n * the size of the seed table and b=2^32-1. (a is chosen so that * b is a primitive root of the prime a*b^n + 1.)" * * [3] Marsaglia, G., Zaman, A., and Tsang, W. Toward a universal * random number generator. _Statistics and Probability Letters * 8_ (1990), 35-39. */ class GMRand : public Rand { public: enum { SEED_COUNT = 8 }; // const uint64 a = 123471786; // for SEED_COUNT=1024 // const uint64 a = 123554632; // for SEED_COUNT=512 // const uint64 a = 8001634; // for SEED_COUNT=255 // const uint64 a = 8007626; // for SEED_COUNT=128 // const uint64 a = 647535442; // for SEED_COUNT=64 // const uint64 a = 547416522; // for SEED_COUNT=32 // const uint64 a = 487198574; // for SEED_COUNT=16 // const uint64 a = 716514398U; // for SEED_COUNT=8 enum { a = 716514398U }; GMRand( time_e ) { seed(randomSeed()); } GMRand(uint s = 987654321) { seed(s); } /// Provide a new seed. virtual void seed( uint s ) { c = 362436; i = SEED_COUNT - 1; for(int i = 0; i < SEED_COUNT; i++) { s = s ^ (s << 13); s = s ^ (s >> 17); s = s ^ (s << 5); Q[i] = s; } } /// Get a random number between 0 - 65536. virtual uint get() { const uint32 r = 0xFFFFFFFE; uint64 t; uint32 x; i = (i + 1) & (SEED_COUNT - 1); t = a * Q[i] + c; c = uint32(t >> 32); x = uint32(t + c); if( x < c ) { x++; c++; } uint32 val = r - x; Q[i] = val; return val; }; private: uint32 c; uint32 i; uint32 Q[8]; }; /** Random number implementation from the GNU Sci. Lib. (GSL). * Adapted from Nicholas Chapman version: * * Copyright (C) 1996, 1997, 1998, 1999, 2000 James Theiler, Brian Gough * This is the Unix rand48() generator. The generator returns the * upper 32 bits from each term of the sequence, * * x_{n+1} = (a x_n + c) mod m * * using 48-bit unsigned arithmetic, with a = 0x5DEECE66D , c = 0xB * and m = 2^48. The seed specifies the upper 32 bits of the initial * value, x_1, with the lower 16 bits set to 0x330E. * * The theoretical value of x_{10001} is 244131582646046. * * The period of this generator is ? FIXME (probably around 2^48). */ class Rand48 : public Rand { public: Rand48( time_e ) { seed(randomSeed()); } Rand48( uint s = 0x1234ABCD ) { seed(s); } /** Set the given seed. */ virtual void seed( uint s ) { vstate.x0 = 0x330E; vstate.x1 = uint16(s & 0xFFFF); vstate.x2 = uint16((s >> 16) & 0xFFFF); } /** Get a random number. */ virtual uint get() { advance(); uint x1 = vstate.x1; uint x2 = vstate.x2; return (x2 << 16) + x1; } private: void advance() { /* work with unsigned long ints throughout to get correct integer promotions of any unsigned short ints */ const uint32 x0 = vstate.x0; const uint32 x1 = vstate.x1; const uint32 x2 = vstate.x2; uint32 a; a = a0 * x0 + c0; vstate.x0 = uint16(a & 0xFFFF); a >>= 16; /* although the next line may overflow we only need the top 16 bits in the following stage, so it does not matter */ a += a0 * x1 + a1 * x0; vstate.x1 = uint16(a & 0xFFFF); a >>= 16; a += a0 * x2 + a1 * x1 + a2 * x0; vstate.x2 = uint16(a & 0xFFFF); } private: NVMATH_API static const uint16 a0, a1, a2, c0; struct rand48_state_t { uint16 x0, x1, x2; } vstate; }; } // nv namespace #endif // NV_MATH_RANDOM_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/SphericalHarmonic.cpp000066400000000000000000000136021173441656100251010ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #include using namespace nv; namespace { // Basic integer factorial. inline static int factorial( int v ) { if (v == 0) { return 1; } int result = v; while (--v > 0) { result *= v; } return result; } // Double factorial. // Defined as: n!! = n*(n - 2)*(n - 4)..., n!!(0,-1) = 1. inline static int doubleFactorial( int x ) { if (x == 0 || x == -1) { return 1; } int result = x; while ((x -= 2) > 0) { result *= x; } return result; } /// Normalization constant for spherical harmonic. /// @param l is the band. /// @param m is the argument, in the range [0, m] inline static float K( int l, int m ) { nvDebugCheck( m >= 0 ); return sqrtf(((2 * l + 1) * factorial(l - m)) / (4 * PI * factorial(l + m))); } /// Normalization constant for hemispherical harmonic. inline static float HK( int l, int m ) { nvDebugCheck( m >= 0 ); return sqrtf(((2 * l + 1) * factorial(l - m)) / (2 * PI * factorial(l + m))); } /// Evaluate Legendre polynomial. */ static float legendre( int l, int m, float x ) { // piDebugCheck( m >= 0 ); // piDebugCheck( m <= l ); // piDebugCheck( fabs(x) <= 1 ); // Rule 2 needs no previous results if (l == m) { return powf(-1.0f, float(m)) * doubleFactorial(2 * m - 1) * powf(1 - x*x, 0.5f * m); } // Rule 3 requires the result for the same argument of the previous band if (l == m + 1) { return x * (2 * m + 1) * legendrePolynomial(m, m, x); } // Main reccurence used by rule 1 that uses result of the same argument from // the previous two bands return (x * (2 * l - 1) * legendrePolynomial(l - 1, m, x) - (l + m - 1) * legendrePolynomial(l - 2, m, x)) / (l - m); } template float legendre(float x); template <> float legendre<0, 0>(float x) { return 1; } template <> float legendre<1, 0>(float x) { return x; } template <> float legendre<1, 1>(float x) { return -sqrtf(1 - x * x); } template <> float legendre<2, 0>(float x) { return -0.5f + (3 * x * x) / 2; } template <> float legendre<2, 1>(float x) { return -3 * x * sqrtf(1 - x * x); } template <> float legendre<2, 2>(float x) { return -3 * (-1 + x * x); } template <> float legendre<3, 0>(float x) { return -(3 * x) / 2 + (5 * x * x * x) / 2; } template <> float legendre<3, 1>(float x) { return -3 * sqrtf(1 - x * x) / 2 * (-1 + 5 * x * x); } template <> float legendre<3, 2>(float x) { return -15 * (-x + x * x * x); } template <> float legendre<3, 3>(float x) { return -15 * powf(1 - x * x, 1.5f); } template <> float legendre<4, 0>(float x) { return 0.125f * (3.0f - 30.0f * x * x + 35.0f * x * x * x * x); } template <> float legendre<4, 1>(float x) { return -2.5f * x * sqrtf(1.0f - x * x) * (7.0f * x * x - 3.0f); } template <> float legendre<4, 2>(float x) { return -7.5f * (1.0f - 8.0f * x * x + 7.0f * x * x * x * x); } template <> float legendre<4, 3>(float x) { return -105.0f * x * powf(1 - x * x, 1.5f); } template <> float legendre<4, 4>(float x) { return 105.0f * (x * x - 1.0f) * (x * x - 1.0f); } } // namespace float nv::legendrePolynomial(int l, int m, float x) { switch(l) { case 0: return legendre<0, 0>(x); case 1: if(m == 0) return legendre<1, 0>(x); return legendre<1, 1>(x); case 2: if(m == 0) return legendre<2, 0>(x); else if(m == 1) return legendre<2, 1>(x); return legendre<2, 2>(x); case 3: if(m == 0) return legendre<3, 0>(x); else if(m == 1) return legendre<3, 1>(x); else if(m == 2) return legendre<3, 2>(x); return legendre<3, 3>(x); case 4: if(m == 0) return legendre<4, 0>(x); else if(m == 1) return legendre<4, 1>(x); else if(m == 2) return legendre<4, 2>(x); else if(m == 3) return legendre<4, 3>(x); else return legendre<4, 4>(x); } // Fallback to the expensive version. return legendre(l, m, x); } /** * Evaluate the spherical harmonic function for the given angles. * @param l is the band. * @param m is the argument, in the range [-l,l] * @param theta is the altitude, in the range [0, PI] * @param phi is the azimuth, in the range [0, 2*PI] */ float nv::y( int l, int m, float theta, float phi ) { if( m == 0 ) { // K(l, 0) = sqrt((2*l+1)/(4*PI)) return sqrtf((2 * l + 1) / (4 * PI)) * legendrePolynomial(l, 0, cosf(theta)); } else if( m > 0 ) { return sqrtf(2.0f) * K(l, m) * cosf(m * phi) * legendrePolynomial(l, m, cosf(theta)); } else { return sqrtf(2.0f) * K(l, -m) * sinf(-m * phi) * legendrePolynomial(l, -m, cosf(theta)); } } /** * Real spherical harmonic function of an unit vector. Uses the following * equalities to call the angular function: * x = sin(theta)*cos(phi) * y = sin(theta)*sin(phi) * z = cos(theta) */ float nv::y( int l, int m, Vector3::Arg v ) { float theta = acosf(v.z()); float phi = atan2f(v.y(), v.x()); return y( l, m, theta, phi ); } /** * Evaluate the hemispherical harmonic function for the given angles. * @param l is the band. * @param m is the argument, in the range [-l,l] * @param theta is the altitude, in the range [0, PI/2] * @param phi is the azimuth, in the range [0, 2*PI] */ float nv::hy( int l, int m, float theta, float phi ) { if( m == 0 ) { // HK(l, 0) = sqrt((2*l+1)/(2*PI)) return sqrtf((2 * l + 1) / (2 * PI)) * legendrePolynomial(l, 0, 2*cosf(theta)-1); } else if( m > 0 ) { return sqrtf(2.0f) * HK(l, m) * cosf(m * phi) * legendrePolynomial(l, m, 2*cosf(theta)-1); } else { return sqrtf(2.0f) * HK(l, -m) * sinf(-m * phi) * legendrePolynomial(l, -m, 2*cosf(theta)-1); } } /** * Real hemispherical harmonic function of an unit vector. Uses the following * equalities to call the angular function: * x = sin(theta)*cos(phi) * y = sin(theta)*sin(phi) * z = cos(theta) */ float nv::hy( int l, int m, Vector3::Arg v ) { float theta = acosf(v.z()); float phi = atan2f(v.y(), v.x()); return y( l, m, theta, phi ); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/SphericalHarmonic.h000066400000000000000000000204611173441656100245470ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_SPHERICALHARMONIC_H #define NV_MATH_SPHERICALHARMONIC_H #include namespace nv { NVMATH_API float legendrePolynomial( int l, int m, float x ) NV_CONST; NVMATH_API float y( int l, int m, float theta, float phi ) NV_CONST; NVMATH_API float y( int l, int m, Vector3::Arg v ) NV_CONST; NVMATH_API float hy( int l, int m, float theta, float phi ) NV_CONST; NVMATH_API float hy( int l, int m, Vector3::Arg v ) NV_CONST; class Sh; float dot(const Sh & a, const Sh & b) NV_CONST; /// Spherical harmonic class. class Sh { friend class Sh2; friend class ShMatrix; public: /// Construct a spherical harmonic of the given order. Sh(int o) : m_order(o) { m_elemArray = new float[basisNum()]; } /// Copy constructor. Sh(const Sh & sh) : m_order(sh.order()) { m_elemArray = new float[basisNum()]; memcpy(m_elemArray, sh.m_elemArray, sizeof(float) * basisNum()); } /// Destructor. ~Sh() { delete [] m_elemArray; m_elemArray = NULL; } /// Get number of bands. static int bandNum(int order) { return order + 1; } /// Get number of sh basis. static int basisNum(int order) { return (order + 1) * (order + 1); } /// Get the index for the given coefficients. static int index( int l, int m ) { return l * l + l + m; } /// Get sh order. int order() const { return m_order; } /// Get sh order. int bandNum() const { return bandNum(m_order); } /// Get sh order. int basisNum() const { return basisNum(m_order); } /// Get sh coefficient indexed by l,m. float elem( int l, int m ) const { return m_elemArray[index(l, m)]; } /// Get sh coefficient indexed by l,m. float & elem( int l, int m ) { return m_elemArray[index(l, m)]; } /// Get sh coefficient indexed by i. float elemAt( int i ) const { return m_elemArray[i]; } /// Get sh coefficient indexed by i. float & elemAt( int i ) { return m_elemArray[i]; } /// Reset the sh coefficients. void reset() { for( int i = 0; i < basisNum(); i++ ) { m_elemArray[i] = 0.0f; } } /// Copy spherical harmonic. void operator= ( const Sh & sh ) { nvDebugCheck(order() <= sh.order()); for(int i = 0; i < basisNum(); i++) { m_elemArray[i] = sh.m_elemArray[i]; } } /// Add spherical harmonics. void operator+= ( const Sh & sh ) { nvDebugCheck(order() == sh.order()); for(int i = 0; i < basisNum(); i++) { m_elemArray[i] += sh.m_elemArray[i]; } } /// Substract spherical harmonics. void operator-= ( const Sh & sh ) { nvDebugCheck(order() == sh.order()); for(int i = 0; i < basisNum(); i++) { m_elemArray[i] -= sh.m_elemArray[i]; } } // Not exactly convolution, nor product. void operator*= ( const Sh & sh ) { nvDebugCheck(order() == sh.order()); for(int i = 0; i < basisNum(); i++) { m_elemArray[i] *= sh.m_elemArray[i]; } } /// Scale spherical harmonics. void operator*= ( float f ) { for(int i = 0; i < basisNum(); i++) { m_elemArray[i] *= f; } } /// Add scaled spherical harmonics. void addScaled( const Sh & sh, float f ) { nvDebugCheck(order() == sh.order()); for(int i = 0; i < basisNum(); i++) { m_elemArray[i] += sh.m_elemArray[i] * f; } } /*/// Add a weighted sample to the sh coefficients. void AddSample( const Vec3 & dir, const Color3f & color, float w=1.0f ) { for(int l = 0; l <= order; l++) { for(int m = -l; m <= l; m++) { Color3f & elem = GetElem(l, m); elem.Mad( elem, color, w * y(l, m, dir) ); } } }*/ /// Evaluate void eval(Vector3::Arg dir) { for(int l = 0; l <= m_order; l++) { for(int m = -l; m <= l; m++) { elem(l, m) = y(l, m, dir); } } } /// Evaluate the spherical harmonic function. float sample(Vector3::Arg dir) const { Sh sh(order()); sh.eval(dir); return dot(sh, *this); } protected: const int m_order; float * m_elemArray; }; /// Compute dot product of the spherical harmonics. inline float dot(const Sh & a, const Sh & b) { nvDebugCheck(a.order() == b.order()); float sum = 0; for( int i = 0; i < Sh::basisNum(a.order()); i++ ) { sum += a.elemAt(i) * b.elemAt(i); } return sum; } /// Second order spherical harmonic. class Sh2 : public Sh { public: /// Constructor. Sh2() : Sh(2) {} /// Copy constructor. Sh2(const Sh2 & sh) : Sh(sh) {} /// Spherical harmonic resulting from projecting the clamped cosine transfer function to the SH basis. void cosineTransfer() { const float c1 = 0.282095f; // K(0, 0) const float c2 = 0.488603f; // K(1, 0) const float c3 = 1.092548f; // sqrt(15.0f / PI) / 2.0f = K(2, -2) const float c4 = 0.315392f; // sqrt(5.0f / PI) / 4.0f) = K(2, 0) const float c5 = 0.546274f; // sqrt(15.0f / PI) / 4.0f) = K(2, 2) const float normalization = PI * 16.0f / 17.0f; const float const1 = c1 * normalization * 1.0f; const float const2 = c2 * normalization * (2.0f / 3.0f); const float const3 = c3 * normalization * (1.0f / 4.0f); const float const4 = c4 * normalization * (1.0f / 4.0f); const float const5 = c5 * normalization * (1.0f / 4.0f); m_elemArray[0] = const1; m_elemArray[1] = -const2; m_elemArray[2] = const2; m_elemArray[3] = -const2; m_elemArray[4] = const3; m_elemArray[5] = -const3; m_elemArray[6] = const4; m_elemArray[7] = -const3; m_elemArray[8] = const5; } }; #if 0 /// Spherical harmonic matrix. class ShMatrix { public: /// Create an identity matrix of the given order. ShMatrix(int o = 2) : order(o), identity(true) { nvCheck(order > 0); e = new float[Size()]; band = new float *[GetBandNum()]; setupBands(); } /// Destroy and free matrix elements. ~ShMatrix() { delete e; delete band; } /// Set identity matrix. void setIdentity() { identity = true; } /// Return true if this is an identity matrix, false in other case. bool isIdentity() const { return identity; } /// Get number of bands of this matrix. int bandNum() const { return order+1; } /// Get total number of elements in the matrix. int size() const { int size = 0; for( int i = 0; i < bandNum(); i++ ) { size += SQ(i * 2 + 1); } return size; } /// Get element at the given raw index. float elem(const int idx) const { return e[idx]; } /// Get element at the given with the given indices. float & elem( const int b, const int x, const int y ) { nvDebugCheck(b >= 0); nvDebugCheck(b < bandNum()); return band[b][(b + y) * (b * 2 + 1) + (b + x)]; } /// Get element at the given with the given indices. float elem( const int b, const int x, const int y ) const { nvDebugCheck(b >= 0); nvDebugCheck(b < bandNum()); return band[b][(b + y) * (b * 2 + 1) + (b + x)]; } /** Copy matrix. */ void Copy( const ShMatrix & m ) { nvDebugCheck(order == m.order); memcpy(e, m.e, Size() * sizeof(float)); } /** Rotate the given coefficients. */ void transform( const Sh & restrict source, Sh * restrict dest ) const { piCheck( &source != dest ); // Make sure there's no aliasing. piCheck( dest->order <= order ); piCheck( order <= source.order ); if( identity ) { *dest = source; return; } // Loop through each band. for( int l = 0; l <= dest->order; l++ ) { for( int mo = -l; mo <= l; mo++ ) { Color3f rgb = Color3f::Black; for( int mi = -l; mi <= l; mi++ ) { rgb.Mad( rgb, source.elem(l, mi), elem(l, mo, mi) ); } dest->elem(l, mo) = rgb; } } } MATHLIB_API void multiply( const ShMatrix &A, const ShMatrix &B ); MATHLIB_API void rotation( const Matrix & m ); MATHLIB_API void rotation( int axis, float angles ); MATHLIB_API void print(); private: // @@ These could be static indices precomputed only once. /// Setup the band pointers. void setupBands() { int size = 0; for( int i = 0; i < bandNum(); i++ ) { band[i] = &e[size]; size += SQ(i * 2 + 1); } } private: // Matrix order. const int m_order; // Identity flag for quick transform. bool m_identity; // Array of elements. float * m_e; // Band pointers. float ** m_band; }; #endif // 0 } // nv namespace #endif // NV_MATH_SPHERICALHARMONIC_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/TriBox.cpp000066400000000000000000000160701173441656100227170ustar00rootroot00000000000000/********************************************************/ /* AABB-triangle overlap test code */ /* by Tomas Akenine-Möller */ /* Function: int triBoxOverlap(float boxcenter[3], */ /* float boxhalfsize[3],float triverts[3][3]); */ /* History: */ /* 2001-03-05: released the code in its first version */ /* 2001-06-18: changed the order of the tests, faster */ /* */ /* Acknowledgement: Many thanks to Pierre Terdiman for */ /* suggestions and discussions on how to optimize code. */ /* Thanks to David Hunt for finding a ">="-bug! */ /********************************************************/ #include #include using namespace nv; #define X 0 #define Y 1 #define Z 2 #define FINDMINMAX(x0,x1,x2,min,max) \ min = max = x0; \ if(x1max) max=x1;\ if(x2max) max=x2; static bool planeBoxOverlap(Vector3::Arg normal, Vector3::Arg vert, Vector3::Arg maxbox) // -NJMP- { Vector3 vmin, vmax; float signs[3] = {1, 1, 1}; if (normal.x() <= 0.0f) signs[0] = -1; if (normal.y() <= 0.0f) signs[1] = -1; if (normal.z() <= 0.0f) signs[2] = -1; Vector3 sign(signs[0], signs[1], signs[2]); vmin = -scale(sign, maxbox) - vert; vmax = scale(sign, maxbox) - vert; if (dot(normal, vmin) > 0.0f) return false; if (dot(normal, vmax) >= 0.0f) return true; return false; } /*======================== X-tests ========================*/ #define AXISTEST_X01(a, b, fa, fb) \ p0 = a*v0.y() - b*v0.z(); \ p2 = a*v2.y() - b*v2.z(); \ if(p0rad || max<-rad) return false; #define AXISTEST_X2(a, b, fa, fb) \ p0 = a*v0.y() - b*v0.z(); \ p1 = a*v1.y() - b*v1.z(); \ if(p0rad || max<-rad) return false; /*======================== Y-tests ========================*/ #define AXISTEST_Y02(a, b, fa, fb) \ p0 = -a*v0.x() + b*v0.z(); \ p2 = -a*v2.x() + b*v2.z(); \ if(p0rad || max<-rad) return false; #define AXISTEST_Y1(a, b, fa, fb) \ p0 = -a*v0.x() + b*v0.z(); \ p1 = -a*v1.x() + b*v1.z(); \ if(p0rad || max<-rad) return false; /*======================== Z-tests ========================*/ #define AXISTEST_Z12(a, b, fa, fb) \ p1 = a*v1.x() - b*v1.y(); \ p2 = a*v2.x() - b*v2.y(); \ if(p2rad || max<-rad) return false; #define AXISTEST_Z0(a, b, fa, fb) \ p0 = a*v0.x() - b*v0.y(); \ p1 = a*v1.x() - b*v1.y(); \ if(p0rad || max<-rad) return false; bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Triangle & tri) { // use separating axis theorem to test overlap between triangle and box // need to test for overlap in these directions: // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle // we do not even need to test these) // 2) normal of the triangle // 3) crossproduct(edge from tri, {x,y,z}-directin) // this gives 3x3=9 more tests Vector3 v0, v1, v2; float min, max, p0, p1, p2, rad, fex, fey, fez; Vector3 normal, e0, e1, e2; // This is the fastest branch on Sun. // move everything so that the boxcenter is in (0,0,0) v0 = tri.v[0] - boxcenter; v1 = tri.v[1] - boxcenter; v2 = tri.v[2] - boxcenter; // Compute triangle edges. e0 = v1 - v0; // tri edge 0 e1 = v2 - v1; // tri edge 1 e2 = v0 - v2; // tri edge 2 // Bullet 3: // test the 9 tests first (this was faster) fex = fabsf(e0.x()); fey = fabsf(e0.y()); fez = fabsf(e0.z()); AXISTEST_X01(e0.z(), e0.y(), fez, fey); AXISTEST_Y02(e0.z(), e0.x(), fez, fex); AXISTEST_Z12(e0.y(), e0.x(), fey, fex); fex = fabsf(e1.x()); fey = fabsf(e1.y()); fez = fabsf(e1.z()); AXISTEST_X01(e1.z(), e1.y(), fez, fey); AXISTEST_Y02(e1.z(), e1.x(), fez, fex); AXISTEST_Z0(e1.y(), e1.x(), fey, fex); fex = fabsf(e2.x()); fey = fabsf(e2.y()); fez = fabsf(e2.z()); AXISTEST_X2(e2.z(), e2.y(), fez, fey); AXISTEST_Y1(e2.z(), e2.x(), fez, fex); AXISTEST_Z12(e2.y(), e2.x(), fey, fex); // Bullet 1: // first test overlap in the {x,y,z}-directions // find min, max of the triangle each direction, and test for overlap in // that direction -- this is equivalent to testing a minimal AABB around // the triangle against the AABB // test in X-direction FINDMINMAX(v0.x(), v1.x(), v2.x(), min, max); if(min > boxhalfsize.x() || max < -boxhalfsize.x()) return false; // test in Y-direction FINDMINMAX(v0.y(), v1.y(), v2.y(), min, max); if(min > boxhalfsize.y() || max < -boxhalfsize.y()) return false; // test in Z-direction FINDMINMAX(v0.z(), v1.z(), v2.z(), min, max); if(min > boxhalfsize.z() || max < -boxhalfsize.z()) return false; // Bullet 2: // test if the box intersects the plane of the triangle // compute plane equation of triangle: normal*x+d=0 normal = cross(e0, e1); return planeBoxOverlap(normal, v0, boxhalfsize); } bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Triangle & tri) { // use separating axis theorem to test overlap between triangle and box // need to test for overlap in these directions: // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle // we do not even need to test these) // 2) normal of the triangle // 3) crossproduct(edge from tri, {x,y,z}-directin) // this gives 3x3=9 more tests Vector3 v0, v1, v2; float min, max, p0, p1, p2, rad, fex, fey, fez; Vector3 normal, e0, e1, e2; // This is the fastest branch on Sun. // move everything so that the boxcenter is in (0,0,0) v0 = tri.v[0] - boxcenter; v1 = tri.v[1] - boxcenter; v2 = tri.v[2] - boxcenter; // Compute triangle edges. e0 = v1 - v0; // tri edge 0 e1 = v2 - v1; // tri edge 1 e2 = v0 - v2; // tri edge 2 // Bullet 3: // test the 9 tests first (this was faster) fex = fabsf(e0.x()); fey = fabsf(e0.y()); fez = fabsf(e0.z()); AXISTEST_X01(e0.z(), e0.y(), fez, fey); AXISTEST_Y02(e0.z(), e0.x(), fez, fex); AXISTEST_Z12(e0.y(), e0.x(), fey, fex); fex = fabsf(e1.x()); fey = fabsf(e1.y()); fez = fabsf(e1.z()); AXISTEST_X01(e1.z(), e1.y(), fez, fey); AXISTEST_Y02(e1.z(), e1.x(), fez, fex); AXISTEST_Z0(e1.y(), e1.x(), fey, fex); fex = fabsf(e2.x()); fey = fabsf(e2.y()); fez = fabsf(e2.z()); AXISTEST_X2(e2.z(), e2.y(), fez, fey); AXISTEST_Y1(e2.z(), e2.x(), fez, fex); AXISTEST_Z12(e2.y(), e2.x(), fey, fex); // Bullet 2: // test if the box intersects the plane of the triangle // compute plane equation of triangle: normal*x+d=0 normal = cross(e0, e1); return planeBoxOverlap(normal, v0, boxhalfsize); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Triangle.cpp000066400000000000000000000077031173441656100232600ustar00rootroot00000000000000// This code is in the public domain -- Ignacio Castaño #include using namespace nv; /// Tomas Möller, barycentric ray-triangle test. bool rayTest_Moller(const Triangle & t, Vector3::Arg orig, Vector3::Arg dir, float * out_t, float * out_u, float * out_v) { // find vectors for two edges sharing vert0 Vector3 e1 = t.v[1] - t.v[0]; Vector3 e2 = t.v[2] - t.v[0]; // begin calculating determinant - also used to calculate U parameter Vector3 pvec = cross(dir, e2); // if determinant is near zero, ray lies in plane of triangle float det = dot(e1, pvec); if (det < -NV_EPSILON) { return false; } // calculate distance from vert0 to ray origin Vector3 tvec = orig - t.v[0]; // calculate U parameter and test bounds float u = dot(tvec, pvec); if( u < 0.0f || u > det ) { return false; } // prepare to test V parameter Vector3 qvec = cross(tvec, e1); // calculate V parameter and test bounds float v = dot(dir, qvec); if (v < 0.0f || u + v > det) { return false; } // calculate t, scale parameters, ray intersects triangle float inv_det = 1.0f / det; *out_t = dot(e2, qvec) * inv_det; *out_u = u * inv_det; // v *out_v = v * inv_det; // 1-(u+v) return true; } #if 0 // IC: This code is adapted from my Pi.MathLib code, based on Moller-Trumbore triangle test. FXVector3 edge1, edge2, pvec, tvec, qvec; edge1 = tri.V1 - tri.V0; edge2 = tri.V2 - tri.V0; pvec.Cross(ray.Direction, edge2); float det = FXVector3.Dot(edge1, pvec); // calculate distance from vert0 to ray origin. FXVector3 tvec = ray.Origin - vert0; if( det < 0 ) { // calculate U parameter and test bounds. float u = FXVector3.Dot(tvec, pvec); if (u > 0.0 || u < det) { return false; } // prepare to test V parameter. qvec.Cross(tvec, edge1); // calculate V parameter and test bounds. float v = FXVector3.Dot(dir, qvec); return v <= 0.0 && u + v >= det; } else { // calculate U parameter and test bounds. float u = FXVector3.Dot(tvec, pvec); if (u < 0.0 || u > det) { return false; } // prepare to test V parameter. qvec.Cross(tvec, edge1); // calculate V parameter and test bounds. float v = FXVector3.Dot(dir, qvec); return v >= 0.0 && u + v <= det; } /** * Dan Sunday, parametric ray-triangle test. */ // Output: *I = intersection point (when it exists) // Return: -1 = triangle is degenerate (a segment or point) // 0 = disjoint (no intersect) // 1 = intersect in unique point I1 // 2 = are in the same plane bool RayTriangleTest( const Vec3 &p0, const Vec3 &p1, const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &n, Vec3 &I ) { Vec3 u, v; // triangle vectors Vec3 dir, w0, w; // ray vectors float r, a, b; // params to calc ray-plane intersect // get triangle edge vectors and plane normal u.Sub( v1, v0 ); v.Sub( v2, v0 ); dir.Sub( p1, p0 ); // ray direction vector w0.Sub( p0, v0 ); a = Vec3DotProduct( n, w0 ); b = Vec3DotProduct( n, dir ); if( fabs(b) < TI_EPSILON ) // ray is parallel to triangle plane return false; // get intersect point of ray with triangle plane r = -a / b; if( r < 0.0f ) // ray goes away from triangle return false; // => no intersect // for a segment, also test if (r > 1.0) => no intersect I.Mad( p0, dir, r ); // intersect point of ray and plane // is I inside T? float uu, uv, vv, wu, wv, D; uu = Vec3DotProduct( u, u ); uv = Vec3DotProduct( u, v ); vv = Vec3DotProduct( v, v ); w = I - v0; wu = Vec3DotProduct( w, u ); wv = Vec3DotProduct( w, v ); D = uv * uv - uu * vv; // get and test parametric coords float s, t; s = (uv * wv - vv * wu) / D; if( s<0.0 || s > 1.0) // I is outside T return false; t = (uv * wu - uu * wv) / D; if( t<0.0 || (s + t) > 1.0) // I is outside T return false; return true; // I is in T } #endif // 0 nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Triangle.h000066400000000000000000000035701173441656100227230ustar00rootroot00000000000000// This code is in the public domain -- Ignacio Castaño #ifndef NV_MATH_TRIANGLE_H #define NV_MATH_TRIANGLE_H #include #include #include namespace nv { /// Triangle class with three vertices. class Triangle { public: Triangle() {}; Triangle(Vector3::Arg v0, Vector3::Arg v1, Vector3::Arg v2) { v[0] = v0; v[1] = v1; v[2] = v2; } /// Get the bounds of the triangle. Box bounds() const { Box bounds; bounds.clearBounds(); bounds.addPointToBounds(v[0]); bounds.addPointToBounds(v[1]); bounds.addPointToBounds(v[2]); return bounds; } Vector4 plane() const { Vector3 n = cross(v[1]-v[0], v[2]-v[0]); return Vector4(n, dot(n, v[0])); } Vector3 v[3]; }; // Tomas Akenine-Möller box-triangle test. NVMATH_API bool triBoxOverlap(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Triangle & triangle); NVMATH_API bool triBoxOverlapNoBounds(Vector3::Arg boxcenter, Vector3::Arg boxhalfsize, const Triangle & triangle); // Moller ray triangle test. NVMATH_API bool rayTest_Moller(const Triangle & t, Vector3::Arg orig, Vector3::Arg dir, float * out_t, float * out_u, float * out_v); inline bool rayTest(const Triangle & t, Vector3::Arg orig, Vector3::Arg dir, float * out_t, float * out_u, float * out_v) { return rayTest_Moller(t, orig, dir, out_t, out_u, out_v); } inline bool overlap(const Triangle & t, const Box & b) { Vector3 center = b.center(); Vector3 extents = b.extents(); return triBoxOverlap(center, extents, t); } inline bool overlap(const Box & b, const Triangle & t) { return overlap(t, b); } inline bool overlapNoBounds(const Triangle & t, const Box & b) { Vector3 center = b.center(); Vector3 extents = b.extents(); return triBoxOverlapNoBounds(center, extents, t); } } // nv namespace #endif // NV_MATH_TRIANGLE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/Vector.h000066400000000000000000000415371173441656100224250ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_VECTOR_H #define NV_MATH_VECTOR_H #include #include // min, max namespace nv { enum zero_t { zero }; enum identity_t { identity }; // I should probably use templates. typedef float scalar; class NVMATH_CLASS Vector2 { public: typedef Vector2 const & Arg; Vector2(); explicit Vector2(zero_t); explicit Vector2(scalar f); Vector2(scalar x, scalar y); Vector2(Vector2::Arg v); const Vector2 & operator=(Vector2::Arg v); scalar x() const; scalar y() const; scalar component(uint idx) const; const scalar * ptr() const; void set(scalar x, scalar y); Vector2 operator-() const; void operator+=(Vector2::Arg v); void operator-=(Vector2::Arg v); void operator*=(scalar s); void operator*=(Vector2::Arg v); friend bool operator==(Vector2::Arg a, Vector2::Arg b); friend bool operator!=(Vector2::Arg a, Vector2::Arg b); private: scalar m_x, m_y; }; class NVMATH_CLASS Vector3 { public: typedef Vector3 const & Arg; Vector3(); explicit Vector3(zero_t); Vector3(scalar x, scalar y, scalar z); Vector3(Vector2::Arg v, scalar z); Vector3(Vector3::Arg v); const Vector3 & operator=(Vector3::Arg v); scalar x() const; scalar y() const; scalar z() const; const Vector2 & xy() const; scalar component(uint idx) const; const scalar * ptr() const; void set(scalar x, scalar y, scalar z); Vector3 operator-() const; void operator+=(Vector3::Arg v); void operator-=(Vector3::Arg v); void operator*=(scalar s); void operator/=(scalar s); void operator*=(Vector3::Arg v); friend bool operator==(Vector3::Arg a, Vector3::Arg b); friend bool operator!=(Vector3::Arg a, Vector3::Arg b); private: scalar m_x, m_y, m_z; }; class NVMATH_CLASS Vector4 { public: typedef Vector4 const & Arg; Vector4(); explicit Vector4(zero_t); Vector4(scalar x, scalar y, scalar z, scalar w); Vector4(Vector2::Arg v, scalar z, scalar w); Vector4(Vector3::Arg v, scalar w); Vector4(Vector4::Arg v); // Vector4(const Quaternion & v); const Vector4 & operator=(Vector4::Arg v); scalar x() const; scalar y() const; scalar z() const; scalar w() const; const Vector2 & xy() const; const Vector3 & xyz() const; scalar component(uint idx) const; const scalar * ptr() const; void set(scalar x, scalar y, scalar z, scalar w); Vector4 operator-() const; void operator+=(Vector4::Arg v); void operator-=(Vector4::Arg v); void operator*=(scalar s); void operator*=(Vector4::Arg v); friend bool operator==(Vector4::Arg a, Vector4::Arg b); friend bool operator!=(Vector4::Arg a, Vector4::Arg b); private: scalar m_x, m_y, m_z, m_w; }; // Vector2 inline Vector2::Vector2() {} inline Vector2::Vector2(zero_t) : m_x(0.0f), m_y(0.0f) {} inline Vector2::Vector2(scalar f) : m_x(f), m_y(f) {} inline Vector2::Vector2(scalar x, scalar y) : m_x(x), m_y(y) {} inline Vector2::Vector2(Vector2::Arg v) : m_x(v.x()), m_y(v.y()) {} inline const Vector2 & Vector2::operator=(Vector2::Arg v) { m_x = v.x(); m_y = v.y(); return *this; } inline scalar Vector2::x() const { return m_x; } inline scalar Vector2::y() const { return m_y; } inline scalar Vector2::component(uint idx) const { nvDebugCheck(idx < 2); if (idx == 0) return x(); if (idx == 1) return y(); nvAssume(false); return 0.0f; } inline const scalar * Vector2::ptr() const { return &m_x; } inline void Vector2::set(scalar x, scalar y) { m_x = x; m_y = y; } inline Vector2 Vector2::operator-() const { return Vector2(-m_x, -m_y); } inline void Vector2::operator+=(Vector2::Arg v) { m_x += v.m_x; m_y += v.m_y; } inline void Vector2::operator-=(Vector2::Arg v) { m_x -= v.m_x; m_y -= v.m_y; } inline void Vector2::operator*=(scalar s) { m_x *= s; m_y *= s; } inline void Vector2::operator*=(Vector2::Arg v) { m_x *= v.m_x; m_y *= v.m_y; } inline bool operator==(Vector2::Arg a, Vector2::Arg b) { return a.m_x == b.m_x && a.m_y == b.m_y; } inline bool operator!=(Vector2::Arg a, Vector2::Arg b) { return a.m_x != b.m_x || a.m_y != b.m_y; } // Vector3 inline Vector3::Vector3() {} inline Vector3::Vector3(zero_t) : m_x(0.0f), m_y(0.0f), m_z(0.0f) {} inline Vector3::Vector3(scalar x, scalar y, scalar z) : m_x(x), m_y(y), m_z(z) {} inline Vector3::Vector3(Vector2::Arg v, scalar z) : m_x(v.x()), m_y(v.y()), m_z(z) {} inline Vector3::Vector3(Vector3::Arg v) : m_x(v.x()), m_y(v.y()), m_z(v.z()) {} inline const Vector3 & Vector3::operator=(Vector3::Arg v) { m_x = v.m_x; m_y = v.m_y; m_z = v.m_z; return *this; } inline scalar Vector3::x() const { return m_x; } inline scalar Vector3::y() const { return m_y; } inline scalar Vector3::z() const { return m_z; } inline const Vector2 & Vector3::xy() const { return *(Vector2 *)this; } inline scalar Vector3::component(uint idx) const { nvDebugCheck(idx < 3); if (idx == 0) return x(); if (idx == 1) return y(); if (idx == 2) return z(); nvAssume(false); return 0.0f; } inline const scalar * Vector3::ptr() const { return &m_x; } inline void Vector3::set(scalar x, scalar y, scalar z) { m_x = x; m_y = y; m_z = z; } inline Vector3 Vector3::operator-() const { return Vector3(-m_x, -m_y, -m_z); } inline void Vector3::operator+=(Vector3::Arg v) { m_x += v.m_x; m_y += v.m_y; m_z += v.m_z; } inline void Vector3::operator-=(Vector3::Arg v) { m_x -= v.m_x; m_y -= v.m_y; m_z -= v.m_z; } inline void Vector3::operator*=(scalar s) { m_x *= s; m_y *= s; m_z *= s; } inline void Vector3::operator/=(scalar s) { float is = 1.0f / s; m_x *= is; m_y *= is; m_z *= is; } inline void Vector3::operator*=(Vector3::Arg v) { m_x *= v.m_x; m_y *= v.m_y; m_z *= v.m_z; } inline bool operator==(Vector3::Arg a, Vector3::Arg b) { return a.m_x == b.m_x && a.m_y == b.m_y && a.m_z == b.m_z; } inline bool operator!=(Vector3::Arg a, Vector3::Arg b) { return a.m_x != b.m_x || a.m_y != b.m_y || a.m_z != b.m_z; } // Vector4 inline Vector4::Vector4() {} inline Vector4::Vector4(zero_t) : m_x(0.0f), m_y(0.0f), m_z(0.0f), m_w(0.0f) {} inline Vector4::Vector4(scalar x, scalar y, scalar z, scalar w) : m_x(x), m_y(y), m_z(z), m_w(w) {} inline Vector4::Vector4(Vector2::Arg v, scalar z, scalar w) : m_x(v.x()), m_y(v.y()), m_z(z), m_w(w) {} inline Vector4::Vector4(Vector3::Arg v, scalar w) : m_x(v.x()), m_y(v.y()), m_z(v.z()), m_w(w) {} inline Vector4::Vector4(Vector4::Arg v) : m_x(v.x()), m_y(v.y()), m_z(v.z()), m_w(v.w()) {} inline const Vector4 & Vector4::operator=(const Vector4 & v) { m_x = v.m_x; m_y = v.m_y; m_z = v.m_z; m_w = v.m_w; return *this; } inline scalar Vector4::x() const { return m_x; } inline scalar Vector4::y() const { return m_y; } inline scalar Vector4::z() const { return m_z; } inline scalar Vector4::w() const { return m_w; } inline const Vector2 & Vector4::xy() const { return *(Vector2 *)this; } inline const Vector3 & Vector4::xyz() const { return *(Vector3 *)this; } inline scalar Vector4::component(uint idx) const { nvDebugCheck(idx < 4); if (idx == 0) return x(); if (idx == 1) return y(); if (idx == 2) return z(); if (idx == 3) return w(); nvAssume(false); return 0.0f; } inline const scalar * Vector4::ptr() const { return &m_x; } inline void Vector4::set(scalar x, scalar y, scalar z, scalar w) { m_x = x; m_y = y; m_z = z; m_w = w; } inline Vector4 Vector4::operator-() const { return Vector4(-m_x, -m_y, -m_z, -m_w); } inline void Vector4::operator+=(Vector4::Arg v) { m_x += v.m_x; m_y += v.m_y; m_z += v.m_z; m_w += v.m_w; } inline void Vector4::operator-=(Vector4::Arg v) { m_x -= v.m_x; m_y -= v.m_y; m_z -= v.m_z; m_w -= v.m_w; } inline void Vector4::operator*=(scalar s) { m_x *= s; m_y *= s; m_z *= s; m_w *= s; } inline void Vector4::operator*=(Vector4::Arg v) { m_x *= v.m_x; m_y *= v.m_y; m_z *= v.m_z; m_w *= v.m_w; } inline bool operator==(Vector4::Arg a, Vector4::Arg b) { return a.m_x == b.m_x && a.m_y == b.m_y && a.m_z == b.m_z && a.m_w == b.m_w; } inline bool operator!=(Vector4::Arg a, Vector4::Arg b) { return a.m_x != b.m_x || a.m_y != b.m_y || a.m_z != b.m_z || a.m_w != b.m_w; } // Functions // Vector2 inline Vector2 add(Vector2::Arg a, Vector2::Arg b) { return Vector2(a.x() + b.x(), a.y() + b.y()); } inline Vector2 operator+(Vector2::Arg a, Vector2::Arg b) { return add(a, b); } inline Vector2 sub(Vector2::Arg a, Vector2::Arg b) { return Vector2(a.x() - b.x(), a.y() - b.y()); } inline Vector2 operator-(Vector2::Arg a, Vector2::Arg b) { return sub(a, b); } inline Vector2 scale(Vector2::Arg v, scalar s) { return Vector2(v.x() * s, v.y() * s); } inline Vector2 scale(Vector2::Arg v, Vector2::Arg s) { return Vector2(v.x() * s.x(), v.y() * s.y()); } inline Vector2 operator*(Vector2::Arg v, scalar s) { return scale(v, s); } inline Vector2 operator*(Vector2::Arg v1, Vector2::Arg v2) { return Vector2(v1.x()*v2.x(), v1.y()*v2.y()); } inline Vector2 operator*(scalar s, Vector2::Arg v) { return scale(v, s); } inline scalar dot(Vector2::Arg a, Vector2::Arg b) { return a.x() * b.x() + a.y() * b.y(); } inline scalar length_squared(Vector2::Arg v) { return v.x() * v.x() + v.y() * v.y(); } inline scalar length(Vector2::Arg v) { return sqrtf(length_squared(v)); } inline bool equal(Vector2::Arg v1, Vector2::Arg v2, float epsilon = NV_EPSILON) { return equal(v1.x(), v2.x(), epsilon) && equal(v1.y(), v2.y(), epsilon); } inline Vector2 min(Vector2::Arg a, Vector2::Arg b) { return Vector2(min(a.x(), b.x()), min(a.y(), b.y())); } inline Vector2 max(Vector2::Arg a, Vector2::Arg b) { return Vector2(max(a.x(), b.x()), max(a.y(), b.y())); } inline bool isValid(Vector2::Arg v) { return isFinite(v.x()) && isFinite(v.y()); } // Vector3 inline Vector3 add(Vector3::Arg a, Vector3::Arg b) { return Vector3(a.x() + b.x(), a.y() + b.y(), a.z() + b.z()); } inline Vector3 add(Vector3::Arg a, float b) { return Vector3(a.x() + b, a.y() + b, a.z() + b); } inline Vector3 operator+(Vector3::Arg a, Vector3::Arg b) { return add(a, b); } inline Vector3 operator+(Vector3::Arg a, float b) { return add(a, b); } inline Vector3 sub(Vector3::Arg a, Vector3::Arg b) { return Vector3(a.x() - b.x(), a.y() - b.y(), a.z() - b.z()); } inline Vector3 sub(Vector3::Arg a, float b) { return Vector3(a.x() - b, a.y() - b, a.z() - b); } inline Vector3 operator-(Vector3::Arg a, Vector3::Arg b) { return sub(a, b); } inline Vector3 operator-(Vector3::Arg a, float b) { return sub(a, b); } inline Vector3 cross(Vector3::Arg a, Vector3::Arg b) { return Vector3(a.y() * b.z() - a.z() * b.y(), a.z() * b.x() - a.x() * b.z(), a.x() * b.y() - a.y() * b.x()); } inline Vector3 scale(Vector3::Arg v, scalar s) { return Vector3(v.x() * s, v.y() * s, v.z() * s); } inline Vector3 scale(Vector3::Arg v, Vector3::Arg s) { return Vector3(v.x() * s.x(), v.y() * s.y(), v.z() * s.z()); } inline Vector3 operator*(Vector3::Arg v, scalar s) { return scale(v, s); } inline Vector3 operator*(scalar s, Vector3::Arg v) { return scale(v, s); } inline Vector3 operator*(Vector3::Arg v, Vector3::Arg s) { return scale(v, s); } inline Vector3 operator/(Vector3::Arg v, scalar s) { return scale(v, 1.0f/s); } inline Vector3 add_scaled(Vector3::Arg a, Vector3::Arg b, scalar s) { return Vector3(a.x() + b.x() * s, a.y() + b.y() * s, a.z() + b.z() * s); } inline Vector3 lerp(Vector3::Arg v1, Vector3::Arg v2, scalar t) { const scalar s = 1.0f - t; return Vector3(v1.x() * s + t * v2.x(), v1.y() * s + t * v2.y(), v1.z() * s + t * v2.z()); } inline scalar dot(Vector3::Arg a, Vector3::Arg b) { return a.x() * b.x() + a.y() * b.y() + a.z() * b.z(); } inline scalar length_squared(Vector3::Arg v) { return v.x() * v.x() + v.y() * v.y() + v.z() * v.z(); } inline scalar length(Vector3::Arg v) { return sqrtf(length_squared(v)); } inline bool isNormalized(Vector3::Arg v, float epsilon = NV_NORMAL_EPSILON) { return equal(length(v), 1, epsilon); } inline Vector3 normalize(Vector3::Arg v, float epsilon = NV_EPSILON) { float l = length(v); nvDebugCheck(!isZero(l, epsilon)); Vector3 n = scale(v, 1.0f / l); nvDebugCheck(isNormalized(n)); return n; } inline Vector3 normalizeSafe(Vector3::Arg v, Vector3::Arg fallback, float epsilon = NV_EPSILON) { float l = length(v); if (isZero(l, epsilon)) { return fallback; } return scale(v, 1.0f / l); } inline bool equal(Vector3::Arg v1, Vector3::Arg v2, float epsilon = NV_EPSILON) { return equal(v1.x(), v2.x(), epsilon) && equal(v1.y(), v2.y(), epsilon) && equal(v1.z(), v2.z(), epsilon); } inline Vector3 min(Vector3::Arg a, Vector3::Arg b) { return Vector3(min(a.x(), b.x()), min(a.y(), b.y()), min(a.z(), b.z())); } inline Vector3 max(Vector3::Arg a, Vector3::Arg b) { return Vector3(max(a.x(), b.x()), max(a.y(), b.y()), max(a.z(), b.z())); } inline Vector3 clamp(Vector3::Arg v, float min, float max) { return Vector3(clamp(v.x(), min, max), clamp(v.y(), min, max), clamp(v.z(), min, max)); } inline bool isValid(Vector3::Arg v) { return isFinite(v.x()) && isFinite(v.y()) && isFinite(v.z()); } /* Vector3 transform(Quaternion, vector3); Vector3 transform_point(matrix34, vector3); Vector3 transform_vector(matrix34, vector3); Vector3 transform_point(matrix44, vector3); Vector3 transform_vector(matrix44, vector3); */ // Vector4 inline Vector4 add(Vector4::Arg a, Vector4::Arg b) { return Vector4(a.x() + b.x(), a.y() + b.y(), a.z() + b.z(), a.w() + b.w()); } inline Vector4 operator+(Vector4::Arg a, Vector4::Arg b) { return add(a, b); } inline Vector4 sub(Vector4::Arg a, Vector4::Arg b) { return Vector4(a.x() - b.x(), a.y() - b.y(), a.z() - b.z(), a.w() - b.w()); } inline Vector4 operator-(Vector4::Arg a, Vector4::Arg b) { return sub(a, b); } inline Vector4 scale(Vector4::Arg v, scalar s) { return Vector4(v.x() * s, v.y() * s, v.z() * s, v.w() * s); } inline Vector4 scale(Vector4::Arg v, Vector4::Arg s) { return Vector4(v.x() * s.x(), v.y() * s.y(), v.z() * s.z(), v.w() * s.w()); } inline Vector4 operator*(Vector4::Arg v, scalar s) { return scale(v, s); } inline Vector4 operator*(scalar s, Vector4::Arg v) { return scale(v, s); } inline Vector4 operator/(Vector4::Arg v, scalar s) { return scale(v, 1.0f/s); } inline Vector4 add_scaled(Vector4::Arg a, Vector4::Arg b, scalar s) { return Vector4(a.x() + b.x() * s, a.y() + b.y() * s, a.z() + b.z() * s, a.w() + b.w() * s); } inline scalar dot(Vector4::Arg a, Vector4::Arg b) { return a.x() * b.x() + a.y() * b.y() + a.z() * b.z() + a.w() * b.w(); } inline scalar length_squared(Vector4::Arg v) { return v.x() * v.x() + v.y() * v.y() + v.z() * v.z() + v.w() * v.w(); } inline scalar length(Vector4::Arg v) { return sqrtf(length_squared(v)); } inline bool isNormalized(Vector4::Arg v, float epsilon = NV_NORMAL_EPSILON) { return equal(length(v), 1, epsilon); } inline Vector4 normalize(Vector4::Arg v, float epsilon = NV_EPSILON) { float l = length(v); nvDebugCheck(!isZero(l, epsilon)); Vector4 n = scale(v, 1.0f / l); nvDebugCheck(isNormalized(n)); return n; } inline Vector4 normalizeSafe(Vector4::Arg v, Vector4::Arg fallback, float epsilon = NV_EPSILON) { float l = length(v); if (isZero(l, epsilon)) { return fallback; } return scale(v, 1.0f / l); } inline bool equal(Vector4::Arg v1, Vector4::Arg v2, float epsilon = NV_EPSILON) { return equal(v1.x(), v2.x(), epsilon) && equal(v1.y(), v2.y(), epsilon) && equal(v1.z(), v2.z(), epsilon) && equal(v1.w(), v2.w(), epsilon); } inline Vector4 min(Vector4::Arg a, Vector4::Arg b) { return Vector4(min(a.x(), b.x()), min(a.y(), b.y()), min(a.z(), b.z()), min(a.w(), b.w())); } inline Vector4 max(Vector4::Arg a, Vector4::Arg b) { return Vector4(max(a.x(), b.x()), max(a.y(), b.y()), max(a.z(), b.z()), max(a.w(), b.w())); } inline bool isValid(Vector4::Arg v) { return isFinite(v.x()) && isFinite(v.y()) && isFinite(v.z()) && isFinite(v.w()); } /* vector4 transform(matrix34, vector4); vector4 transform(matrix44, vector4); */ /* Quaternion mul(Quaternion, Quaternion); // rotational composition Quaternion conjugate(Quaternion); Quaternion inverse(Quaternion); Quaternion axis_angle(const Vector3 & v, scalar s); */ /* matrix34 add(matrix34, matrix34); // note: implicit '1' stays as '1' matrix34 operator+(matrix34, matrix34); matrix34 sub(matrix34, matrix34); // note: implicit '1' stays as '1' matrix34 operator-(matrix34, matrix34); matrix34 mul(matrix34, matrix34); matrix34 operator*(matrix34, matrix34); matrix34 mul(matrix34, quaternion4); // rotation multiplication matrix34 operator*(matrix34, quaternion4); // rotation multiplication matrix34 translation(vector3); matrix34 rotation(quaternion4); matrix34 rotation(vector3, scalar); // axis/angle matrix44 add(matrix44, matrix44); matrix44 operator+(matrix44, matrix44); matrix44 sub(matrix44, matrix44); matrix44 operator-(matrix44, matrix44); matrix44 mul(matrix44, matrix44); matrix44 operator*(matrix44, matrix44); matrix44 mul(matrix44, quaternion4); // rotation multiplication matrix44 operator*(matrix44, quaternion4); // rotation multiplication matrix44 invert(matrix34); matrix44 invert(matrix44); matrix44 transpose(matrix34); matrix44 transpose(matrix44); */ } // nv namespace #endif // NV_MATH_VECTOR_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvmath/nvmath.h000066400000000000000000000060531173441656100224520ustar00rootroot00000000000000// This code is in the public domain -- castanyo@yahoo.es #ifndef NV_MATH_H #define NV_MATH_H #include #include #include // Function linkage #if NVMATH_SHARED #ifdef NVMATH_EXPORTS #define NVMATH_API DLL_EXPORT #define NVMATH_CLASS DLL_EXPORT_CLASS #else #define NVMATH_API DLL_IMPORT #define NVMATH_CLASS DLL_IMPORT #endif #else // NVMATH_SHARED #define NVMATH_API #define NVMATH_CLASS #endif // NVMATH_SHARED #ifndef PI #define PI float(3.1415926535897932384626433833) #endif #define NV_EPSILON (0.0001f) #define NV_NORMAL_EPSILON (0.001f) /* #define SQ(r) ((r)*(r)) #define SIGN_BITMASK 0x80000000 /// Integer representation of a floating-point value. #define IR(x) ((uint32 &)(x)) /// Absolute integer representation of a floating-point value #define AIR(x) (IR(x) & 0x7fffffff) /// Floating-point representation of an integer value. #define FR(x) ((float&)(x)) /// Integer-based comparison of a floating point value. /// Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context. #define IS_NEGATIVE_FLOAT(x) (IR(x)&SIGN_BITMASK) */ inline double sqrt_assert(const double f) { nvDebugCheck(f >= 0.0f); return sqrt(f); } inline float sqrtf_assert(const float f) { nvDebugCheck(f >= 0.0f); return sqrtf(f); } inline double acos_assert(const double f) { nvDebugCheck(f >= -1.0f && f <= 1.0f); return acos(f); } inline float acosf_assert(const float f) { nvDebugCheck(f >= -1.0f && f <= 1.0f); return acosf(f); } inline double asin_assert(const double f) { nvDebugCheck(f >= -1.0f && f <= 1.0f); return asin(f); } inline float asinf_assert(const float f) { nvDebugCheck(f >= -1.0f && f <= 1.0f); return asinf(f); } // Replace default functions with asserting ones. #define sqrt sqrt_assert #define sqrtf sqrtf_assert #define acos acos_assert #define acosf acosf_assert #define asin asin_assert #define asinf asinf_assert #if NV_OS_WIN32 #include #endif namespace nv { inline float toRadian(float degree) { return degree * (PI / 180.0f); } inline float toDegree(float radian) { return radian * (180.0f / PI); } inline bool equal(const float f0, const float f1, const float epsilon = NV_EPSILON) { return fabs(f0-f1) <= epsilon; } inline bool isZero(const float f, const float epsilon = NV_EPSILON) { return fabs(f) <= epsilon; } inline bool isFinite(const float f) { #if NV_OS_WIN32 return _finite(f) != 0; #elif NV_OS_DARWIN return isfinite(f); #elif NV_OS_LINUX return finitef(f); #else # error "isFinite not supported" #endif //return std::isfinite (f); //return finite (f); } inline bool isNan(const float f) { #if NV_OS_WIN32 return _isnan(f) != 0; #elif NV_OS_DARWIN return isnan(f); #elif NV_OS_LINUX return isnanf(f); #else # error "isNan not supported" #endif } inline uint log2(uint i) { uint value = 0; while( i >>= 1 ) { value++; } return value; } inline float lerp(float f0, float f1, float t) { const float s = 1.0f - t; return f0 * s + f1 * t; } inline float square(float f) { return f * f; } } // nv #endif // NV_MATH_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/000077500000000000000000000000001173441656100204765ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/CMakeLists.txt000066400000000000000000000053201173441656100232360ustar00rootroot00000000000000PROJECT(nvtt) ADD_SUBDIRECTORY(squish) SET(NVTT_SRCS nvtt.h nvtt.cpp Compressor.h Compressor.cpp nvtt_wrapper.h nvtt_wrapper.cpp CompressDXT.h CompressDXT.cpp CompressRGB.h CompressRGB.cpp QuickCompressDXT.h QuickCompressDXT.cpp OptimalCompressDXT.h OptimalCompressDXT.cpp SingleColorLookup.h CompressionOptions.h CompressionOptions.cpp InputOptions.h InputOptions.cpp OutputOptions.h OutputOptions.cpp cuda/CudaUtils.h cuda/CudaUtils.cpp cuda/CudaMath.h cuda/Bitmaps.h cuda/CudaCompressDXT.h cuda/CudaCompressDXT.cpp) IF(CUDA_FOUND) ADD_DEFINITIONS(-DHAVE_CUDA) WRAP_CUDA(CUDA_SRCS cuda/CompressKernel.cu) SET(NVTT_SRCS ${NVTT_SRCS} ${CUDA_SRCS}) SET(LIBS ${LIBS} ${CUDA_LIBRARIES}) INCLUDE_DIRECTORIES(${CUDA_INCLUDE_PATH}) ENDIF(CUDA_FOUND) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) ADD_DEFINITIONS(-DNVTT_EXPORTS) IF(NVTT_SHARED) ADD_DEFINITIONS(-DNVTT_SHARED=1) ADD_LIBRARY(nvtt SHARED ${NVTT_SRCS}) ELSE(NVTT_SHARED) ADD_LIBRARY(nvtt ${NVTT_SRCS}) ENDIF(NVTT_SHARED) TARGET_LINK_LIBRARIES(nvtt ${LIBS} nvcore nvmath nvimage squish) INSTALL(TARGETS nvtt RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib/static) INSTALL(FILES nvtt.h DESTINATION include/nvtt) # test executables ADD_EXECUTABLE(nvcompress tools/compress.cpp tools/cmdline.h) TARGET_LINK_LIBRARIES(nvcompress nvcore nvmath nvimage nvtt) ADD_EXECUTABLE(nvdecompress tools/decompress.cpp tools/cmdline.h) TARGET_LINK_LIBRARIES(nvdecompress nvcore nvmath nvimage) ADD_EXECUTABLE(nvddsinfo tools/ddsinfo.cpp tools/cmdline.h) TARGET_LINK_LIBRARIES(nvddsinfo nvcore nvmath nvimage) ADD_EXECUTABLE(nvimgdiff tools/imgdiff.cpp tools/cmdline.h) TARGET_LINK_LIBRARIES(nvimgdiff nvcore nvmath nvimage) ADD_EXECUTABLE(nvassemble tools/assemble.cpp tools/cmdline.h) TARGET_LINK_LIBRARIES(nvassemble nvcore nvmath nvimage) ADD_EXECUTABLE(filtertest tests/filtertest.cpp tools/cmdline.h) TARGET_LINK_LIBRARIES(filtertest nvcore nvmath nvimage) ADD_EXECUTABLE(nvzoom tools/resize.cpp tools/cmdline.h) TARGET_LINK_LIBRARIES(nvzoom nvcore nvmath nvimage) INSTALL(TARGETS nvcompress nvdecompress nvddsinfo nvimgdiff nvassemble nvzoom DESTINATION bin) # UI tools IF(QT4_FOUND AND NOT MSVC) SET(QT_USE_QTOPENGL TRUE) INCLUDE_DIRECTORIES(${QT_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) SET(SRCS tools/main.cpp tools/configdialog.h tools/configdialog.cpp) SET(LIBS nvtt ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY}) QT4_WRAP_UI(UICS tools/configdialog.ui) QT4_WRAP_CPP(MOCS tools/configdialog.h) #QT4_ADD_RESOURCES(RCCS tools/configdialog.rc) ADD_EXECUTABLE(nvcompressui MACOSX_BUNDLE ${SRCS} ${UICS} ${MOCS}) TARGET_LINK_LIBRARIES(nvcompressui ${LIBS}) ENDIF(QT4_FOUND AND NOT MSVC) nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/CompressDXT.cpp000066400000000000000000000365131173441656100233650ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include "nvtt.h" #include "CompressDXT.h" #include "QuickCompressDXT.h" #include "OptimalCompressDXT.h" #include "CompressionOptions.h" #include "OutputOptions.h" // squish #include "squish/colourset.h" //#include "squish/clusterfit.h" #include "squish/fastclusterfit.h" #include "squish/weightedclusterfit.h" // s3_quant #if defined(HAVE_S3QUANT) #include "s3tc/s3_quant.h" #endif // ati tc #if defined(HAVE_ATITC) #include "atitc/ATI_Compress.h" #endif //#include using namespace nv; using namespace nvtt; nv::FastCompressor::FastCompressor() : m_image(NULL), m_alphaMode(AlphaMode_None) { } nv::FastCompressor::~FastCompressor() { } void nv::FastCompressor::setImage(const Image * image, nvtt::AlphaMode alphaMode) { m_image = image; m_alphaMode = alphaMode; } void nv::FastCompressor::compressDXT1(const OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT1 block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); QuickCompress::compressDXT1(rgba, &block); if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::FastCompressor::compressDXT1a(const OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT1 block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); QuickCompress::compressDXT1a(rgba, &block); if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::FastCompressor::compressDXT3(const nvtt::OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT3 block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); QuickCompress::compressDXT3(rgba, &block); if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::FastCompressor::compressDXT5(const nvtt::OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT5 block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); QuickCompress::compressDXT5(rgba, &block, 0); if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::FastCompressor::compressDXT5n(const nvtt::OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT5 block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); rgba.swizzleDXT5n(); QuickCompress::compressDXT5(rgba, &block, 0); if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } nv::SlowCompressor::SlowCompressor() : m_image(NULL), m_alphaMode(AlphaMode_None) { } nv::SlowCompressor::~SlowCompressor() { } void nv::SlowCompressor::setImage(const Image * image, nvtt::AlphaMode alphaMode) { m_image = image; m_alphaMode = alphaMode; } void nv::SlowCompressor::compressDXT1(const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT1 block; squish::WeightedClusterFit fit; //squish::ClusterFit fit; //squish::FastClusterFit fit; fit.SetMetric(compressionOptions.colorWeight.x(), compressionOptions.colorWeight.y(), compressionOptions.colorWeight.z()); for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); if (rgba.isSingleColor()) { OptimalCompress::compressDXT1(rgba.color(0), &block); } else { squish::ColourSet colours((uint8 *)rgba.colors(), 0, true); fit.SetColourSet(&colours, squish::kDxt1); fit.Compress(&block); } if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::SlowCompressor::compressDXT1a(const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT1 block; squish::WeightedClusterFit fit; fit.SetMetric(compressionOptions.colorWeight.x(), compressionOptions.colorWeight.y(), compressionOptions.colorWeight.z()); for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); bool anyAlpha = false; bool allAlpha = true; for (uint i = 0; i < 16; i++) { if (rgba.color(i).a < 128) anyAlpha = true; else allAlpha = false; } if ((!anyAlpha && rgba.isSingleColor() || allAlpha)) { OptimalCompress::compressDXT1a(rgba.color(0), &block); } else { squish::ColourSet colours((uint8 *)rgba.colors(), squish::kDxt1|squish::kWeightColourByAlpha); fit.SetColourSet(&colours, squish::kDxt1); fit.Compress(&block); } if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::SlowCompressor::compressDXT3(const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT3 block; squish::WeightedClusterFit fit; //squish::FastClusterFit fit; fit.SetMetric(compressionOptions.colorWeight.x(), compressionOptions.colorWeight.y(), compressionOptions.colorWeight.z()); for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); // Compress explicit alpha. OptimalCompress::compressDXT3A(rgba, &block.alpha); // Compress color. if (rgba.isSingleColor()) { OptimalCompress::compressDXT1(rgba.color(0), &block.color); } else { squish::ColourSet colours((uint8 *)rgba.colors(), squish::kWeightColourByAlpha); fit.SetColourSet(&colours, 0); fit.Compress(&block.color); } if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::SlowCompressor::compressDXT5(const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT5 block; squish::WeightedClusterFit fit; fit.SetMetric(compressionOptions.colorWeight.x(), compressionOptions.colorWeight.y(), compressionOptions.colorWeight.z()); for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); // Compress alpha. if (compressionOptions.quality == Quality_Highest) { OptimalCompress::compressDXT5A(rgba, &block.alpha); } else { QuickCompress::compressDXT5A(rgba, &block.alpha); } // Compress color. if (rgba.isSingleColor()) { OptimalCompress::compressDXT1(rgba.color(0), &block.color); } else { squish::ColourSet colours((uint8 *)rgba.colors(), squish::kWeightColourByAlpha); fit.SetColourSet(&colours, 0); fit.Compress(&block.color); } if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::SlowCompressor::compressDXT5n(const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; BlockDXT5 block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); rgba.swizzleDXT5n(); // Compress X. if (compressionOptions.quality == Quality_Highest) { OptimalCompress::compressDXT5A(rgba, &block.alpha); } else { QuickCompress::compressDXT5A(rgba, &block.alpha); } // Compress Y. OptimalCompress::compressDXT1G(rgba, &block.color); if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::SlowCompressor::compressBC4(const CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock rgba; AlphaBlockDXT5 block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { rgba.init(m_image, x, y); if (compressionOptions.quality == Quality_Highest) { OptimalCompress::compressDXT5A(rgba, &block); } else { QuickCompress::compressDXT5A(rgba, &block); } if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } void nv::SlowCompressor::compressBC5(const CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions) { const uint w = m_image->width(); const uint h = m_image->height(); ColorBlock xcolor; ColorBlock ycolor; BlockATI2 block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { xcolor.init(m_image, x, y); xcolor.splatX(); ycolor.init(m_image, x, y); ycolor.splatY(); if (compressionOptions.quality == Quality_Highest) { OptimalCompress::compressDXT5A(xcolor, &block.x); OptimalCompress::compressDXT5A(ycolor, &block.y); } else { QuickCompress::compressDXT5A(xcolor, &block.x); QuickCompress::compressDXT5A(ycolor, &block.y); } if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&block, sizeof(block)); } } } } #if defined(HAVE_S3QUANT) void nv::s3CompressDXT1(const Image * image, const nvtt::OutputOptions::Private & outputOptions) { const uint w = image->width(); const uint h = image->height(); float error = 0.0f; BlockDXT1 dxtBlock3; BlockDXT1 dxtBlock4; ColorBlock block; for (uint y = 0; y < h; y += 4) { for (uint x = 0; x < w; x += 4) { block.init(image, x, y); // Init rgb block. RGBBlock rgbBlock; rgbBlock.n = 16; for (uint i = 0; i < 16; i++) { rgbBlock.colorChannel[i][0] = clamp(float(block.color(i).r) / 255.0f, 0.0f, 1.0f); rgbBlock.colorChannel[i][1] = clamp(float(block.color(i).g) / 255.0f, 0.0f, 1.0f); rgbBlock.colorChannel[i][2] = clamp(float(block.color(i).b) / 255.0f, 0.0f, 1.0f); } rgbBlock.weight[0] = 1.0f; rgbBlock.weight[1] = 1.0f; rgbBlock.weight[2] = 1.0f; rgbBlock.inLevel = 4; CodeRGBBlock(&rgbBlock); // Copy results to DXT block. dxtBlock4.col0.r = rgbBlock.endPoint[0][0]; dxtBlock4.col0.g = rgbBlock.endPoint[0][1]; dxtBlock4.col0.b = rgbBlock.endPoint[0][2]; dxtBlock4.col1.r = rgbBlock.endPoint[1][0]; dxtBlock4.col1.g = rgbBlock.endPoint[1][1]; dxtBlock4.col1.b = rgbBlock.endPoint[1][2]; dxtBlock4.setIndices(rgbBlock.index); if (dxtBlock4.col0.u < dxtBlock4.col1.u) { swap(dxtBlock4.col0.u, dxtBlock4.col1.u); dxtBlock4.indices ^= 0x55555555; } uint error4 = blockError(block, dxtBlock4); rgbBlock.inLevel = 3; CodeRGBBlock(&rgbBlock); // Copy results to DXT block. dxtBlock3.col0.r = rgbBlock.endPoint[0][0]; dxtBlock3.col0.g = rgbBlock.endPoint[0][1]; dxtBlock3.col0.b = rgbBlock.endPoint[0][2]; dxtBlock3.col1.r = rgbBlock.endPoint[1][0]; dxtBlock3.col1.g = rgbBlock.endPoint[1][1]; dxtBlock3.col1.b = rgbBlock.endPoint[1][2]; dxtBlock3.setIndices(rgbBlock.index); if (dxtBlock3.col0.u > dxtBlock3.col1.u) { swap(dxtBlock3.col0.u, dxtBlock3.col1.u); dxtBlock3.indices ^= (~dxtBlock3.indices >> 1) & 0x55555555; } uint error3 = blockError(block, dxtBlock3); if (error3 < error4) { error += error3; if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&dxtBlock3, sizeof(dxtBlock3)); } } else { error += error4; if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(&dxtBlock4, sizeof(dxtBlock4)); } } } } printf("error = %f\n", error/((w+3)/4 * (h+3)/4)); } #endif // defined(HAVE_S3QUANT) #if defined(HAVE_ATITC) void nv::atiCompressDXT1(const Image * image, const OutputOptions::Private & outputOptions) { // Init source texture ATI_TC_Texture srcTexture; srcTexture.dwSize = sizeof(srcTexture); srcTexture.dwWidth = image->width(); srcTexture.dwHeight = image->height(); srcTexture.dwPitch = image->width() * 4; srcTexture.format = ATI_TC_FORMAT_ARGB_8888; srcTexture.dwDataSize = ATI_TC_CalculateBufferSize(&srcTexture); srcTexture.pData = (ATI_TC_BYTE*) image->pixels(); // Init dest texture ATI_TC_Texture destTexture; destTexture.dwSize = sizeof(destTexture); destTexture.dwWidth = image->width(); destTexture.dwHeight = image->height(); destTexture.dwPitch = 0; destTexture.format = ATI_TC_FORMAT_DXT1; destTexture.dwDataSize = ATI_TC_CalculateBufferSize(&destTexture); destTexture.pData = (ATI_TC_BYTE*) mem::malloc(destTexture.dwDataSize); // Compress ATI_TC_ConvertTexture(&srcTexture, &destTexture, NULL, NULL, NULL, NULL); if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(destTexture.pData, destTexture.dwDataSize); } } #endif // defined(HAVE_ATITC) nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/CompressDXT.h000066400000000000000000000066311173441656100230300ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_COMPRESSDXT_H #define NV_TT_COMPRESSDXT_H #include #include "nvtt.h" namespace nv { class Image; class FloatImage; class FastCompressor { public: FastCompressor(); ~FastCompressor(); void setImage(const Image * image, nvtt::AlphaMode alphaMode); void compressDXT1(const nvtt::OutputOptions::Private & outputOptions); void compressDXT1a(const nvtt::OutputOptions::Private & outputOptions); void compressDXT3(const nvtt::OutputOptions::Private & outputOptions); void compressDXT5(const nvtt::OutputOptions::Private & outputOptions); void compressDXT5n(const nvtt::OutputOptions::Private & outputOptions); private: const Image * m_image; nvtt::AlphaMode m_alphaMode; }; class SlowCompressor { public: SlowCompressor(); ~SlowCompressor(); void setImage(const Image * image, nvtt::AlphaMode alphaMode); void compressDXT1(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); void compressDXT1a(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); void compressDXT3(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); void compressDXT5(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); void compressDXT5n(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); void compressBC4(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); void compressBC5(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); private: const Image * m_image; nvtt::AlphaMode m_alphaMode; }; // External compressors. #if defined(HAVE_S3QUANT) void s3CompressDXT1(const Image * image, const nvtt::OutputOptions::Private & outputOptions); #endif #if defined(HAVE_ATITC) void atiCompressDXT1(const Image * image, const nvtt::OutputOptions::Private & outputOptions); #endif } // nv namespace #endif // NV_TT_COMPRESSDXT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/CompressRGB.cpp000066400000000000000000000100101173441656100233200ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include "CompressRGB.h" #include "CompressionOptions.h" #include "OutputOptions.h" using namespace nv; using namespace nvtt; namespace { inline uint computePitch(uint w, uint bitsize) { uint p = w * ((bitsize + 7) / 8); // Align to 32 bits. return ((p + 3) / 4) * 4; } inline void convert_to_a8r8g8b8(const void * src, void * dst, uint w) { memcpy(dst, src, 4 * w); } inline void convert_to_x8r8g8b8(const void * src, void * dst, uint w) { memcpy(dst, src, 4 * w); } } // namespace // Pixel format converter. void nv::compressRGB(const Image * image, const OutputOptions::Private & outputOptions, const CompressionOptions::Private & compressionOptions) { nvCheck(image != NULL); const uint w = image->width(); const uint h = image->height(); const uint bitCount = compressionOptions.bitcount; nvCheck(bitCount == 8 || bitCount == 16 || bitCount == 24 || bitCount == 32); const uint byteCount = bitCount / 8; const uint rmask = compressionOptions.rmask; uint rshift, rsize; PixelFormat::maskShiftAndSize(rmask, &rshift, &rsize); const uint gmask = compressionOptions.gmask; uint gshift, gsize; PixelFormat::maskShiftAndSize(gmask, &gshift, &gsize); const uint bmask = compressionOptions.bmask; uint bshift, bsize; PixelFormat::maskShiftAndSize(bmask, &bshift, &bsize); const uint amask = compressionOptions.amask; uint ashift, asize; PixelFormat::maskShiftAndSize(amask, &ashift, &asize); // Determine pitch. uint pitch = computePitch(w, compressionOptions.bitcount); uint8 * dst = (uint8 *)mem::malloc(pitch + 4); for (uint y = 0; y < h; y++) { const Color32 * src = image->scanline(y); if (bitCount == 32 && rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0xFF000000) { convert_to_a8r8g8b8(src, dst, w); } else if (bitCount == 32 && rmask == 0xFF0000 && gmask == 0xFF00 && bmask == 0xFF && amask == 0) { convert_to_x8r8g8b8(src, dst, w); } else { // Generic pixel format conversion. for (uint x = 0; x < w; x++) { uint c = 0; c |= PixelFormat::convert(src[x].r, 8, rsize) << rshift; c |= PixelFormat::convert(src[x].g, 8, gsize) << gshift; c |= PixelFormat::convert(src[x].b, 8, bsize) << bshift; c |= PixelFormat::convert(src[x].a, 8, asize) << ashift; // Output one byte at a time. for (uint i = 0; i < byteCount; i++) { *(dst + x * byteCount + i) = (c >> (i * 8)) & 0xFF; } } // Zero padding. for (uint x = w * byteCount; x < pitch; x++) { *(dst + x) = 0; } } if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(dst, pitch); } } mem::free(dst); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/CompressRGB.h000066400000000000000000000030111173441656100227700ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_COMPRESSRGB_H #define NV_TT_COMPRESSRGB_H #include "nvtt.h" namespace nv { class Image; // Pixel format converter. void compressRGB(const Image * image, const nvtt::OutputOptions::Private & outputOptions, const nvtt::CompressionOptions::Private & compressionOptions); } // nv namespace #endif // NV_TT_COMPRESSDXT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/CompressionOptions.cpp000066400000000000000000000105031173441656100250560ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 "nvtt.h" #include "CompressionOptions.h" using namespace nv; using namespace nvtt; /// Constructor. Sets compression options to the default values. CompressionOptions::CompressionOptions() : m(*new CompressionOptions::Private()) { reset(); } /// Destructor. CompressionOptions::~CompressionOptions() { delete &m; } /// Set default compression options. void CompressionOptions::reset() { m.format = Format_DXT1; m.quality = Quality_Normal; m.colorWeight.set(1.0f, 1.0f, 1.0f, 1.0f); m.bitcount = 32; m.bmask = 0x000000FF; m.gmask = 0x0000FF00; m.rmask = 0x00FF0000; m.amask = 0xFF000000; m.enableColorDithering = false; m.enableAlphaDithering = false; m.binaryAlpha = false; m.alphaThreshold = 127; } /// Set desired compression format. void CompressionOptions::setFormat(Format format) { m.format = format; } /// Set compression quality settings. void CompressionOptions::setQuality(Quality quality) { m.quality = quality; } /// Set the weights of each color channel. /// The choice for these values is subjective. In many case uniform color weights /// (1.0, 1.0, 1.0) work very well. A popular choice is to use the NTSC luma encoding /// weights (0.2126, 0.7152, 0.0722), but I think that blue contributes to our /// perception more than a 7%. A better choice in my opinion is (3, 4, 2). void CompressionOptions::setColorWeights(float red, float green, float blue, float alpha/*=1.0f*/) { // float total = red + green + blue; // float x = red / total; // float y = green / total; // m.colorWeight.set(x, y, 1.0f - x - y); m.colorWeight.set(red, green, blue, alpha); } /// Set color mask to describe the RGB/RGBA format. void CompressionOptions::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { // Validate arguments. nvCheck(bitcount == 8 || bitcount == 16 || bitcount == 24 || bitcount == 32); nvCheck((rmask & gmask) == 0); nvCheck((rmask & bmask) == 0); nvCheck((rmask & amask) == 0); nvCheck((gmask & bmask) == 0); nvCheck((gmask & amask) == 0); nvCheck((bmask & amask) == 0); if (bitcount != 32) { uint maxMask = (1 << bitcount); nvCheck(maxMask > rmask); nvCheck(maxMask > gmask); nvCheck(maxMask > bmask); nvCheck(maxMask > amask); } m.bitcount = bitcount; m.rmask = rmask; m.gmask = gmask; m.bmask = bmask; m.amask = amask; } /// Use external compressor. void CompressionOptions::setExternalCompressor(const char * name) { m.externalCompressor = name; } /// Set quantization options. /// @warning Do not enable dithering unless you know what you are doing. Quantization /// introduces errors. It's better to let the compressor quantize the result to /// minimize the error, instead of quantizing the data before handling it to /// the compressor. void CompressionOptions::setQuantization(bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold/*= 127*/) { nvCheck(alphaThreshold >= 0 && alphaThreshold < 256); m.enableColorDithering = colorDithering; m.enableAlphaDithering = alphaDithering; m.binaryAlpha = binaryAlpha; m.alphaThreshold = alphaThreshold; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/CompressionOptions.h000066400000000000000000000035311173441656100245260ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_COMPRESSIONOPTIONS_H #define NV_TT_COMPRESSIONOPTIONS_H #include #include #include "nvtt.h" namespace nvtt { struct CompressionOptions::Private { Format format; Quality quality; nv::Vector4 colorWeight; // Pixel format description. uint bitcount; uint rmask; uint gmask; uint bmask; uint amask; nv::String externalCompressor; // Quantization. bool enableColorDithering; bool enableAlphaDithering; bool binaryAlpha; int alphaThreshold; // reference value used for binary alpha quantization. }; } // nvtt namespace #endif // NV_TT_COMPRESSIONOPTIONS_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/Compressor.cpp000066400000000000000000000546231173441656100233500ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2008 -- Ignacio Castano // // 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 #include #include #include #include #include #include #include #include #include #include #include #include "Compressor.h" #include "InputOptions.h" #include "CompressionOptions.h" #include "OutputOptions.h" #include "CompressDXT.h" #include "CompressRGB.h" #include "cuda/CudaUtils.h" #include "cuda/CudaCompressDXT.h" using namespace nv; using namespace nvtt; namespace { static int blockSize(Format format) { if (format == Format_DXT1 || format == Format_DXT1a) { return 8; } else if (format == Format_DXT3) { return 16; } else if (format == Format_DXT5 || format == Format_DXT5n) { return 16; } else if (format == Format_BC4) { return 8; } else if (format == Format_BC5) { return 16; } return 0; } inline uint computePitch(uint w, uint bitsize) { uint p = w * ((bitsize + 7) / 8); // Align to 32 bits. return ((p + 3) / 4) * 4; } static int computeImageSize(uint w, uint h, uint d, uint bitCount, Format format) { if (format == Format_RGBA) { return d * h * computePitch(w, bitCount); } else { // @@ Handle 3D textures. DXT and VTC have different behaviors. return ((w + 3) / 4) * ((h + 3) / 4) * blockSize(format); } } } // namespace namespace nvtt { // Mipmap could be: // - a pointer to an input image. // - a fixed point image. // - a floating point image. struct Mipmap { Mipmap() : m_inputImage(NULL) {} ~Mipmap() {} // Reference input image. void setFromInput(const InputOptions::Private & inputOptions, uint idx) { m_inputImage = inputOptions.image(idx); m_fixedImage = NULL; m_floatImage = NULL; } // Assign and take ownership of given image. void setImage(FloatImage * image) { m_inputImage = NULL; m_fixedImage = NULL; m_floatImage = image; } // Convert linear float image to fixed image ready for compression. void toFixedImage(const InputOptions::Private & inputOptions) { if (m_floatImage != NULL) // apfaffe - We should check that we have a float image, if so convert it! { if (inputOptions.isNormalMap || inputOptions.outputGamma == 1.0f) { m_fixedImage = m_floatImage->createImage(); } else { m_fixedImage = m_floatImage->createImageGammaCorrect(inputOptions.outputGamma); } } } // Convert input image to linear float image. void toFloatImage(const InputOptions::Private & inputOptions) { if (m_floatImage == NULL) { nvDebugCheck(this->asFixedImage() != NULL); m_floatImage = new FloatImage(this->asFixedImage()); if (inputOptions.isNormalMap) { // Expand normals to [-1, 1] range. // floatImage->expandNormals(0); } else if (inputOptions.inputGamma != 1.0f) { // Convert to linear space. m_floatImage->toLinear(0, 3, inputOptions.inputGamma); } } } const FloatImage * asFloatImage() const { return m_floatImage.ptr(); } FloatImage * asFloatImage() { return m_floatImage.ptr(); } const Image * asFixedImage() const { // - apfaffe - switched logic to return the 'processed image' rather than the input! if (m_fixedImage != NULL && m_fixedImage.ptr() != NULL) { return m_fixedImage.ptr(); } return m_inputImage; } Image * asMutableFixedImage() { if (m_inputImage != NULL) { // Do not modify input image, create a copy. m_fixedImage = new Image(*m_inputImage); m_inputImage = NULL; } return m_fixedImage.ptr(); } private: const Image * m_inputImage; AutoPtr m_fixedImage; AutoPtr m_floatImage; }; } // nvtt namespace Compressor::Compressor() : m(*new Compressor::Private()) { // CUDA initialization. m.cudaSupported = cuda::isHardwarePresent(); m.cudaEnabled = false; m.cudaDevice = -1; enableCudaAcceleration(m.cudaSupported); } Compressor::~Compressor() { enableCudaAcceleration(false); delete &m; } /// Enable CUDA acceleration. void Compressor::enableCudaAcceleration(bool enable) { if (m.cudaSupported) { if (m.cudaEnabled && !enable) { m.cudaEnabled = false; m.cuda = NULL; if (m.cudaDevice != -1) { // Exit device. cuda::exitDevice(); } } else if (!m.cudaEnabled && enable) { // Init the CUDA device. This may return -1 if CUDA was already initialized by the app. m.cudaEnabled = cuda::initDevice(&m.cudaDevice); if (m.cudaEnabled) { // Create compressor if initialization succeeds. m.cuda = new CudaCompressor(); // But cleanup if failed. if (!m.cuda->isValid()) { enableCudaAcceleration(false); } } } } } /// Check if CUDA acceleration is enabled. bool Compressor::isCudaAccelerationEnabled() const { return m.cudaEnabled; } /// Compress the input texture with the given compression options. bool Compressor::process(const InputOptions & inputOptions, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const { return m.compress(inputOptions.m, compressionOptions.m, outputOptions.m); } /// Estimate the size of compressing the input with the given options. int Compressor::estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions) const { return m.estimateSize(inputOptions.m, compressionOptions.m); } bool Compressor::Private::compress(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const { // Make sure enums match. nvStaticCheck(FloatImage::WrapMode_Clamp == (FloatImage::WrapMode)WrapMode_Clamp); nvStaticCheck(FloatImage::WrapMode_Mirror == (FloatImage::WrapMode)WrapMode_Mirror); nvStaticCheck(FloatImage::WrapMode_Repeat == (FloatImage::WrapMode)WrapMode_Repeat); // Get output handler. if (!outputOptions.openFile()) { if (outputOptions.errorHandler) outputOptions.errorHandler->error(Error_FileOpen); return false; } inputOptions.computeTargetExtents(); // Output DDS header. if (!outputHeader(inputOptions, compressionOptions, outputOptions)) { return false; } for (uint f = 0; f < inputOptions.faceCount; f++) { if (!compressMipmaps(f, inputOptions, compressionOptions, outputOptions)) { return false; } } outputOptions.closeFile(); return true; } // Output DDS header. bool Compressor::Private::outputHeader(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const { // Output DDS header. if (outputOptions.outputHandler == NULL || !outputOptions.outputHeader) { return true; } DDSHeader header; header.setWidth(inputOptions.targetWidth); header.setHeight(inputOptions.targetHeight); int mipmapCount = inputOptions.realMipmapCount(); nvDebugCheck(mipmapCount > 0); header.setMipmapCount(mipmapCount); if (inputOptions.textureType == TextureType_2D) { header.setTexture2D(); } else if (inputOptions.textureType == TextureType_Cube) { header.setTextureCube(); } /*else if (inputOptions.textureType == TextureType_3D) { header.setTexture3D(); header.setDepth(inputOptions.targetDepth); }*/ if (compressionOptions.format == Format_RGBA) { header.setPitch(computePitch(inputOptions.targetWidth, compressionOptions.bitcount)); header.setPixelFormat(compressionOptions.bitcount, compressionOptions.rmask, compressionOptions.gmask, compressionOptions.bmask, compressionOptions.amask); } else { header.setLinearSize(computeImageSize(inputOptions.targetWidth, inputOptions.targetHeight, inputOptions.targetDepth, compressionOptions.bitcount, compressionOptions.format)); if (compressionOptions.format == Format_DXT1 || compressionOptions.format == Format_DXT1a) { header.setFourCC('D', 'X', 'T', '1'); if (inputOptions.isNormalMap) header.setNormalFlag(true); } else if (compressionOptions.format == Format_DXT3) { header.setFourCC('D', 'X', 'T', '3'); } else if (compressionOptions.format == Format_DXT5) { header.setFourCC('D', 'X', 'T', '5'); } else if (compressionOptions.format == Format_DXT5n) { header.setFourCC('D', 'X', 'T', '5'); if (inputOptions.isNormalMap) header.setNormalFlag(true); } else if (compressionOptions.format == Format_BC4) { header.setFourCC('A', 'T', 'I', '1'); } else if (compressionOptions.format == Format_BC5) { header.setFourCC('A', 'T', 'I', '2'); if (inputOptions.isNormalMap) header.setNormalFlag(true); } } // Swap bytes if necessary. header.swapBytes(); uint headerSize = 128; if (header.hasDX10Header()) { nvStaticCheck(sizeof(DDSHeader) == 128 + 20); headerSize = 128 + 20; } bool writeSucceed = outputOptions.outputHandler->writeData(&header, headerSize); if (!writeSucceed && outputOptions.errorHandler != NULL) { outputOptions.errorHandler->error(Error_FileWrite); } return writeSucceed; } bool Compressor::Private::compressMipmaps(uint f, const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const { uint w = inputOptions.targetWidth; uint h = inputOptions.targetHeight; uint d = inputOptions.targetDepth; Mipmap mipmap; const uint mipmapCount = inputOptions.realMipmapCount(); nvDebugCheck(mipmapCount > 0); for (uint m = 0; m < mipmapCount; m++) { if (outputOptions.outputHandler) { int size = computeImageSize(w, h, d, compressionOptions.bitcount, compressionOptions.format); outputOptions.outputHandler->beginImage(size, w, h, d, f, m); } // @@ Where to do the color transform? // - Color transform may not be linear, so we cannot do before computing mipmaps. // - Should be done in linear space, that is, after gamma correction. if (!initMipmap(mipmap, inputOptions, w, h, d, f, m)) { if (outputOptions.errorHandler != NULL) { outputOptions.errorHandler->error(Error_InvalidInput); return false; } } quantizeMipmap(mipmap, compressionOptions); compressMipmap(mipmap, inputOptions, compressionOptions, outputOptions); // Compute extents of next mipmap: w = max(1U, w / 2); h = max(1U, h / 2); d = max(1U, d / 2); } return true; } bool Compressor::Private::initMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f, uint m) const { // Find image from input. int inputIdx = findExactMipmap(inputOptions, w, h, d, f); if ((inputIdx == -1 || inputOptions.convertToNormalMap) && m != 0) { // Generate from last, when mipmap not found, or normal map conversion enabled. downsampleMipmap(mipmap, inputOptions); } else { if (inputIdx != -1) { // If input mipmap found, then get from input. mipmap.setFromInput(inputOptions, inputIdx); } else { // If not found, resize closest mipmap. inputIdx = findClosestMipmap(inputOptions, w, h, d, f); if (inputIdx == -1) { return false; } mipmap.setFromInput(inputOptions, inputIdx); scaleMipmap(mipmap, inputOptions, w, h, d); } processInputImage(mipmap, inputOptions); } // Convert linear float image to fixed image ready for compression. mipmap.toFixedImage(inputOptions); return true; } int Compressor::Private::findExactMipmap(const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f) const { for (int m = 0; m < int(inputOptions.mipmapCount); m++) { int idx = f * inputOptions.mipmapCount + m; const InputOptions::Private::InputImage & inputImage = inputOptions.images[idx]; if (inputImage.width == int(w) && inputImage.height == int(h) && inputImage.depth == int(d)) { if (inputImage.data != NULL) { return idx; } return -1; } else if (inputImage.width < int(w) || inputImage.height < int(h) || inputImage.depth < int(d)) { return -1; } } return -1; } int Compressor::Private::findClosestMipmap(const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f) const { int bestIdx = -1; for (int m = 0; m < int(inputOptions.mipmapCount); m++) { int idx = f * inputOptions.mipmapCount + m; const InputOptions::Private::InputImage & inputImage = inputOptions.images[idx]; if (inputImage.data != NULL) { int difference = (inputImage.width - w) + (inputImage.height - h) + (inputImage.depth - d); if (difference < 0) { if (bestIdx == -1) { bestIdx = idx; } return bestIdx; } bestIdx = idx; } } return bestIdx; } // Create mipmap from the given image. void Compressor::Private::downsampleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const { // Make sure that floating point linear representation is available. mipmap.toFloatImage(inputOptions); const FloatImage * floatImage = mipmap.asFloatImage(); if (inputOptions.mipmapFilter == MipmapFilter_Box) { // Use fast downsample. mipmap.setImage(floatImage->fastDownSample()); } else if (inputOptions.mipmapFilter == MipmapFilter_Triangle) { TriangleFilter filter; mipmap.setImage(floatImage->downSample(filter, (FloatImage::WrapMode)inputOptions.wrapMode)); } else /*if (inputOptions.mipmapFilter == MipmapFilter_Kaiser)*/ { nvDebugCheck(inputOptions.mipmapFilter == MipmapFilter_Kaiser); KaiserFilter filter(inputOptions.kaiserWidth); filter.setParameters(inputOptions.kaiserAlpha, inputOptions.kaiserStretch); mipmap.setImage(floatImage->downSample(filter, (FloatImage::WrapMode)inputOptions.wrapMode)); } // Normalize mipmap. if ((inputOptions.isNormalMap || inputOptions.convertToNormalMap) && inputOptions.normalizeMipmaps) { normalizeNormalMap(mipmap.asFloatImage()); } } void Compressor::Private::scaleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d) const { mipmap.toFloatImage(inputOptions); // @@ Add more filters. // @@ Select different filters for downscaling and reconstruction. // Resize image. BoxFilter boxFilter; mipmap.setImage(mipmap.asFloatImage()->resize(boxFilter, w, h, (FloatImage::WrapMode)inputOptions.wrapMode)); } // Process an input image: Convert to normal map, normalize, or convert to linear space. void Compressor::Private::processInputImage(Mipmap & mipmap, const InputOptions::Private & inputOptions) const { if (inputOptions.convertToNormalMap) { mipmap.toFixedImage(inputOptions); Vector4 heightScale = inputOptions.heightFactors; mipmap.setImage(createNormalMap(mipmap.asFixedImage(), (FloatImage::WrapMode)inputOptions.wrapMode, heightScale, inputOptions.bumpFrequencyScale)); } else if (inputOptions.isNormalMap) { if (inputOptions.normalizeMipmaps) { // If floating point image available, normalize in place. if (mipmap.asFloatImage() == NULL) { FloatImage * floatImage = new FloatImage(mipmap.asFixedImage()); normalizeNormalMap(floatImage); mipmap.setImage(floatImage); } else { normalizeNormalMap(mipmap.asFloatImage()); mipmap.setImage(mipmap.asFloatImage()); } } } else { if (inputOptions.inputGamma != inputOptions.outputGamma) { mipmap.toFloatImage(inputOptions); } } } // Quantize the given mipmap according to the compression options. void Compressor::Private::quantizeMipmap(Mipmap & mipmap, const CompressionOptions::Private & compressionOptions) const { nvDebugCheck(mipmap.asFixedImage() != NULL); if (compressionOptions.binaryAlpha) { if (compressionOptions.enableAlphaDithering) { Quantize::FloydSteinberg_BinaryAlpha(mipmap.asMutableFixedImage(), compressionOptions.alphaThreshold); } else { Quantize::BinaryAlpha(mipmap.asMutableFixedImage(), compressionOptions.alphaThreshold); } } if (compressionOptions.enableColorDithering || compressionOptions.enableAlphaDithering) { uint rsize = 8; uint gsize = 8; uint bsize = 8; uint asize = 8; if (compressionOptions.enableColorDithering) { if (compressionOptions.format >= Format_DXT1 && compressionOptions.format <= Format_DXT5) { rsize = 5; gsize = 6; bsize = 5; } else if (compressionOptions.format == Format_RGB) { uint rshift, gshift, bshift; PixelFormat::maskShiftAndSize(compressionOptions.rmask, &rshift, &rsize); PixelFormat::maskShiftAndSize(compressionOptions.gmask, &gshift, &gsize); PixelFormat::maskShiftAndSize(compressionOptions.bmask, &bshift, &bsize); } } if (compressionOptions.enableAlphaDithering) { if (compressionOptions.format == Format_DXT3) { asize = 4; } else if (compressionOptions.format == Format_RGB) { uint ashift; PixelFormat::maskShiftAndSize(compressionOptions.amask, &ashift, &asize); } } if (compressionOptions.binaryAlpha) { asize = 8; // Already quantized. } Quantize::FloydSteinberg(mipmap.asMutableFixedImage(), rsize, gsize, bsize, asize); } } // Compress the given mipmap. bool Compressor::Private::compressMipmap(const Mipmap & mipmap, const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const { const Image * image = mipmap.asFixedImage(); nvDebugCheck(image != NULL); FastCompressor fast; fast.setImage(image, inputOptions.alphaMode); SlowCompressor slow; slow.setImage(image, inputOptions.alphaMode); const bool useCuda = cudaEnabled && image->width() * image->height() >= 512; if (compressionOptions.format == Format_RGBA || compressionOptions.format == Format_RGB) { compressRGB(image, outputOptions, compressionOptions); } else if (compressionOptions.format == Format_DXT1) { #if defined(HAVE_S3QUANT) if (compressionOptions.externalCompressor == "s3") { s3CompressDXT1(image, outputOptions); } else #endif #if defined(HAVE_ATITC) if (compressionOptions.externalCompressor == "ati") { atiCompressDXT1(image, outputOptions); } else #endif if (compressionOptions.quality == Quality_Fastest) { fast.compressDXT1(outputOptions); } else { if (useCuda) { nvDebugCheck(cudaSupported); cuda->setImage(image, inputOptions.alphaMode); cuda->compressDXT1(compressionOptions, outputOptions); } else { slow.compressDXT1(compressionOptions, outputOptions); } } } else if (compressionOptions.format == Format_DXT1a) { if (compressionOptions.quality == Quality_Fastest) { fast.compressDXT1a(outputOptions); } else { if (useCuda) { nvDebugCheck(cudaSupported); /*cuda*/slow.compressDXT1a(compressionOptions, outputOptions); } else { slow.compressDXT1a(compressionOptions, outputOptions); } } } else if (compressionOptions.format == Format_DXT3) { if (compressionOptions.quality == Quality_Fastest) { fast.compressDXT3(outputOptions); } else { if (useCuda) { nvDebugCheck(cudaSupported); cuda->setImage(image, inputOptions.alphaMode); cuda->compressDXT3(compressionOptions, outputOptions); } else { slow.compressDXT3(compressionOptions, outputOptions); } } } else if (compressionOptions.format == Format_DXT5) { if (compressionOptions.quality == Quality_Fastest) { fast.compressDXT5(outputOptions); } else { if (useCuda) { nvDebugCheck(cudaSupported); cuda->setImage(image, inputOptions.alphaMode); cuda->compressDXT5(compressionOptions, outputOptions); } else { slow.compressDXT5(compressionOptions, outputOptions); } } } else if (compressionOptions.format == Format_DXT5n) { if (compressionOptions.quality == Quality_Fastest) { fast.compressDXT5n(outputOptions); } else { slow.compressDXT5n(compressionOptions, outputOptions); } } else if (compressionOptions.format == Format_BC4) { slow.compressBC4(compressionOptions, outputOptions); } else if (compressionOptions.format == Format_BC5) { slow.compressBC5(compressionOptions, outputOptions); } return true; } int Compressor::Private::estimateSize(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions) const { const Format format = compressionOptions.format; const uint bitCount = compressionOptions.bitcount; inputOptions.computeTargetExtents(); uint mipmapCount = inputOptions.realMipmapCount(); int size = 0; for (uint f = 0; f < inputOptions.faceCount; f++) { uint w = inputOptions.targetWidth; uint h = inputOptions.targetHeight; uint d = inputOptions.targetDepth; for (uint m = 0; m < mipmapCount; m++) { size += computeImageSize(w, h, d, bitCount, format); // Compute extents of next mipmap: w = max(1U, w / 2); h = max(1U, h / 2); d = max(1U, d / 2); } } return size; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/Compressor.h000066400000000000000000000063061173441656100230100ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2008 -- Ignacio Castano // // 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 NV_TT_COMPRESSOR_H #define NV_TT_COMPRESSOR_H #include #include #include "nvtt.h" namespace nv { class Image; } namespace nvtt { struct Mipmap; struct Compressor::Private { Private() {} bool compress(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; int estimateSize(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions) const; private: bool outputHeader(const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; bool compressMipmaps(uint f, const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; bool initMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f, uint m) const; int findExactMipmap(const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f) const; int findClosestMipmap(const InputOptions::Private & inputOptions, uint w, uint h, uint d, uint f) const; void downsampleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions) const; void scaleMipmap(Mipmap & mipmap, const InputOptions::Private & inputOptions, uint w, uint h, uint d) const; void processInputImage(Mipmap & mipmap, const InputOptions::Private & inputOptions) const; void quantizeMipmap(Mipmap & mipmap, const CompressionOptions::Private & compressionOptions) const; bool compressMipmap(const Mipmap & mipmap, const InputOptions::Private & inputOptions, const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) const; public: bool cudaSupported; bool cudaEnabled; int cudaDevice; nv::AutoPtr cuda; }; } // nvtt namespace #endif // NV_TT_COMPRESSOR_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/InputOptions.cpp000066400000000000000000000230251173441656100236570ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 // memcpy #include #include "nvtt.h" #include "InputOptions.h" using namespace nv; using namespace nvtt; namespace { static uint countMipmaps(int w, int h, int d) { uint mipmap = 0; while (w != 1 || h != 1 || d != 1) { w = max(1, w / 2); h = max(1, h / 2); d = max(1, d / 2); mipmap++; } return mipmap + 1; } // 1 -> 1, 2 -> 2, 3 -> 2, 4 -> 4, 5 -> 4, ... static uint previousPowerOfTwo(const uint v) { return nextPowerOfTwo(v + 1) / 2; } static uint nearestPowerOfTwo(const uint v) { const uint np2 = nextPowerOfTwo(v); const uint pp2 = previousPowerOfTwo(v); if (np2 - v <= v - pp2) { return np2; } else { return pp2; } } } // namespace /// Constructor. InputOptions::InputOptions() : m(*new InputOptions::Private()) { reset(); } // Delete images. InputOptions::~InputOptions() { resetTextureLayout(); delete &m; } // Reset input options. void InputOptions::reset() { m.wrapMode = WrapMode_Mirror; m.textureType = TextureType_2D; m.inputFormat = InputFormat_BGRA_8UB; m.alphaMode = AlphaMode_None; m.inputGamma = 2.2f; m.outputGamma = 2.2f; m.colorTransform = ColorTransform_None; m.linearTransform = Matrix(identity); m.generateMipmaps = true; m.maxLevel = -1; m.mipmapFilter = MipmapFilter_Box; m.kaiserWidth = 3; m.kaiserAlpha = 4.0f; m.kaiserStretch = 1.0f; m.isNormalMap = false; m.normalizeMipmaps = true; m.convertToNormalMap = false; m.heightFactors.set(0.0f, 0.0f, 0.0f, 1.0f); m.bumpFrequencyScale = Vector4(1.0f, 0.5f, 0.25f, 0.125f) / (1.0f + 0.5f + 0.25f + 0.125f); m.maxExtent = 0; m.roundMode = RoundMode_None; } // Setup the input image. void InputOptions::setTextureLayout(TextureType type, int width, int height, int depth /*= 1*/) { // Validate arguments. nvCheck(width >= 0); nvCheck(height >= 0); nvCheck(depth >= 0); // Correct arguments. if (width == 0) width = 1; if (height == 0) height = 1; if (depth == 0) depth = 1; // Delete previous images. resetTextureLayout(); m.textureType = type; // Allocate images. m.mipmapCount = countMipmaps(width, height, depth); m.faceCount = (type == TextureType_Cube) ? 6 : 1; m.imageCount = m.mipmapCount * m.faceCount; m.images = new Private::InputImage[m.imageCount]; for(uint f = 0; f < m.faceCount; f++) { uint w = width; uint h = height; uint d = depth; for (uint mipLevel = 0; mipLevel < m.mipmapCount; mipLevel++) { Private::InputImage & img = m.images[f * m.mipmapCount + mipLevel]; img.width = w; img.height = h; img.depth = d; img.mipLevel = mipLevel; img.face = f; img.data = NULL; w = max(1U, w / 2); h = max(1U, h / 2); d = max(1U, d / 2); } } } void InputOptions::resetTextureLayout() { if (m.images != NULL) { // Delete image array. delete [] m.images; m.images = NULL; m.faceCount = 0; m.mipmapCount = 0; m.imageCount = 0; } } // Copies the data to our internal structures. bool InputOptions::setMipmapData(const void * data, int width, int height, int depth /*= 1*/, int face /*= 0*/, int mipLevel /*= 0*/) { nvCheck(depth == 1); const int idx = face * m.mipmapCount + mipLevel; if (m.images[idx].width != width || m.images[idx].height != height || m.images[idx].depth != depth || m.images[idx].mipLevel != mipLevel || m.images[idx].face != face) { // Invalid dimension or index. return false; } m.images[idx].data = new nv::Image(); m.images[idx].data->allocate(width, height); memcpy(m.images[idx].data->pixels(), data, width * height * 4); return true; } /// Describe the format of the input. void InputOptions::setFormat(InputFormat format) { m.inputFormat = format; } /// Set the way the input alpha channel is interpreted. void InputOptions::setAlphaMode(AlphaMode alphaMode) { m.alphaMode = alphaMode; } /// Set gamma settings. void InputOptions::setGamma(float inputGamma, float outputGamma) { m.inputGamma = inputGamma; m.outputGamma = outputGamma; } /// Set texture wrappign mode. void InputOptions::setWrapMode(WrapMode mode) { m.wrapMode = mode; } /// Set mipmap filter. void InputOptions::setMipmapFilter(MipmapFilter filter) { m.mipmapFilter = filter; } /// Set mipmap generation. void InputOptions::setMipmapGeneration(bool enabled, int maxLevel/*= -1*/) { m.generateMipmaps = enabled; m.maxLevel = maxLevel; } /// Set Kaiser filter parameters. void InputOptions::setKaiserParameters(float width, float alpha, float stretch) { m.kaiserWidth = width; m.kaiserAlpha = alpha; m.kaiserStretch = stretch; } /// Indicate whether input is a normal map or not. void InputOptions::setNormalMap(bool b) { m.isNormalMap = b; } /// Enable normal map conversion. void InputOptions::setConvertToNormalMap(bool convert) { m.convertToNormalMap = convert; } /// Set height evaluation factors. void InputOptions::setHeightEvaluation(float redScale, float greenScale, float blueScale, float alphaScale) { // Do not normalize height factors. // float total = redScale + greenScale + blueScale + alphaScale; m.heightFactors = Vector4(redScale, greenScale, blueScale, alphaScale); } /// Set normal map conversion filter. void InputOptions::setNormalFilter(float small, float medium, float big, float large) { float total = small + medium + big + large; m.bumpFrequencyScale = Vector4(small, medium, big, large) / total; } /// Enable mipmap normalization. void InputOptions::setNormalizeMipmaps(bool normalize) { m.normalizeMipmaps = normalize; } /// Set color transform. void InputOptions::setColorTransform(ColorTransform t) { m.colorTransform = t; } // Set linear transform for the given channel. void InputOptions::setLinearTransform(int channel, float w0, float w1, float w2, float w3) { nvCheck(channel >= 0 && channel < 4); Vector4 w(w0, w1, w2, w3); //m.linearTransform.setRow(channel, w); } void InputOptions::setMaxExtents(int e) { nvDebugCheck(e > 0); m.maxExtent = e; } void InputOptions::setRoundMode(RoundMode mode) { m.roundMode = mode; } void InputOptions::Private::computeTargetExtents() const { nvCheck(images != NULL); uint maxExtent = this->maxExtent; if (roundMode != RoundMode_None) { // rounded max extent should never be higher than original max extent. maxExtent = previousPowerOfTwo(maxExtent); } uint w = images->width; uint h = images->height; uint d = images->depth; nvDebugCheck(w > 0); nvDebugCheck(h > 0); nvDebugCheck(d > 0); // Scale extents without changing aspect ratio. uint maxwhd = max(max(w, h), d); if (maxExtent != 0 && maxwhd > maxExtent) { w = max((w * maxExtent) / maxwhd, 1U); h = max((h * maxExtent) / maxwhd, 1U); d = max((d * maxExtent) / maxwhd, 1U); } // Round to power of two. if (roundMode == RoundMode_ToNextPowerOfTwo) { w = nextPowerOfTwo(w); h = nextPowerOfTwo(h); d = nextPowerOfTwo(d); } else if (roundMode == RoundMode_ToNearestPowerOfTwo) { w = nearestPowerOfTwo(w); h = nearestPowerOfTwo(h); d = nearestPowerOfTwo(d); } else if (roundMode == RoundMode_ToPreviousPowerOfTwo) { w = previousPowerOfTwo(w); h = previousPowerOfTwo(h); d = previousPowerOfTwo(d); } this->targetWidth = w; this->targetHeight = h; this->targetDepth = d; this->targetMipmapCount = countMipmaps(w, h, d); } // Return real number of mipmaps, including first level. // computeTargetExtents should have been called before. int InputOptions::Private::realMipmapCount() const { int mipmapCount = targetMipmapCount; if (!generateMipmaps) mipmapCount = 1; else if (maxLevel != -1 && maxLevel < mipmapCount - 1) mipmapCount = maxLevel + 1; return mipmapCount; } const Image * InputOptions::Private::image(uint face, uint mipmap) const { nvDebugCheck(face < faceCount); nvDebugCheck(mipmap < mipmapCount); const InputImage & image = this->images[face * mipmapCount + mipmap]; nvDebugCheck(image.face == face); nvDebugCheck(image.mipLevel == mipmap); return image.data.ptr(); } const Image * InputOptions::Private::image(uint idx) const { nvDebugCheck(idx < faceCount * mipmapCount); const InputImage & image = this->images[idx]; return image.data.ptr(); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/InputOptions.h000066400000000000000000000055031173441656100233250ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_INPUTOPTIONS_H #define NV_TT_INPUTOPTIONS_H #include #include #include #include #include "nvtt.h" namespace nvtt { struct InputOptions::Private { Private() : images(NULL) {} WrapMode wrapMode; TextureType textureType; InputFormat inputFormat; AlphaMode alphaMode; uint faceCount; uint mipmapCount; uint imageCount; struct InputImage; InputImage * images; // Gamma conversion. float inputGamma; float outputGamma; // Color transform. ColorTransform colorTransform; nv::Matrix linearTransform; // Mipmap generation options. bool generateMipmaps; int maxLevel; MipmapFilter mipmapFilter; // Kaiser filter parameters. float kaiserWidth; float kaiserAlpha; float kaiserStretch; // Normal map options. bool isNormalMap; bool normalizeMipmaps; bool convertToNormalMap; nv::Vector4 heightFactors; nv::Vector4 bumpFrequencyScale; // Adjust extents. uint maxExtent; RoundMode roundMode; // @@ These are computed in nvtt::compress, so they should be mutable or stored elsewhere... mutable uint targetWidth; mutable uint targetHeight; mutable uint targetDepth; mutable uint targetMipmapCount; void computeTargetExtents() const; int realMipmapCount() const; const nv::Image * image(uint face, uint mipmap) const; const nv::Image * image(uint idx) const; }; // Internal image structure. struct InputOptions::Private::InputImage { InputImage() {} int mipLevel; int face; int width; int height; int depth; nv::AutoPtr data; }; } // nvtt namespace #endif // NV_TT_INPUTOPTIONS_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/OptimalCompressDXT.cpp000066400000000000000000000212271173441656100247070ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 // swap #include #include #include #include "OptimalCompressDXT.h" #include "SingleColorLookup.h" using namespace nv; using namespace OptimalCompress; namespace { static int computeGreenError(const ColorBlock & rgba, const BlockDXT1 * block) { nvDebugCheck(block != NULL); int palette[4]; palette[0] = (block->col0.g << 2) | (block->col0.g >> 4); palette[1] = (block->col1.g << 2) | (block->col1.g >> 4); palette[2] = (2 * palette[0] + palette[1]) / 3; palette[3] = (2 * palette[1] + palette[0]) / 3; int totalError = 0; for (int i = 0; i < 16; i++) { const int green = rgba.color(i).g; int error = abs(green - palette[0]); error = min(error, abs(green - palette[1])); error = min(error, abs(green - palette[2])); error = min(error, abs(green - palette[3])); totalError += error; } return totalError; } static uint computeGreenIndices(const ColorBlock & rgba, const Color32 palette[4]) { const int color0 = palette[0].g; const int color1 = palette[1].g; const int color2 = palette[2].g; const int color3 = palette[3].g; uint indices = 0; for (int i = 0; i < 16; i++) { const int color = rgba.color(i).g; uint d0 = abs(color0 - color); uint d1 = abs(color1 - color); uint d2 = abs(color2 - color); uint d3 = abs(color3 - color); uint b0 = d0 > d3; uint b1 = d1 > d2; uint b2 = d0 > d2; uint b3 = d1 > d3; uint b4 = d2 > d3; uint x0 = b1 & b2; uint x1 = b0 & b3; uint x2 = b0 & b4; indices |= (x2 | ((x0 | x1) << 1)) << (2 * i); } return indices; } // Choose quantized color that produces less error. Used by DXT3 compressor. inline static uint quantize4(uint8 a) { int q0 = (a >> 4) - 1; int q1 = (a >> 4); int q2 = (a >> 4) + 1; q0 = (q0 << 4) | q0; q1 = (q1 << 4) | q1; q2 = (q2 << 4) | q2; int d0 = abs(q0 - a); int d1 = abs(q1 - a); int d2 = abs(q2 - a); if (d0 < d1 && d0 < d2) return q0 >> 4; if (d1 < d2) return q1 >> 4; return q2 >> 4; } static uint computeAlphaError(const ColorBlock & rgba, const AlphaBlockDXT5 * block) { uint8 alphas[8]; block->evaluatePalette(alphas); uint totalError = 0; for (uint i = 0; i < 16; i++) { uint8 alpha = rgba.color(i).a; uint besterror = 256*256; uint best; for (uint p = 0; p < 8; p++) { int d = alphas[p] - alpha; uint error = d * d; if (error < besterror) { besterror = error; best = p; } } totalError += besterror; } return totalError; } static void computeAlphaIndices(const ColorBlock & rgba, AlphaBlockDXT5 * block) { uint8 alphas[8]; block->evaluatePalette(alphas); for (uint i = 0; i < 16; i++) { uint8 alpha = rgba.color(i).a; uint besterror = 256*256; uint best = 8; for(uint p = 0; p < 8; p++) { int d = alphas[p] - alpha; uint error = d * d; if (error < besterror) { besterror = error; best = p; } } nvDebugCheck(best < 8); block->setIndex(i, best); } } } // namespace // Single color compressor, based on: // https://mollyrocket.com/forums/viewtopic.php?t=392 void OptimalCompress::compressDXT1(Color32 c, BlockDXT1 * dxtBlock) { dxtBlock->col0.r = OMatch5[c.r][0]; dxtBlock->col0.g = OMatch6[c.g][0]; dxtBlock->col0.b = OMatch5[c.b][0]; dxtBlock->col1.r = OMatch5[c.r][1]; dxtBlock->col1.g = OMatch6[c.g][1]; dxtBlock->col1.b = OMatch5[c.b][1]; dxtBlock->indices = 0xaaaaaaaa; if (dxtBlock->col0.u < dxtBlock->col1.u) { swap(dxtBlock->col0.u, dxtBlock->col1.u); dxtBlock->indices ^= 0x55555555; } } void OptimalCompress::compressDXT1a(Color32 rgba, BlockDXT1 * dxtBlock) { if (rgba.a < 128) { dxtBlock->col0.u = 0; dxtBlock->col1.u = 0; dxtBlock->indices = 0xFFFFFFFF; } else { compressDXT1(rgba, dxtBlock); } } // Brute force green channel compressor void OptimalCompress::compressDXT1G(const ColorBlock & rgba, BlockDXT1 * block) { nvDebugCheck(block != NULL); uint8 ming = 63; uint8 maxg = 0; // Get min/max green. for (uint i = 0; i < 16; i++) { uint8 green = rgba.color(i).g >> 2; ming = min(ming, green); maxg = max(maxg, green); } block->col0.r = 31; block->col1.r = 31; block->col0.g = maxg; block->col1.g = ming; block->col0.b = 0; block->col1.b = 0; if (maxg - ming > 4) { int besterror = computeGreenError(rgba, block); int bestg0 = maxg; int bestg1 = ming; for (int g0 = ming+5; g0 < maxg; g0++) { for (int g1 = ming; g1 < g0-4; g1++) { if ((maxg-g0) + (g1-ming) > besterror) continue; block->col0.g = g0; block->col1.g = g1; int error = computeGreenError(rgba, block); if (error < besterror) { besterror = error; bestg0 = g0; bestg1 = g1; } } } block->col0.g = bestg0; block->col1.g = bestg1; } Color32 palette[4]; block->evaluatePalette(palette); block->indices = computeGreenIndices(rgba, palette); } void OptimalCompress::compressDXT3A(const ColorBlock & rgba, AlphaBlockDXT3 * dxtBlock) { dxtBlock->alpha0 = quantize4(rgba.color(0).a); dxtBlock->alpha1 = quantize4(rgba.color(1).a); dxtBlock->alpha2 = quantize4(rgba.color(2).a); dxtBlock->alpha3 = quantize4(rgba.color(3).a); dxtBlock->alpha4 = quantize4(rgba.color(4).a); dxtBlock->alpha5 = quantize4(rgba.color(5).a); dxtBlock->alpha6 = quantize4(rgba.color(6).a); dxtBlock->alpha7 = quantize4(rgba.color(7).a); dxtBlock->alpha8 = quantize4(rgba.color(8).a); dxtBlock->alpha9 = quantize4(rgba.color(9).a); dxtBlock->alphaA = quantize4(rgba.color(10).a); dxtBlock->alphaB = quantize4(rgba.color(11).a); dxtBlock->alphaC = quantize4(rgba.color(12).a); dxtBlock->alphaD = quantize4(rgba.color(13).a); dxtBlock->alphaE = quantize4(rgba.color(14).a); dxtBlock->alphaF = quantize4(rgba.color(15).a); } void OptimalCompress::compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock) { uint8 mina = 255; uint8 maxa = 0; // Get min/max alpha. for (uint i = 0; i < 16; i++) { uint8 alpha = rgba.color(i).a; mina = min(mina, alpha); maxa = max(maxa, alpha); } dxtBlock->alpha0 = maxa; dxtBlock->alpha1 = mina; /*int centroidDist = 256; int centroid; // Get the closest to the centroid. for (uint i = 0; i < 16; i++) { uint8 alpha = rgba.color(i).a; int dist = abs(alpha - (maxa + mina) / 2); if (dist < centroidDist) { centroidDist = dist; centroid = alpha; } }*/ if (maxa - mina > 8) { int besterror = computeAlphaError(rgba, dxtBlock); int besta0 = maxa; int besta1 = mina; for (int a0 = mina+9; a0 < maxa; a0++) { for (int a1 = mina; a1 < a0-8; a1++) //for (int a1 = mina; a1 < maxa; a1++) { //nvCheck(abs(a1-a0) > 8); //if (abs(a0 - a1) < 8) continue; //if ((maxa-a0) + (a1-mina) + min(abs(centroid-a0), abs(centroid-a1)) > besterror) if ((maxa-a0) + (a1-mina) > besterror) continue; dxtBlock->alpha0 = a0; dxtBlock->alpha1 = a1; int error = computeAlphaError(rgba, dxtBlock); if (error < besterror) { besterror = error; besta0 = a0; besta1 = a1; } } } dxtBlock->alpha0 = besta0; dxtBlock->alpha1 = besta1; } computeAlphaIndices(rgba, dxtBlock); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/OptimalCompressDXT.h000066400000000000000000000035261173441656100243560ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2008 -- Ignacio Castano // // 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 NV_TT_OPTIMALCOMPRESSDXT_H #define NV_TT_OPTIMALCOMPRESSDXT_H #include namespace nv { struct ColorBlock; struct BlockDXT1; struct BlockDXT3; struct BlockDXT5; struct AlphaBlockDXT3; struct AlphaBlockDXT5; namespace OptimalCompress { void compressDXT1(Color32 rgba, BlockDXT1 * dxtBlock); void compressDXT1a(Color32 rgba, BlockDXT1 * dxtBlock); void compressDXT1G(const ColorBlock & rgba, BlockDXT1 * block); void compressDXT3A(const ColorBlock & rgba, AlphaBlockDXT3 * dxtBlock); void compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock); } } // nv namespace #endif // NV_TT_OPTIMALCOMPRESSDXT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/OutputOptions.cpp000066400000000000000000000047721173441656100240700ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 "OutputOptions.h" using namespace nvtt; OutputOptions::OutputOptions() : m(*new OutputOptions::Private()) { reset(); } OutputOptions::~OutputOptions() { delete &m; } /// Set default output options. void OutputOptions::reset() { m.fileName.reset(); m.outputHandler = NULL; m.errorHandler = NULL; m.outputHeader = true; } /// Set output file name. void OutputOptions::setFileName(const char * fileName) { m.fileName = fileName; m.outputHandler = NULL; } /// Set output handler. void OutputOptions::setOutputHandler(OutputHandler * outputHandler) { m.fileName.reset(); m.outputHandler = outputHandler; } /// Set error handler. void OutputOptions::setErrorHandler(ErrorHandler * errorHandler) { m.errorHandler = errorHandler; } /// Set output header. void OutputOptions::setOutputHeader(bool outputHeader) { m.outputHeader = outputHeader; } bool OutputOptions::Private::openFile() const { if (!fileName.isNull()) { nvCheck(outputHandler == NULL); DefaultOutputHandler * oh = new DefaultOutputHandler(fileName.str()); if (oh->stream.isError()) { return false; } outputHandler = oh; } return true; } void OutputOptions::Private::closeFile() const { if (!fileName.isNull()) { delete outputHandler; outputHandler = NULL; } } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/OutputOptions.h000066400000000000000000000042051173441656100235240ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_OUTPUTOPTIONS_H #define NV_TT_OUTPUTOPTIONS_H #include #include #include "nvtt.h" namespace nvtt { struct DefaultOutputHandler : public nvtt::OutputHandler { DefaultOutputHandler(const char * fileName) : stream(fileName) {} virtual ~DefaultOutputHandler() { } virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) { // ignore. } // Output data. virtual bool writeData(const void * data, int size) { stream.serialize(const_cast(data), size); //return !stream.isError(); return true; } nv::StdOutputStream stream; }; struct OutputOptions::Private { nv::Path fileName; mutable OutputHandler * outputHandler; ErrorHandler * errorHandler; bool outputHeader; bool openFile() const; void closeFile() const; }; } // nvtt namespace #endif // NV_TT_OUTPUTOPTIONS_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/QuickCompressDXT.cpp000066400000000000000000000342731173441656100243630ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include "QuickCompressDXT.h" #include "OptimalCompressDXT.h" using namespace nv; using namespace QuickCompress; inline static void extractColorBlockRGB(const ColorBlock & rgba, Vector3 block[16]) { for (int i = 0; i < 16; i++) { const Color32 c = rgba.color(i); block[i] = Vector3(c.r, c.g, c.b); } } inline static uint extractColorBlockRGBA(const ColorBlock & rgba, Vector3 block[16]) { int num = 0; for (int i = 0; i < 16; i++) { const Color32 c = rgba.color(i); if (c.a > 127) { block[num++] = Vector3(c.r, c.g, c.b); } } return num; } // find minimum and maximum colors based on bounding box in color space inline static void findMinMaxColorsBox(const Vector3 * block, uint num, Vector3 * restrict maxColor, Vector3 * restrict minColor) { *maxColor = Vector3(0, 0, 0); *minColor = Vector3(255, 255, 255); for (uint i = 0; i < num; i++) { *maxColor = max(*maxColor, block[i]); *minColor = min(*minColor, block[i]); } } inline static void selectDiagonal(const Vector3 * block, uint num, Vector3 * restrict maxColor, Vector3 * restrict minColor) { Vector3 center = (*maxColor + *minColor) * 0.5; Vector2 covariance = Vector2(zero); for (uint i = 0; i < num; i++) { Vector3 t = block[i] - center; covariance += t.xy() * t.z(); } float x0 = maxColor->x(); float y0 = maxColor->y(); float x1 = minColor->x(); float y1 = minColor->y(); if (covariance.x() < 0) { swap(x0, x1); } if (covariance.y() < 0) { swap(y0, y1); } maxColor->set(x0, y0, maxColor->z()); minColor->set(x1, y1, minColor->z()); } inline static void insetBBox(Vector3 * restrict maxColor, Vector3 * restrict minColor) { Vector3 inset = (*maxColor - *minColor) / 16.0f - (8.0f / 255.0f) / 16.0f; *maxColor = clamp(*maxColor - inset, 0.0f, 255.0f); *minColor = clamp(*minColor + inset, 0.0f, 255.0f); } inline static uint16 roundAndExpand(Vector3 * restrict v) { uint r = uint(clamp(v->x() * (31.0f / 255.0f), 0.0f, 31.0f) + 0.5f); uint g = uint(clamp(v->y() * (63.0f / 255.0f), 0.0f, 63.0f) + 0.5f); uint b = uint(clamp(v->z() * (31.0f / 255.0f), 0.0f, 31.0f) + 0.5f); uint16 w = (r << 11) | (g << 5) | b; r = (r << 3) | (r >> 2); g = (g << 2) | (g >> 4); b = (b << 3) | (b >> 2); *v = Vector3(float(r), float(g), float(b)); return w; } inline static float colorDistance(Vector3::Arg c0, Vector3::Arg c1) { return dot(c0-c1, c0-c1); } inline static uint computeIndices4(Vector3 block[16], Vector3::Arg maxColor, Vector3::Arg minColor) { Vector3 palette[4]; palette[0] = maxColor; palette[1] = minColor; palette[2] = lerp(palette[0], palette[1], 1.0f / 3.0f); palette[3] = lerp(palette[0], palette[1], 2.0f / 3.0f); uint indices = 0; for(int i = 0; i < 16; i++) { float d0 = colorDistance(palette[0], block[i]); float d1 = colorDistance(palette[1], block[i]); float d2 = colorDistance(palette[2], block[i]); float d3 = colorDistance(palette[3], block[i]); uint b0 = d0 > d3; uint b1 = d1 > d2; uint b2 = d0 > d2; uint b3 = d1 > d3; uint b4 = d2 > d3; uint x0 = b1 & b2; uint x1 = b0 & b3; uint x2 = b0 & b4; indices |= (x2 | ((x0 | x1) << 1)) << (2 * i); } return indices; } inline static uint computeIndices3(const ColorBlock & rgba, Vector3::Arg maxColor, Vector3::Arg minColor) { Vector3 palette[4]; palette[0] = minColor; palette[1] = maxColor; palette[2] = (palette[0] + palette[1]) * 0.5f; uint indices = 0; for(int i = 0; i < 16; i++) { Color32 c = rgba.color(i); Vector3 color = Vector3(c.r, c.g, c.b); float d0 = colorDistance(palette[0], color); float d1 = colorDistance(palette[1], color); float d2 = colorDistance(palette[2], color); uint index; if (c.a < 128) index = 3; else if (d0 < d1 && d0 < d2) index = 0; else if (d1 < d2) index = 1; else index = 2; indices |= index << (2 * i); } return indices; } static void optimizeEndPoints4(Vector3 block[16], BlockDXT1 * dxtBlock) { float alpha2_sum = 0.0f; float beta2_sum = 0.0f; float alphabeta_sum = 0.0f; Vector3 alphax_sum(zero); Vector3 betax_sum(zero); for( int i = 0; i < 16; ++i ) { const uint bits = dxtBlock->indices >> (2 * i); float beta = float(bits & 1); if (bits & 2) beta = (1 + beta) / 3.0f; float alpha = 1.0f - beta; alpha2_sum += alpha * alpha; beta2_sum += beta * beta; alphabeta_sum += alpha * beta; alphax_sum += alpha * block[i]; betax_sum += beta * block[i]; } float denom = alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum; if (equal(denom, 0.0f)) return; float factor = 1.0f / denom; Vector3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; Vector3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; a = clamp(a, 0, 255); b = clamp(b, 0, 255); uint16 color0 = roundAndExpand(&a); uint16 color1 = roundAndExpand(&b); if (color0 < color1) { swap(a, b); swap(color0, color1); } dxtBlock->col0 = Color16(color0); dxtBlock->col1 = Color16(color1); dxtBlock->indices = computeIndices4(block, a, b); } /*static void optimizeEndPoints3(Vector3 block[16], BlockDXT1 * dxtBlock) { float alpha2_sum = 0.0f; float beta2_sum = 0.0f; float alphabeta_sum = 0.0f; Vector3 alphax_sum(zero); Vector3 betax_sum(zero); for( int i = 0; i < 16; ++i ) { const uint bits = dxtBlock->indices >> (2 * i); float beta = (bits & 1); if (bits & 2) beta = 0.5f; float alpha = 1.0f - beta; alpha2_sum += alpha * alpha; beta2_sum += beta * beta; alphabeta_sum += alpha * beta; alphax_sum += alpha * block[i]; betax_sum += beta * block[i]; } float denom = alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum; if (equal(denom, 0.0f)) return; float factor = 1.0f / denom; Vector3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; Vector3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; a = clamp(a, 0, 255); b = clamp(b, 0, 255); uint16 color0 = roundAndExpand(&a); uint16 color1 = roundAndExpand(&b); if (color0 < color1) { swap(a, b); swap(color0, color1); } dxtBlock->col0 = Color16(color1); dxtBlock->col1 = Color16(color0); dxtBlock->indices = computeIndices3(block, a, b); }*/ namespace { static uint computeAlphaIndices(const ColorBlock & rgba, AlphaBlockDXT5 * block) { uint8 alphas[8]; block->evaluatePalette(alphas); uint totalError = 0; for (uint i = 0; i < 16; i++) { uint8 alpha = rgba.color(i).a; uint besterror = 256*256; uint best = 8; for(uint p = 0; p < 8; p++) { int d = alphas[p] - alpha; uint error = d * d; if (error < besterror) { besterror = error; best = p; } } nvDebugCheck(best < 8); totalError += besterror; block->setIndex(i, best); } return totalError; } static void optimizeAlpha8(const ColorBlock & rgba, AlphaBlockDXT5 * block) { float alpha2_sum = 0; float beta2_sum = 0; float alphabeta_sum = 0; float alphax_sum = 0; float betax_sum = 0; for (int i = 0; i < 16; i++) { uint idx = block->index(i); float alpha; if (idx < 2) alpha = 1.0f - idx; else alpha = (8.0f - idx) / 7.0f; float beta = 1 - alpha; alpha2_sum += alpha * alpha; beta2_sum += beta * beta; alphabeta_sum += alpha * beta; alphax_sum += alpha * rgba.color(i).a; betax_sum += beta * rgba.color(i).a; } const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; uint alpha0 = uint(min(max(a, 0.0f), 255.0f)); uint alpha1 = uint(min(max(b, 0.0f), 255.0f)); if (alpha0 < alpha1) { swap(alpha0, alpha1); // Flip indices: for (int i = 0; i < 16; i++) { uint idx = block->index(i); if (idx < 2) block->setIndex(i, 1 - idx); else block->setIndex(i, 9 - idx); } } else if (alpha0 == alpha1) { for (int i = 0; i < 16; i++) { block->setIndex(i, 0); } } block->alpha0 = alpha0; block->alpha1 = alpha1; } /* static void optimizeAlpha6(const ColorBlock & rgba, AlphaBlockDXT5 * block) { float alpha2_sum = 0; float beta2_sum = 0; float alphabeta_sum = 0; float alphax_sum = 0; float betax_sum = 0; for (int i = 0; i < 16; i++) { uint8 x = rgba.color(i).a; if (x == 0 || x == 255) continue; uint bits = block->index(i); if (bits == 6 || bits == 7) continue; float alpha; if (bits == 0) alpha = 1.0f; else if (bits == 1) alpha = 0.0f; else alpha = (6.0f - block->index(i)) / 5.0f; float beta = 1 - alpha; alpha2_sum += alpha * alpha; beta2_sum += beta * beta; alphabeta_sum += alpha * beta; alphax_sum += alpha * x; betax_sum += beta * x; } const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; uint alpha0 = uint(min(max(a, 0.0f), 255.0f)); uint alpha1 = uint(min(max(b, 0.0f), 255.0f)); if (alpha0 > alpha1) { swap(alpha0, alpha1); } block->alpha0 = alpha0; block->alpha1 = alpha1; } */ static bool sameIndices(const AlphaBlockDXT5 & block0, const AlphaBlockDXT5 & block1) { const uint64 mask = ~uint64(0xFFFF); return (block0.u | mask) == (block1.u | mask); } } // namespace void QuickCompress::compressDXT1(const ColorBlock & rgba, BlockDXT1 * dxtBlock) { if (rgba.isSingleColor()) { OptimalCompress::compressDXT1(rgba.color(0), dxtBlock); } else { // read block Vector3 block[16]; extractColorBlockRGB(rgba, block); // find min and max colors Vector3 maxColor, minColor; findMinMaxColorsBox(block, 16, &maxColor, &minColor); selectDiagonal(block, 16, &maxColor, &minColor); insetBBox(&maxColor, &minColor); uint16 color0 = roundAndExpand(&maxColor); uint16 color1 = roundAndExpand(&minColor); if (color0 < color1) { swap(maxColor, minColor); swap(color0, color1); } dxtBlock->col0 = Color16(color0); dxtBlock->col1 = Color16(color1); dxtBlock->indices = computeIndices4(block, maxColor, minColor); optimizeEndPoints4(block, dxtBlock); } } void QuickCompress::compressDXT1a(const ColorBlock & rgba, BlockDXT1 * dxtBlock) { bool hasAlpha = false; for (uint i = 0; i < 16; i++) { if (rgba.color(i).a < 128) { hasAlpha = true; break; } } if (!hasAlpha) { compressDXT1(rgba, dxtBlock); } // @@ Handle single RGB, with varying alpha? We need tables for single color compressor in 3 color mode. //else if (rgba.isSingleColorNoAlpha()) { ... } else { // read block Vector3 block[16]; uint num = extractColorBlockRGBA(rgba, block); // find min and max colors Vector3 maxColor, minColor; findMinMaxColorsBox(block, num, &maxColor, &minColor); selectDiagonal(block, num, &maxColor, &minColor); insetBBox(&maxColor, &minColor); uint16 color0 = roundAndExpand(&maxColor); uint16 color1 = roundAndExpand(&minColor); if (color0 < color1) { swap(maxColor, minColor); swap(color0, color1); } dxtBlock->col0 = Color16(color1); dxtBlock->col1 = Color16(color0); dxtBlock->indices = computeIndices3(rgba, maxColor, minColor); // optimizeEndPoints(block, dxtBlock); } } void QuickCompress::compressDXT3(const ColorBlock & rgba, BlockDXT3 * dxtBlock) { compressDXT1(rgba, &dxtBlock->color); OptimalCompress::compressDXT3A(rgba, &dxtBlock->alpha); } void QuickCompress::compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock, int iterationCount/*=8*/) { uint8 alpha0 = 0; uint8 alpha1 = 255; // Get min/max alpha. for (uint i = 0; i < 16; i++) { uint8 alpha = rgba.color(i).a; alpha0 = max(alpha0, alpha); alpha1 = min(alpha1, alpha); } AlphaBlockDXT5 block; block.alpha0 = alpha0 - (alpha0 - alpha1) / 34; block.alpha1 = alpha1 + (alpha0 - alpha1) / 34; uint besterror = computeAlphaIndices(rgba, &block); AlphaBlockDXT5 bestblock = block; for (int i = 0; i < iterationCount; i++) { optimizeAlpha8(rgba, &block); uint error = computeAlphaIndices(rgba, &block); if (error >= besterror) { // No improvement, stop. break; } if (sameIndices(block, bestblock)) { bestblock = block; break; } besterror = error; bestblock = block; }; // Copy best block to result; *dxtBlock = bestblock; } void QuickCompress::compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock, int iterationCount/*=8*/) { compressDXT1(rgba, &dxtBlock->color); compressDXT5A(rgba, &dxtBlock->alpha, iterationCount); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/QuickCompressDXT.h000066400000000000000000000036201173441656100240200ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_QUICKCOMPRESSDXT_H #define NV_TT_QUICKCOMPRESSDXT_H #include namespace nv { struct ColorBlock; struct BlockDXT1; struct BlockDXT3; struct BlockDXT5; struct AlphaBlockDXT3; struct AlphaBlockDXT5; namespace QuickCompress { void compressDXT1(const ColorBlock & rgba, BlockDXT1 * dxtBlock); void compressDXT1a(const ColorBlock & rgba, BlockDXT1 * dxtBlock); void compressDXT3(const ColorBlock & rgba, BlockDXT3 * dxtBlock); void compressDXT5A(const ColorBlock & rgba, AlphaBlockDXT5 * dxtBlock, int iterationCount=8); void compressDXT5(const ColorBlock & rgba, BlockDXT5 * dxtBlock, int iterationCount=8); } } // nv namespace #endif // NV_TT_QUICKCOMPRESSDXT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/SingleColorLookup.h000066400000000000000000000211711173441656100242630ustar00rootroot00000000000000 /* typedef unsigned char uint8; static int Mul8Bit(int a, int b) { int t = a * b + 128; return (t + (t >> 8)) >> 8; } static inline int Lerp13(int fm, int to) { return (fm * 2 + to) / 3; } static void PrepareOptTable(uint8 * Table, const uint8 * expand, int size) { for (int i = 0; i < 256; i++) { float bestErr = 256; for (int min = 0; min < size; min++) { for (int max = 0; max < size; max++) { int mine = expand[min]; int maxe = expand[max]; float err = abs(maxe + Mul8Bit(mine-maxe, 0x55) - i); err += 0.03f * abs(max - min); if (err < bestErr) { Table[i*2+0] = max; Table[i*2+1] = min; bestErr = err; } } } } } void initTables() { uint8 Expand5[32]; uint8 Expand6[64]; for(sInt i=0;i<32;i++) Expand5[i] = (i<<3)|(i>>2); for(sInt i=0;i<64;i++) Expand6[i] = (i<<2)|(i>>4); PrepareOptTable(OMatch5, Expand5, 32) PrepareOptTable(OMatch6, Expand6, 64) }; */ #if __CUDACC__ __constant__ unsigned short #else const static uint8 #endif OMatch5[256][2] = { {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x01}, {0x00, 0x01}, {0x01, 0x00}, {0x01, 0x00}, {0x01, 0x00}, {0x01, 0x01}, {0x01, 0x01}, {0x01, 0x01}, {0x01, 0x02}, {0x00, 0x04}, {0x02, 0x01}, {0x02, 0x01}, {0x02, 0x01}, {0x02, 0x02}, {0x02, 0x02}, {0x02, 0x02}, {0x02, 0x03}, {0x01, 0x05}, {0x03, 0x02}, {0x03, 0x02}, {0x04, 0x00}, {0x03, 0x03}, {0x03, 0x03}, {0x03, 0x03}, {0x03, 0x04}, {0x03, 0x04}, {0x03, 0x04}, {0x03, 0x05}, {0x04, 0x03}, {0x04, 0x03}, {0x05, 0x02}, {0x04, 0x04}, {0x04, 0x04}, {0x04, 0x05}, {0x04, 0x05}, {0x05, 0x04}, {0x05, 0x04}, {0x05, 0x04}, {0x06, 0x03}, {0x05, 0x05}, {0x05, 0x05}, {0x05, 0x06}, {0x04, 0x08}, {0x06, 0x05}, {0x06, 0x05}, {0x06, 0x05}, {0x06, 0x06}, {0x06, 0x06}, {0x06, 0x06}, {0x06, 0x07}, {0x05, 0x09}, {0x07, 0x06}, {0x07, 0x06}, {0x08, 0x04}, {0x07, 0x07}, {0x07, 0x07}, {0x07, 0x07}, {0x07, 0x08}, {0x07, 0x08}, {0x07, 0x08}, {0x07, 0x09}, {0x08, 0x07}, {0x08, 0x07}, {0x09, 0x06}, {0x08, 0x08}, {0x08, 0x08}, {0x08, 0x09}, {0x08, 0x09}, {0x09, 0x08}, {0x09, 0x08}, {0x09, 0x08}, {0x0A, 0x07}, {0x09, 0x09}, {0x09, 0x09}, {0x09, 0x0A}, {0x08, 0x0C}, {0x0A, 0x09}, {0x0A, 0x09}, {0x0A, 0x09}, {0x0A, 0x0A}, {0x0A, 0x0A}, {0x0A, 0x0A}, {0x0A, 0x0B}, {0x09, 0x0D}, {0x0B, 0x0A}, {0x0B, 0x0A}, {0x0C, 0x08}, {0x0B, 0x0B}, {0x0B, 0x0B}, {0x0B, 0x0B}, {0x0B, 0x0C}, {0x0B, 0x0C}, {0x0B, 0x0C}, {0x0B, 0x0D}, {0x0C, 0x0B}, {0x0C, 0x0B}, {0x0D, 0x0A}, {0x0C, 0x0C}, {0x0C, 0x0C}, {0x0C, 0x0D}, {0x0C, 0x0D}, {0x0D, 0x0C}, {0x0D, 0x0C}, {0x0D, 0x0C}, {0x0E, 0x0B}, {0x0D, 0x0D}, {0x0D, 0x0D}, {0x0D, 0x0E}, {0x0C, 0x10}, {0x0E, 0x0D}, {0x0E, 0x0D}, {0x0E, 0x0D}, {0x0E, 0x0E}, {0x0E, 0x0E}, {0x0E, 0x0E}, {0x0E, 0x0F}, {0x0D, 0x11}, {0x0F, 0x0E}, {0x0F, 0x0E}, {0x10, 0x0C}, {0x0F, 0x0F}, {0x0F, 0x0F}, {0x0F, 0x0F}, {0x0F, 0x10}, {0x0F, 0x10}, {0x0F, 0x10}, {0x0F, 0x11}, {0x10, 0x0F}, {0x10, 0x0F}, {0x11, 0x0E}, {0x10, 0x10}, {0x10, 0x10}, {0x10, 0x11}, {0x10, 0x11}, {0x11, 0x10}, {0x11, 0x10}, {0x11, 0x10}, {0x12, 0x0F}, {0x11, 0x11}, {0x11, 0x11}, {0x11, 0x12}, {0x10, 0x14}, {0x12, 0x11}, {0x12, 0x11}, {0x12, 0x11}, {0x12, 0x12}, {0x12, 0x12}, {0x12, 0x12}, {0x12, 0x13}, {0x11, 0x15}, {0x13, 0x12}, {0x13, 0x12}, {0x14, 0x10}, {0x13, 0x13}, {0x13, 0x13}, {0x13, 0x13}, {0x13, 0x14}, {0x13, 0x14}, {0x13, 0x14}, {0x13, 0x15}, {0x14, 0x13}, {0x14, 0x13}, {0x15, 0x12}, {0x14, 0x14}, {0x14, 0x14}, {0x14, 0x15}, {0x14, 0x15}, {0x15, 0x14}, {0x15, 0x14}, {0x15, 0x14}, {0x16, 0x13}, {0x15, 0x15}, {0x15, 0x15}, {0x15, 0x16}, {0x14, 0x18}, {0x16, 0x15}, {0x16, 0x15}, {0x16, 0x15}, {0x16, 0x16}, {0x16, 0x16}, {0x16, 0x16}, {0x16, 0x17}, {0x15, 0x19}, {0x17, 0x16}, {0x17, 0x16}, {0x18, 0x14}, {0x17, 0x17}, {0x17, 0x17}, {0x17, 0x17}, {0x17, 0x18}, {0x17, 0x18}, {0x17, 0x18}, {0x17, 0x19}, {0x18, 0x17}, {0x18, 0x17}, {0x19, 0x16}, {0x18, 0x18}, {0x18, 0x18}, {0x18, 0x19}, {0x18, 0x19}, {0x19, 0x18}, {0x19, 0x18}, {0x19, 0x18}, {0x1A, 0x17}, {0x19, 0x19}, {0x19, 0x19}, {0x19, 0x1A}, {0x18, 0x1C}, {0x1A, 0x19}, {0x1A, 0x19}, {0x1A, 0x19}, {0x1A, 0x1A}, {0x1A, 0x1A}, {0x1A, 0x1A}, {0x1A, 0x1B}, {0x19, 0x1D}, {0x1B, 0x1A}, {0x1B, 0x1A}, {0x1C, 0x18}, {0x1B, 0x1B}, {0x1B, 0x1B}, {0x1B, 0x1B}, {0x1B, 0x1C}, {0x1B, 0x1C}, {0x1B, 0x1C}, {0x1B, 0x1D}, {0x1C, 0x1B}, {0x1C, 0x1B}, {0x1D, 0x1A}, {0x1C, 0x1C}, {0x1C, 0x1C}, {0x1C, 0x1D}, {0x1C, 0x1D}, {0x1D, 0x1C}, {0x1D, 0x1C}, {0x1D, 0x1C}, {0x1E, 0x1B}, {0x1D, 0x1D}, {0x1D, 0x1D}, {0x1D, 0x1E}, {0x1D, 0x1E}, {0x1E, 0x1D}, {0x1E, 0x1D}, {0x1E, 0x1D}, {0x1E, 0x1E}, {0x1E, 0x1E}, {0x1E, 0x1E}, {0x1E, 0x1F}, {0x1E, 0x1F}, {0x1F, 0x1E}, {0x1F, 0x1E}, {0x1F, 0x1E}, {0x1F, 0x1F}, {0x1F, 0x1F}, }; #if __CUDACC__ __constant__ unsigned short #else const static uint8 #endif OMatch6[256][2] = { {0x00, 0x00}, {0x00, 0x01}, {0x01, 0x00}, {0x01, 0x01}, {0x01, 0x01}, {0x01, 0x02}, {0x02, 0x01}, {0x02, 0x02}, {0x02, 0x02}, {0x02, 0x03}, {0x03, 0x02}, {0x03, 0x03}, {0x03, 0x03}, {0x03, 0x04}, {0x04, 0x03}, {0x04, 0x04}, {0x04, 0x04}, {0x04, 0x05}, {0x05, 0x04}, {0x05, 0x05}, {0x05, 0x05}, {0x05, 0x06}, {0x06, 0x05}, {0x00, 0x11}, {0x06, 0x06}, {0x06, 0x07}, {0x07, 0x06}, {0x02, 0x10}, {0x07, 0x07}, {0x07, 0x08}, {0x08, 0x07}, {0x03, 0x11}, {0x08, 0x08}, {0x08, 0x09}, {0x09, 0x08}, {0x05, 0x10}, {0x09, 0x09}, {0x09, 0x0A}, {0x0A, 0x09}, {0x06, 0x11}, {0x0A, 0x0A}, {0x0A, 0x0B}, {0x0B, 0x0A}, {0x08, 0x10}, {0x0B, 0x0B}, {0x0B, 0x0C}, {0x0C, 0x0B}, {0x09, 0x11}, {0x0C, 0x0C}, {0x0C, 0x0D}, {0x0D, 0x0C}, {0x0B, 0x10}, {0x0D, 0x0D}, {0x0D, 0x0E}, {0x0E, 0x0D}, {0x0C, 0x11}, {0x0E, 0x0E}, {0x0E, 0x0F}, {0x0F, 0x0E}, {0x0E, 0x10}, {0x0F, 0x0F}, {0x0F, 0x10}, {0x10, 0x0E}, {0x10, 0x0F}, {0x11, 0x0E}, {0x10, 0x10}, {0x10, 0x11}, {0x11, 0x10}, {0x12, 0x0F}, {0x11, 0x11}, {0x11, 0x12}, {0x12, 0x11}, {0x14, 0x0E}, {0x12, 0x12}, {0x12, 0x13}, {0x13, 0x12}, {0x15, 0x0F}, {0x13, 0x13}, {0x13, 0x14}, {0x14, 0x13}, {0x17, 0x0E}, {0x14, 0x14}, {0x14, 0x15}, {0x15, 0x14}, {0x18, 0x0F}, {0x15, 0x15}, {0x15, 0x16}, {0x16, 0x15}, {0x1A, 0x0E}, {0x16, 0x16}, {0x16, 0x17}, {0x17, 0x16}, {0x1B, 0x0F}, {0x17, 0x17}, {0x17, 0x18}, {0x18, 0x17}, {0x13, 0x21}, {0x18, 0x18}, {0x18, 0x19}, {0x19, 0x18}, {0x15, 0x20}, {0x19, 0x19}, {0x19, 0x1A}, {0x1A, 0x19}, {0x16, 0x21}, {0x1A, 0x1A}, {0x1A, 0x1B}, {0x1B, 0x1A}, {0x18, 0x20}, {0x1B, 0x1B}, {0x1B, 0x1C}, {0x1C, 0x1B}, {0x19, 0x21}, {0x1C, 0x1C}, {0x1C, 0x1D}, {0x1D, 0x1C}, {0x1B, 0x20}, {0x1D, 0x1D}, {0x1D, 0x1E}, {0x1E, 0x1D}, {0x1C, 0x21}, {0x1E, 0x1E}, {0x1E, 0x1F}, {0x1F, 0x1E}, {0x1E, 0x20}, {0x1F, 0x1F}, {0x1F, 0x20}, {0x20, 0x1E}, {0x20, 0x1F}, {0x21, 0x1E}, {0x20, 0x20}, {0x20, 0x21}, {0x21, 0x20}, {0x22, 0x1F}, {0x21, 0x21}, {0x21, 0x22}, {0x22, 0x21}, {0x24, 0x1E}, {0x22, 0x22}, {0x22, 0x23}, {0x23, 0x22}, {0x25, 0x1F}, {0x23, 0x23}, {0x23, 0x24}, {0x24, 0x23}, {0x27, 0x1E}, {0x24, 0x24}, {0x24, 0x25}, {0x25, 0x24}, {0x28, 0x1F}, {0x25, 0x25}, {0x25, 0x26}, {0x26, 0x25}, {0x2A, 0x1E}, {0x26, 0x26}, {0x26, 0x27}, {0x27, 0x26}, {0x2B, 0x1F}, {0x27, 0x27}, {0x27, 0x28}, {0x28, 0x27}, {0x23, 0x31}, {0x28, 0x28}, {0x28, 0x29}, {0x29, 0x28}, {0x25, 0x30}, {0x29, 0x29}, {0x29, 0x2A}, {0x2A, 0x29}, {0x26, 0x31}, {0x2A, 0x2A}, {0x2A, 0x2B}, {0x2B, 0x2A}, {0x28, 0x30}, {0x2B, 0x2B}, {0x2B, 0x2C}, {0x2C, 0x2B}, {0x29, 0x31}, {0x2C, 0x2C}, {0x2C, 0x2D}, {0x2D, 0x2C}, {0x2B, 0x30}, {0x2D, 0x2D}, {0x2D, 0x2E}, {0x2E, 0x2D}, {0x2C, 0x31}, {0x2E, 0x2E}, {0x2E, 0x2F}, {0x2F, 0x2E}, {0x2E, 0x30}, {0x2F, 0x2F}, {0x2F, 0x30}, {0x30, 0x2E}, {0x30, 0x2F}, {0x31, 0x2E}, {0x30, 0x30}, {0x30, 0x31}, {0x31, 0x30}, {0x32, 0x2F}, {0x31, 0x31}, {0x31, 0x32}, {0x32, 0x31}, {0x34, 0x2E}, {0x32, 0x32}, {0x32, 0x33}, {0x33, 0x32}, {0x35, 0x2F}, {0x33, 0x33}, {0x33, 0x34}, {0x34, 0x33}, {0x37, 0x2E}, {0x34, 0x34}, {0x34, 0x35}, {0x35, 0x34}, {0x38, 0x2F}, {0x35, 0x35}, {0x35, 0x36}, {0x36, 0x35}, {0x3A, 0x2E}, {0x36, 0x36}, {0x36, 0x37}, {0x37, 0x36}, {0x3B, 0x2F}, {0x37, 0x37}, {0x37, 0x38}, {0x38, 0x37}, {0x3D, 0x2E}, {0x38, 0x38}, {0x38, 0x39}, {0x39, 0x38}, {0x3E, 0x2F}, {0x39, 0x39}, {0x39, 0x3A}, {0x3A, 0x39}, {0x3A, 0x3A}, {0x3A, 0x3A}, {0x3A, 0x3B}, {0x3B, 0x3A}, {0x3B, 0x3B}, {0x3B, 0x3B}, {0x3B, 0x3C}, {0x3C, 0x3B}, {0x3C, 0x3C}, {0x3C, 0x3C}, {0x3C, 0x3D}, {0x3D, 0x3C}, {0x3D, 0x3D}, {0x3D, 0x3D}, {0x3D, 0x3E}, {0x3E, 0x3D}, {0x3E, 0x3E}, {0x3E, 0x3E}, {0x3E, 0x3F}, {0x3F, 0x3E}, {0x3F, 0x3F}, {0x3F, 0x3F}, }; nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/000077500000000000000000000000001173441656100214125ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/Bitmaps.h000066400000000000000000000352021173441656100231640ustar00rootroot00000000000000 /* static void doPrecomputation() { uint bitmaps[1024]; int indices[16]; int num = 0; // Compute bitmaps with 3 clusters: // first cluster [0,i) is at the start for( int m = 0; m < 16; ++m ) { indices[m] = 0; } const int imax = 15; for( int i = imax; i >= 0; --i ) { // second cluster [i,j) is half along for( int m = i; m < 16; ++m ) { indices[m] = 2; } const int jmax = ( i == 0 ) ? 15 : 16; for( int j = jmax; j >= i; --j ) { // last cluster [j,k) is at the end if( j < 16 ) { indices[j] = 1; } uint bitmap = 0; for(int p = 0; p < 16; p++) { bitmap |= indices[p] << (p * 2); } bitmaps[num] = bitmap; num++; } } nvDebugCheck(num == 151); // Align to 160. for(int i = 0; i < 9; i++) { bitmaps[num] = 0x555AA000; num++; } nvDebugCheck(num == 160); // Append bitmaps with 4 clusters: // first cluster [0,i) is at the start for( int m = 0; m < 16; ++m ) { indices[m] = 0; } for( int i = imax; i >= 0; --i ) { // second cluster [i,j) is one third along for( int m = i; m < 16; ++m ) { indices[m] = 2; } const int jmax = ( i == 0 ) ? 15 : 16; for( int j = jmax; j >= i; --j ) { // third cluster [j,k) is two thirds along for( int m = j; m < 16; ++m ) { indices[m] = 3; } int kmax = ( j == 0 ) ? 15 : 16; for( int k = kmax; k >= j; --k ) { // last cluster [k,n) is at the end if( k < 16 ) { indices[k] = 1; } uint bitmap = 0; bool hasThree = false; for(int p = 0; p < 16; p++) { bitmap |= indices[p] << (p * 2); if (indices[p] == 3) hasThree = true; } if (hasThree) { bitmaps[num] = bitmap; num++; } } } } nvDebugCheck(num == 975); // Align to 1024. for(int i = 0; i < 49; i++) { bitmaps[num] = 0x555AA000; num++; } nvDebugCheck(num == 1024); printf("uint bitmaps[992] =\n{\n"); for (int i = 0; i < 992; i++) { printf("\t0x%.8X,\n", bitmaps[i]); } printf("};\n"); } */ const static uint s_bitmapTable[992] = { 0x80000000, 0x40000000, 0xA0000000, 0x60000000, 0x50000000, 0xA8000000, 0x68000000, 0x58000000, 0x54000000, 0xAA000000, 0x6A000000, 0x5A000000, 0x56000000, 0x55000000, 0xAA800000, 0x6A800000, 0x5A800000, 0x56800000, 0x55800000, 0x55400000, 0xAAA00000, 0x6AA00000, 0x5AA00000, 0x56A00000, 0x55A00000, 0x55600000, 0x55500000, 0xAAA80000, 0x6AA80000, 0x5AA80000, 0x56A80000, 0x55A80000, 0x55680000, 0x55580000, 0x55540000, 0xAAAA0000, 0x6AAA0000, 0x5AAA0000, 0x56AA0000, 0x55AA0000, 0x556A0000, 0x555A0000, 0x55560000, 0x55550000, 0xAAAA8000, 0x6AAA8000, 0x5AAA8000, 0x56AA8000, 0x55AA8000, 0x556A8000, 0x555A8000, 0x55568000, 0x55558000, 0x55554000, 0xAAAAA000, 0x6AAAA000, 0x5AAAA000, 0x56AAA000, 0x55AAA000, 0x556AA000, 0x555AA000, 0x5556A000, 0x5555A000, 0x55556000, 0x55555000, 0xAAAAA800, 0x6AAAA800, 0x5AAAA800, 0x56AAA800, 0x55AAA800, 0x556AA800, 0x555AA800, 0x5556A800, 0x5555A800, 0x55556800, 0x55555800, 0x55555400, 0xAAAAAA00, 0x6AAAAA00, 0x5AAAAA00, 0x56AAAA00, 0x55AAAA00, 0x556AAA00, 0x555AAA00, 0x5556AA00, 0x5555AA00, 0x55556A00, 0x55555A00, 0x55555600, 0x55555500, 0xAAAAAA80, 0x6AAAAA80, 0x5AAAAA80, 0x56AAAA80, 0x55AAAA80, 0x556AAA80, 0x555AAA80, 0x5556AA80, 0x5555AA80, 0x55556A80, 0x55555A80, 0x55555680, 0x55555580, 0x55555540, 0xAAAAAAA0, 0x6AAAAAA0, 0x5AAAAAA0, 0x56AAAAA0, 0x55AAAAA0, 0x556AAAA0, 0x555AAAA0, 0x5556AAA0, 0x5555AAA0, 0x55556AA0, 0x55555AA0, 0x555556A0, 0x555555A0, 0x55555560, 0x55555550, 0xAAAAAAA8, 0x6AAAAAA8, 0x5AAAAAA8, 0x56AAAAA8, 0x55AAAAA8, 0x556AAAA8, 0x555AAAA8, 0x5556AAA8, 0x5555AAA8, 0x55556AA8, 0x55555AA8, 0x555556A8, 0x555555A8, 0x55555568, 0x55555558, 0x55555554, 0x6AAAAAAA, 0x5AAAAAAA, 0x56AAAAAA, 0x55AAAAAA, 0x556AAAAA, 0x555AAAAA, 0x5556AAAA, 0x5555AAAA, 0x55556AAA, 0x55555AAA, 0x555556AA, 0x555555AA, 0x5555556A, 0x5555555A, 0x55555556, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0xC0000000, 0xE0000000, 0xF0000000, 0x70000000, 0xE8000000, 0xF8000000, 0x78000000, 0xFC000000, 0x7C000000, 0x5C000000, 0xEA000000, 0xFA000000, 0x7A000000, 0xFE000000, 0x7E000000, 0x5E000000, 0xFF000000, 0x7F000000, 0x5F000000, 0x57000000, 0xEA800000, 0xFA800000, 0x7A800000, 0xFE800000, 0x7E800000, 0x5E800000, 0xFF800000, 0x7F800000, 0x5F800000, 0x57800000, 0xFFC00000, 0x7FC00000, 0x5FC00000, 0x57C00000, 0x55C00000, 0xEAA00000, 0xFAA00000, 0x7AA00000, 0xFEA00000, 0x7EA00000, 0x5EA00000, 0xFFA00000, 0x7FA00000, 0x5FA00000, 0x57A00000, 0xFFE00000, 0x7FE00000, 0x5FE00000, 0x57E00000, 0x55E00000, 0xFFF00000, 0x7FF00000, 0x5FF00000, 0x57F00000, 0x55F00000, 0x55700000, 0xEAA80000, 0xFAA80000, 0x7AA80000, 0xFEA80000, 0x7EA80000, 0x5EA80000, 0xFFA80000, 0x7FA80000, 0x5FA80000, 0x57A80000, 0xFFE80000, 0x7FE80000, 0x5FE80000, 0x57E80000, 0x55E80000, 0xFFF80000, 0x7FF80000, 0x5FF80000, 0x57F80000, 0x55F80000, 0x55780000, 0xFFFC0000, 0x7FFC0000, 0x5FFC0000, 0x57FC0000, 0x55FC0000, 0x557C0000, 0x555C0000, 0xEAAA0000, 0xFAAA0000, 0x7AAA0000, 0xFEAA0000, 0x7EAA0000, 0x5EAA0000, 0xFFAA0000, 0x7FAA0000, 0x5FAA0000, 0x57AA0000, 0xFFEA0000, 0x7FEA0000, 0x5FEA0000, 0x57EA0000, 0x55EA0000, 0xFFFA0000, 0x7FFA0000, 0x5FFA0000, 0x57FA0000, 0x55FA0000, 0x557A0000, 0xFFFE0000, 0x7FFE0000, 0x5FFE0000, 0x57FE0000, 0x55FE0000, 0x557E0000, 0x555E0000, 0xFFFF0000, 0x7FFF0000, 0x5FFF0000, 0x57FF0000, 0x55FF0000, 0x557F0000, 0x555F0000, 0x55570000, 0xEAAA8000, 0xFAAA8000, 0x7AAA8000, 0xFEAA8000, 0x7EAA8000, 0x5EAA8000, 0xFFAA8000, 0x7FAA8000, 0x5FAA8000, 0x57AA8000, 0xFFEA8000, 0x7FEA8000, 0x5FEA8000, 0x57EA8000, 0x55EA8000, 0xFFFA8000, 0x7FFA8000, 0x5FFA8000, 0x57FA8000, 0x55FA8000, 0x557A8000, 0xFFFE8000, 0x7FFE8000, 0x5FFE8000, 0x57FE8000, 0x55FE8000, 0x557E8000, 0x555E8000, 0xFFFF8000, 0x7FFF8000, 0x5FFF8000, 0x57FF8000, 0x55FF8000, 0x557F8000, 0x555F8000, 0x55578000, 0xFFFFC000, 0x7FFFC000, 0x5FFFC000, 0x57FFC000, 0x55FFC000, 0x557FC000, 0x555FC000, 0x5557C000, 0x5555C000, 0xEAAAA000, 0xFAAAA000, 0x7AAAA000, 0xFEAAA000, 0x7EAAA000, 0x5EAAA000, 0xFFAAA000, 0x7FAAA000, 0x5FAAA000, 0x57AAA000, 0xFFEAA000, 0x7FEAA000, 0x5FEAA000, 0x57EAA000, 0x55EAA000, 0xFFFAA000, 0x7FFAA000, 0x5FFAA000, 0x57FAA000, 0x55FAA000, 0x557AA000, 0xFFFEA000, 0x7FFEA000, 0x5FFEA000, 0x57FEA000, 0x55FEA000, 0x557EA000, 0x555EA000, 0xFFFFA000, 0x7FFFA000, 0x5FFFA000, 0x57FFA000, 0x55FFA000, 0x557FA000, 0x555FA000, 0x5557A000, 0xFFFFE000, 0x7FFFE000, 0x5FFFE000, 0x57FFE000, 0x55FFE000, 0x557FE000, 0x555FE000, 0x5557E000, 0x5555E000, 0xFFFFF000, 0x7FFFF000, 0x5FFFF000, 0x57FFF000, 0x55FFF000, 0x557FF000, 0x555FF000, 0x5557F000, 0x5555F000, 0x55557000, 0xEAAAA800, 0xFAAAA800, 0x7AAAA800, 0xFEAAA800, 0x7EAAA800, 0x5EAAA800, 0xFFAAA800, 0x7FAAA800, 0x5FAAA800, 0x57AAA800, 0xFFEAA800, 0x7FEAA800, 0x5FEAA800, 0x57EAA800, 0x55EAA800, 0xFFFAA800, 0x7FFAA800, 0x5FFAA800, 0x57FAA800, 0x55FAA800, 0x557AA800, 0xFFFEA800, 0x7FFEA800, 0x5FFEA800, 0x57FEA800, 0x55FEA800, 0x557EA800, 0x555EA800, 0xFFFFA800, 0x7FFFA800, 0x5FFFA800, 0x57FFA800, 0x55FFA800, 0x557FA800, 0x555FA800, 0x5557A800, 0xFFFFE800, 0x7FFFE800, 0x5FFFE800, 0x57FFE800, 0x55FFE800, 0x557FE800, 0x555FE800, 0x5557E800, 0x5555E800, 0xFFFFF800, 0x7FFFF800, 0x5FFFF800, 0x57FFF800, 0x55FFF800, 0x557FF800, 0x555FF800, 0x5557F800, 0x5555F800, 0x55557800, 0xFFFFFC00, 0x7FFFFC00, 0x5FFFFC00, 0x57FFFC00, 0x55FFFC00, 0x557FFC00, 0x555FFC00, 0x5557FC00, 0x5555FC00, 0x55557C00, 0x55555C00, 0xEAAAAA00, 0xFAAAAA00, 0x7AAAAA00, 0xFEAAAA00, 0x7EAAAA00, 0x5EAAAA00, 0xFFAAAA00, 0x7FAAAA00, 0x5FAAAA00, 0x57AAAA00, 0xFFEAAA00, 0x7FEAAA00, 0x5FEAAA00, 0x57EAAA00, 0x55EAAA00, 0xFFFAAA00, 0x7FFAAA00, 0x5FFAAA00, 0x57FAAA00, 0x55FAAA00, 0x557AAA00, 0xFFFEAA00, 0x7FFEAA00, 0x5FFEAA00, 0x57FEAA00, 0x55FEAA00, 0x557EAA00, 0x555EAA00, 0xFFFFAA00, 0x7FFFAA00, 0x5FFFAA00, 0x57FFAA00, 0x55FFAA00, 0x557FAA00, 0x555FAA00, 0x5557AA00, 0xFFFFEA00, 0x7FFFEA00, 0x5FFFEA00, 0x57FFEA00, 0x55FFEA00, 0x557FEA00, 0x555FEA00, 0x5557EA00, 0x5555EA00, 0xFFFFFA00, 0x7FFFFA00, 0x5FFFFA00, 0x57FFFA00, 0x55FFFA00, 0x557FFA00, 0x555FFA00, 0x5557FA00, 0x5555FA00, 0x55557A00, 0xFFFFFE00, 0x7FFFFE00, 0x5FFFFE00, 0x57FFFE00, 0x55FFFE00, 0x557FFE00, 0x555FFE00, 0x5557FE00, 0x5555FE00, 0x55557E00, 0x55555E00, 0xFFFFFF00, 0x7FFFFF00, 0x5FFFFF00, 0x57FFFF00, 0x55FFFF00, 0x557FFF00, 0x555FFF00, 0x5557FF00, 0x5555FF00, 0x55557F00, 0x55555F00, 0x55555700, 0xEAAAAA80, 0xFAAAAA80, 0x7AAAAA80, 0xFEAAAA80, 0x7EAAAA80, 0x5EAAAA80, 0xFFAAAA80, 0x7FAAAA80, 0x5FAAAA80, 0x57AAAA80, 0xFFEAAA80, 0x7FEAAA80, 0x5FEAAA80, 0x57EAAA80, 0x55EAAA80, 0xFFFAAA80, 0x7FFAAA80, 0x5FFAAA80, 0x57FAAA80, 0x55FAAA80, 0x557AAA80, 0xFFFEAA80, 0x7FFEAA80, 0x5FFEAA80, 0x57FEAA80, 0x55FEAA80, 0x557EAA80, 0x555EAA80, 0xFFFFAA80, 0x7FFFAA80, 0x5FFFAA80, 0x57FFAA80, 0x55FFAA80, 0x557FAA80, 0x555FAA80, 0x5557AA80, 0xFFFFEA80, 0x7FFFEA80, 0x5FFFEA80, 0x57FFEA80, 0x55FFEA80, 0x557FEA80, 0x555FEA80, 0x5557EA80, 0x5555EA80, 0xFFFFFA80, 0x7FFFFA80, 0x5FFFFA80, 0x57FFFA80, 0x55FFFA80, 0x557FFA80, 0x555FFA80, 0x5557FA80, 0x5555FA80, 0x55557A80, 0xFFFFFE80, 0x7FFFFE80, 0x5FFFFE80, 0x57FFFE80, 0x55FFFE80, 0x557FFE80, 0x555FFE80, 0x5557FE80, 0x5555FE80, 0x55557E80, 0x55555E80, 0xFFFFFF80, 0x7FFFFF80, 0x5FFFFF80, 0x57FFFF80, 0x55FFFF80, 0x557FFF80, 0x555FFF80, 0x5557FF80, 0x5555FF80, 0x55557F80, 0x55555F80, 0x55555780, 0xFFFFFFC0, 0x7FFFFFC0, 0x5FFFFFC0, 0x57FFFFC0, 0x55FFFFC0, 0x557FFFC0, 0x555FFFC0, 0x5557FFC0, 0x5555FFC0, 0x55557FC0, 0x55555FC0, 0x555557C0, 0x555555C0, 0xEAAAAAA0, 0xFAAAAAA0, 0x7AAAAAA0, 0xFEAAAAA0, 0x7EAAAAA0, 0x5EAAAAA0, 0xFFAAAAA0, 0x7FAAAAA0, 0x5FAAAAA0, 0x57AAAAA0, 0xFFEAAAA0, 0x7FEAAAA0, 0x5FEAAAA0, 0x57EAAAA0, 0x55EAAAA0, 0xFFFAAAA0, 0x7FFAAAA0, 0x5FFAAAA0, 0x57FAAAA0, 0x55FAAAA0, 0x557AAAA0, 0xFFFEAAA0, 0x7FFEAAA0, 0x5FFEAAA0, 0x57FEAAA0, 0x55FEAAA0, 0x557EAAA0, 0x555EAAA0, 0xFFFFAAA0, 0x7FFFAAA0, 0x5FFFAAA0, 0x57FFAAA0, 0x55FFAAA0, 0x557FAAA0, 0x555FAAA0, 0x5557AAA0, 0xFFFFEAA0, 0x7FFFEAA0, 0x5FFFEAA0, 0x57FFEAA0, 0x55FFEAA0, 0x557FEAA0, 0x555FEAA0, 0x5557EAA0, 0x5555EAA0, 0xFFFFFAA0, 0x7FFFFAA0, 0x5FFFFAA0, 0x57FFFAA0, 0x55FFFAA0, 0x557FFAA0, 0x555FFAA0, 0x5557FAA0, 0x5555FAA0, 0x55557AA0, 0xFFFFFEA0, 0x7FFFFEA0, 0x5FFFFEA0, 0x57FFFEA0, 0x55FFFEA0, 0x557FFEA0, 0x555FFEA0, 0x5557FEA0, 0x5555FEA0, 0x55557EA0, 0x55555EA0, 0xFFFFFFA0, 0x7FFFFFA0, 0x5FFFFFA0, 0x57FFFFA0, 0x55FFFFA0, 0x557FFFA0, 0x555FFFA0, 0x5557FFA0, 0x5555FFA0, 0x55557FA0, 0x55555FA0, 0x555557A0, 0xFFFFFFE0, 0x7FFFFFE0, 0x5FFFFFE0, 0x57FFFFE0, 0x55FFFFE0, 0x557FFFE0, 0x555FFFE0, 0x5557FFE0, 0x5555FFE0, 0x55557FE0, 0x55555FE0, 0x555557E0, 0x555555E0, 0xFFFFFFF0, 0x7FFFFFF0, 0x5FFFFFF0, 0x57FFFFF0, 0x55FFFFF0, 0x557FFFF0, 0x555FFFF0, 0x5557FFF0, 0x5555FFF0, 0x55557FF0, 0x55555FF0, 0x555557F0, 0x555555F0, 0x55555570, 0xEAAAAAA8, 0xFAAAAAA8, 0x7AAAAAA8, 0xFEAAAAA8, 0x7EAAAAA8, 0x5EAAAAA8, 0xFFAAAAA8, 0x7FAAAAA8, 0x5FAAAAA8, 0x57AAAAA8, 0xFFEAAAA8, 0x7FEAAAA8, 0x5FEAAAA8, 0x57EAAAA8, 0x55EAAAA8, 0xFFFAAAA8, 0x7FFAAAA8, 0x5FFAAAA8, 0x57FAAAA8, 0x55FAAAA8, 0x557AAAA8, 0xFFFEAAA8, 0x7FFEAAA8, 0x5FFEAAA8, 0x57FEAAA8, 0x55FEAAA8, 0x557EAAA8, 0x555EAAA8, 0xFFFFAAA8, 0x7FFFAAA8, 0x5FFFAAA8, 0x57FFAAA8, 0x55FFAAA8, 0x557FAAA8, 0x555FAAA8, 0x5557AAA8, 0xFFFFEAA8, 0x7FFFEAA8, 0x5FFFEAA8, 0x57FFEAA8, 0x55FFEAA8, 0x557FEAA8, 0x555FEAA8, 0x5557EAA8, 0x5555EAA8, 0xFFFFFAA8, 0x7FFFFAA8, 0x5FFFFAA8, 0x57FFFAA8, 0x55FFFAA8, 0x557FFAA8, 0x555FFAA8, 0x5557FAA8, 0x5555FAA8, 0x55557AA8, 0xFFFFFEA8, 0x7FFFFEA8, 0x5FFFFEA8, 0x57FFFEA8, 0x55FFFEA8, 0x557FFEA8, 0x555FFEA8, 0x5557FEA8, 0x5555FEA8, 0x55557EA8, 0x55555EA8, 0xFFFFFFA8, 0x7FFFFFA8, 0x5FFFFFA8, 0x57FFFFA8, 0x55FFFFA8, 0x557FFFA8, 0x555FFFA8, 0x5557FFA8, 0x5555FFA8, 0x55557FA8, 0x55555FA8, 0x555557A8, 0xFFFFFFE8, 0x7FFFFFE8, 0x5FFFFFE8, 0x57FFFFE8, 0x55FFFFE8, 0x557FFFE8, 0x555FFFE8, 0x5557FFE8, 0x5555FFE8, 0x55557FE8, 0x55555FE8, 0x555557E8, 0x555555E8, 0xFFFFFFF8, 0x7FFFFFF8, 0x5FFFFFF8, 0x57FFFFF8, 0x55FFFFF8, 0x557FFFF8, 0x555FFFF8, 0x5557FFF8, 0x5555FFF8, 0x55557FF8, 0x55555FF8, 0x555557F8, 0x555555F8, 0x55555578, 0xFFFFFFFC, 0x7FFFFFFC, 0x5FFFFFFC, 0x57FFFFFC, 0x55FFFFFC, 0x557FFFFC, 0x555FFFFC, 0x5557FFFC, 0x5555FFFC, 0x55557FFC, 0x55555FFC, 0x555557FC, 0x555555FC, 0x5555557C, 0x5555555C, 0xEAAAAAAA, 0xFAAAAAAA, 0x7AAAAAAA, 0xFEAAAAAA, 0x7EAAAAAA, 0x5EAAAAAA, 0xFFAAAAAA, 0x7FAAAAAA, 0x5FAAAAAA, 0x57AAAAAA, 0xFFEAAAAA, 0x7FEAAAAA, 0x5FEAAAAA, 0x57EAAAAA, 0x55EAAAAA, 0xFFFAAAAA, 0x7FFAAAAA, 0x5FFAAAAA, 0x57FAAAAA, 0x55FAAAAA, 0x557AAAAA, 0xFFFEAAAA, 0x7FFEAAAA, 0x5FFEAAAA, 0x57FEAAAA, 0x55FEAAAA, 0x557EAAAA, 0x555EAAAA, 0xFFFFAAAA, 0x7FFFAAAA, 0x5FFFAAAA, 0x57FFAAAA, 0x55FFAAAA, 0x557FAAAA, 0x555FAAAA, 0x5557AAAA, 0xFFFFEAAA, 0x7FFFEAAA, 0x5FFFEAAA, 0x57FFEAAA, 0x55FFEAAA, 0x557FEAAA, 0x555FEAAA, 0x5557EAAA, 0x5555EAAA, 0xFFFFFAAA, 0x7FFFFAAA, 0x5FFFFAAA, 0x57FFFAAA, 0x55FFFAAA, 0x557FFAAA, 0x555FFAAA, 0x5557FAAA, 0x5555FAAA, 0x55557AAA, 0xFFFFFEAA, 0x7FFFFEAA, 0x5FFFFEAA, 0x57FFFEAA, 0x55FFFEAA, 0x557FFEAA, 0x555FFEAA, 0x5557FEAA, 0x5555FEAA, 0x55557EAA, 0x55555EAA, 0xFFFFFFAA, 0x7FFFFFAA, 0x5FFFFFAA, 0x57FFFFAA, 0x55FFFFAA, 0x557FFFAA, 0x555FFFAA, 0x5557FFAA, 0x5555FFAA, 0x55557FAA, 0x55555FAA, 0x555557AA, 0xFFFFFFEA, 0x7FFFFFEA, 0x5FFFFFEA, 0x57FFFFEA, 0x55FFFFEA, 0x557FFFEA, 0x555FFFEA, 0x5557FFEA, 0x5555FFEA, 0x55557FEA, 0x55555FEA, 0x555557EA, 0x555555EA, 0xFFFFFFFA, 0x7FFFFFFA, 0x5FFFFFFA, 0x57FFFFFA, 0x55FFFFFA, 0x557FFFFA, 0x555FFFFA, 0x5557FFFA, 0x5555FFFA, 0x55557FFA, 0x55555FFA, 0x555557FA, 0x555555FA, 0x5555557A, 0xFFFFFFFE, 0x7FFFFFFE, 0x5FFFFFFE, 0x57FFFFFE, 0x55FFFFFE, 0x557FFFFE, 0x555FFFFE, 0x5557FFFE, 0x5555FFFE, 0x55557FFE, 0x55555FFE, 0x555557FE, 0x555555FE, 0x5555557E, 0x5555555E, 0x7FFFFFFF, 0x5FFFFFFF, 0x57FFFFFF, 0x55FFFFFF, 0x557FFFFF, 0x555FFFFF, 0x5557FFFF, 0x5555FFFF, 0x55557FFF, 0x55555FFF, 0x555557FF, 0x555555FF, 0x5555557F, 0x5555555F, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, 0x55555557, }; nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/CompressKernel.cu000066400000000000000000000752221173441656100247070ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include "CudaMath.h" #include "../SingleColorLookup.h" #define NUM_THREADS 64 // Number of threads per block. #if __DEVICE_EMULATION__ #define __debugsync() __syncthreads() #else #define __debugsync() #endif typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; template __device__ inline void swap(T & a, T & b) { T tmp = a; a = b; b = tmp; } __constant__ float3 kColorMetric = { 1.0f, 1.0f, 1.0f }; __constant__ float3 kColorMetricSqr = { 1.0f, 1.0f, 1.0f }; //////////////////////////////////////////////////////////////////////////////// // Sort colors //////////////////////////////////////////////////////////////////////////////// __device__ void sortColors(const float * values, int * cmp) { int tid = threadIdx.x; #if 1 cmp[tid] = (values[0] < values[tid]); cmp[tid] += (values[1] < values[tid]); cmp[tid] += (values[2] < values[tid]); cmp[tid] += (values[3] < values[tid]); cmp[tid] += (values[4] < values[tid]); cmp[tid] += (values[5] < values[tid]); cmp[tid] += (values[6] < values[tid]); cmp[tid] += (values[7] < values[tid]); cmp[tid] += (values[8] < values[tid]); cmp[tid] += (values[9] < values[tid]); cmp[tid] += (values[10] < values[tid]); cmp[tid] += (values[11] < values[tid]); cmp[tid] += (values[12] < values[tid]); cmp[tid] += (values[13] < values[tid]); cmp[tid] += (values[14] < values[tid]); cmp[tid] += (values[15] < values[tid]); // Resolve elements with the same index. if (tid > 0 && cmp[tid] == cmp[0]) ++cmp[tid]; if (tid > 1 && cmp[tid] == cmp[1]) ++cmp[tid]; if (tid > 2 && cmp[tid] == cmp[2]) ++cmp[tid]; if (tid > 3 && cmp[tid] == cmp[3]) ++cmp[tid]; if (tid > 4 && cmp[tid] == cmp[4]) ++cmp[tid]; if (tid > 5 && cmp[tid] == cmp[5]) ++cmp[tid]; if (tid > 6 && cmp[tid] == cmp[6]) ++cmp[tid]; if (tid > 7 && cmp[tid] == cmp[7]) ++cmp[tid]; if (tid > 8 && cmp[tid] == cmp[8]) ++cmp[tid]; if (tid > 9 && cmp[tid] == cmp[9]) ++cmp[tid]; if (tid > 10 && cmp[tid] == cmp[10]) ++cmp[tid]; if (tid > 11 && cmp[tid] == cmp[11]) ++cmp[tid]; if (tid > 12 && cmp[tid] == cmp[12]) ++cmp[tid]; if (tid > 13 && cmp[tid] == cmp[13]) ++cmp[tid]; if (tid > 14 && cmp[tid] == cmp[14]) ++cmp[tid]; #else cmp[tid] = 0; #pragma unroll for (int i = 0; i < 16; i++) { cmp[tid] += (values[i] < values[tid]); } // Resolve elements with the same index. #pragma unroll for (int i = 0; i < 15; i++) { if (tid > 0 && cmp[tid] == cmp[i]) ++cmp[tid]; } #endif } //////////////////////////////////////////////////////////////////////////////// // Load color block to shared mem //////////////////////////////////////////////////////////////////////////////// __device__ void loadColorBlock(const uint * image, float3 colors[16], float3 sums[16], int xrefs[16], int * sameColor) { const int bid = blockIdx.x; const int idx = threadIdx.x; __shared__ float dps[16]; if (idx < 16) { // Read color and copy to shared mem. uint c = image[(bid) * 16 + idx]; colors[idx].z = ((c >> 0) & 0xFF) * (1.0f / 255.0f); colors[idx].y = ((c >> 8) & 0xFF) * (1.0f / 255.0f); colors[idx].x = ((c >> 16) & 0xFF) * (1.0f / 255.0f); // No need to synchronize, 16 < warp size. #if __DEVICE_EMULATION__ } __debugsync(); if (idx < 16) { #endif // Sort colors along the best fit line. colorSums(colors, sums); float3 axis = bestFitLine(colors, sums[0], kColorMetric); *sameColor = (axis == make_float3(0, 0, 0)); dps[idx] = dot(colors[idx], axis); #if __DEVICE_EMULATION__ } __debugsync(); if (idx < 16) { #endif sortColors(dps, xrefs); float3 tmp = colors[idx]; colors[xrefs[idx]] = tmp; } } __device__ void loadColorBlock(const uint * image, float3 colors[16], float3 sums[16], float weights[16], int xrefs[16], int * sameColor) { const int bid = blockIdx.x; const int idx = threadIdx.x; __shared__ float3 rawColors[16]; __shared__ float dps[16]; if (idx < 16) { // Read color and copy to shared mem. uint c = image[(bid) * 16 + idx]; rawColors[idx].z = ((c >> 0) & 0xFF) * (1.0f / 255.0f); rawColors[idx].y = ((c >> 8) & 0xFF) * (1.0f / 255.0f); rawColors[idx].x = ((c >> 16) & 0xFF) * (1.0f / 255.0f); weights[idx] = (((c >> 24) & 0xFF) + 1) * (1.0f / 256.0f); colors[idx] = rawColors[idx] * weights[idx]; // No need to synchronize, 16 < warp size. #if __DEVICE_EMULATION__ } __debugsync(); if (idx < 16) { #endif // Sort colors along the best fit line. colorSums(colors, sums); float3 axis = bestFitLine(colors, sums[0], kColorMetric); *sameColor = (axis == make_float3(0, 0, 0)); // Single color compressor needs unweighted colors. if (*sameColor) colors[idx] = rawColors[idx]; dps[idx] = dot(rawColors[idx], axis); #if __DEVICE_EMULATION__ } __debugsync(); if (idx < 16) { #endif sortColors(dps, xrefs); float3 tmp = colors[idx]; colors[xrefs[idx]] = tmp; float w = weights[idx]; weights[xrefs[idx]] = w; } } //////////////////////////////////////////////////////////////////////////////// // Round color to RGB565 and expand //////////////////////////////////////////////////////////////////////////////// inline __device__ float3 roundAndExpand565(float3 v, ushort * w) { v.x = rintf(__saturatef(v.x) * 31.0f); v.y = rintf(__saturatef(v.y) * 63.0f); v.z = rintf(__saturatef(v.z) * 31.0f); *w = ((ushort)v.x << 11) | ((ushort)v.y << 5) | (ushort)v.z; v.x *= 0.03227752766457f; // approximate integer bit expansion. v.y *= 0.01583151765563f; v.z *= 0.03227752766457f; return v; } //////////////////////////////////////////////////////////////////////////////// // Evaluate permutations //////////////////////////////////////////////////////////////////////////////// __device__ float evalPermutation4(const float3 * colors, uint permutation, ushort * start, ushort * end) { // Compute endpoints using least squares. float alpha2_sum = 0.0f; float beta2_sum = 0.0f; float alphabeta_sum = 0.0f; float3 alphax_sum = make_float3(0.0f, 0.0f, 0.0f); float3 betax_sum = make_float3(0.0f, 0.0f, 0.0f); // Compute alpha & beta for this permutation. for (int i = 0; i < 16; i++) { const uint bits = permutation >> (2*i); float beta = (bits & 1); if (bits & 2) beta = (1 + beta) / 3.0f; float alpha = 1.0f - beta; alpha2_sum += alpha * alpha; beta2_sum += beta * beta; alphabeta_sum += alpha * beta; alphax_sum += alpha * colors[i]; betax_sum += beta * colors[i]; } const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; // Round a, b to the closest 5-6-5 color and expand... a = roundAndExpand565(a, start); b = roundAndExpand565(b, end); // compute the error float3 e = a * a * alpha2_sum + b * b * beta2_sum + 2.0f * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum); return dot(e, kColorMetricSqr); } __device__ float evalPermutation3(const float3 * colors, uint permutation, ushort * start, ushort * end) { // Compute endpoints using least squares. float alpha2_sum = 0.0f; float beta2_sum = 0.0f; float alphabeta_sum = 0.0f; float3 alphax_sum = make_float3(0.0f, 0.0f, 0.0f); float3 betax_sum = make_float3(0.0f, 0.0f, 0.0f); // Compute alpha & beta for this permutation. for (int i = 0; i < 16; i++) { const uint bits = permutation >> (2*i); float beta = (bits & 1); if (bits & 2) beta = 0.5f; float alpha = 1.0f - beta; alpha2_sum += alpha * alpha; beta2_sum += beta * beta; alphabeta_sum += alpha * beta; alphax_sum += alpha * colors[i]; betax_sum += beta * colors[i]; } const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; // Round a, b to the closest 5-6-5 color and expand... a = roundAndExpand565(a, start); b = roundAndExpand565(b, end); // compute the error float3 e = a * a * alpha2_sum + b * b * beta2_sum + 2.0f * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum); return dot(e, kColorMetricSqr); } __constant__ const float alphaTable4[4] = { 9.0f, 0.0f, 6.0f, 3.0f }; __constant__ const float alphaTable3[4] = { 4.0f, 0.0f, 2.0f, 2.0f }; __constant__ const uint prods4[4] = { 0x090000,0x000900,0x040102,0x010402 }; __constant__ const uint prods3[4] = { 0x040000,0x000400,0x040101,0x010401 }; __device__ float evalPermutation4(const float3 * colors, float3 color_sum, uint permutation, ushort * start, ushort * end) { // Compute endpoints using least squares. float3 alphax_sum = make_float3(0.0f, 0.0f, 0.0f); uint akku = 0; // Compute alpha & beta for this permutation. #pragma unroll for (int i = 0; i < 16; i++) { const uint bits = permutation >> (2*i); alphax_sum += alphaTable4[bits & 3] * colors[i]; akku += prods4[bits & 3]; } float alpha2_sum = float(akku >> 16); float beta2_sum = float((akku >> 8) & 0xff); float alphabeta_sum = float(akku & 0xff); float3 betax_sum = 9.0f * color_sum - alphax_sum; const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; // Round a, b to the closest 5-6-5 color and expand... a = roundAndExpand565(a, start); b = roundAndExpand565(b, end); // compute the error float3 e = a * a * alpha2_sum + b * b * beta2_sum + 2.0f * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum); return (1.0f / 9.0f) * dot(e, kColorMetricSqr); } __device__ float evalPermutation3(const float3 * colors, float3 color_sum, uint permutation, ushort * start, ushort * end) { // Compute endpoints using least squares. float3 alphax_sum = make_float3(0.0f, 0.0f, 0.0f); uint akku = 0; // Compute alpha & beta for this permutation. #pragma unroll for (int i = 0; i < 16; i++) { const uint bits = permutation >> (2*i); alphax_sum += alphaTable3[bits & 3] * colors[i]; akku += prods3[bits & 3]; } float alpha2_sum = float(akku >> 16); float beta2_sum = float((akku >> 8) & 0xff); float alphabeta_sum = float(akku & 0xff); float3 betax_sum = 4.0f * color_sum - alphax_sum; const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; // Round a, b to the closest 5-6-5 color and expand... a = roundAndExpand565(a, start); b = roundAndExpand565(b, end); // compute the error float3 e = a * a * alpha2_sum + b * b * beta2_sum + 2.0f * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum); return (1.0f / 4.0f) * dot(e, kColorMetricSqr); } __device__ float evalPermutation4(const float3 * colors, const float * weights, float3 color_sum, uint permutation, ushort * start, ushort * end) { // Compute endpoints using least squares. float alpha2_sum = 0.0f; float beta2_sum = 0.0f; float alphabeta_sum = 0.0f; float3 alphax_sum = make_float3(0.0f, 0.0f, 0.0f); // Compute alpha & beta for this permutation. for (int i = 0; i < 16; i++) { const uint bits = permutation >> (2*i); float beta = (bits & 1); if (bits & 2) beta = (1 + beta) / 3.0f; float alpha = 1.0f - beta; alpha2_sum += alpha * alpha * weights[i]; beta2_sum += beta * beta * weights[i]; alphabeta_sum += alpha * beta * weights[i]; alphax_sum += alpha * colors[i]; } float3 betax_sum = color_sum - alphax_sum; const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; // Round a, b to the closest 5-6-5 color and expand... a = roundAndExpand565(a, start); b = roundAndExpand565(b, end); // compute the error float3 e = a * a * alpha2_sum + b * b * beta2_sum + 2.0f * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum); return dot(e, kColorMetricSqr); } /* __device__ float evalPermutation3(const float3 * colors, const float * weights, uint permutation, ushort * start, ushort * end) { // Compute endpoints using least squares. float alpha2_sum = 0.0f; float beta2_sum = 0.0f; float alphabeta_sum = 0.0f; float3 alphax_sum = make_float3(0.0f, 0.0f, 0.0f); // Compute alpha & beta for this permutation. for (int i = 0; i < 16; i++) { const uint bits = permutation >> (2*i); float beta = (bits & 1); if (bits & 2) beta = 0.5f; float alpha = 1.0f - beta; alpha2_sum += alpha * alpha * weights[i]; beta2_sum += beta * beta * weights[i]; alphabeta_sum += alpha * beta * weights[i]; alphax_sum += alpha * colors[i]; } float3 betax_sum = color_sum - alphax_sum; const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float3 a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float3 b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; // Round a, b to the closest 5-6-5 color and expand... a = roundAndExpand565(a, start); b = roundAndExpand565(b, end); // compute the error float3 e = a * a * alpha2_sum + b * b * beta2_sum + 2.0f * (a * b * alphabeta_sum - a * alphax_sum - b * betax_sum); return dot(e, kColorMetricSqr); } */ //////////////////////////////////////////////////////////////////////////////// // Evaluate all permutations //////////////////////////////////////////////////////////////////////////////// __device__ void evalAllPermutations(const float3 * colors, float3 colorSum, const uint * permutations, ushort & bestStart, ushort & bestEnd, uint & bestPermutation, float * errors) { const int idx = threadIdx.x; float bestError = FLT_MAX; __shared__ uint s_permutations[160]; for(int i = 0; i < 16; i++) { int pidx = idx + NUM_THREADS * i; if (pidx >= 992) break; ushort start, end; uint permutation = permutations[pidx]; if (pidx < 160) s_permutations[pidx] = permutation; float error = evalPermutation4(colors, colorSum, permutation, &start, &end); if (error < bestError) { bestError = error; bestPermutation = permutation; bestStart = start; bestEnd = end; } } if (bestStart < bestEnd) { swap(bestEnd, bestStart); bestPermutation ^= 0x55555555; // Flip indices. } for(int i = 0; i < 3; i++) { int pidx = idx + NUM_THREADS * i; if (pidx >= 160) break; ushort start, end; uint permutation = s_permutations[pidx]; float error = evalPermutation3(colors, colorSum, permutation, &start, &end); if (error < bestError) { bestError = error; bestPermutation = permutation; bestStart = start; bestEnd = end; if (bestStart > bestEnd) { swap(bestEnd, bestStart); bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices. } } } errors[idx] = bestError; } /* __device__ void evalAllPermutations(const float3 * colors, const float * weights, const uint * permutations, ushort & bestStart, ushort & bestEnd, uint & bestPermutation, float * errors) { const int idx = threadIdx.x; float bestError = FLT_MAX; __shared__ uint s_permutations[160]; for(int i = 0; i < 16; i++) { int pidx = idx + NUM_THREADS * i; if (pidx >= 992) break; ushort start, end; uint permutation = permutations[pidx]; if (pidx < 160) s_permutations[pidx] = permutation; float error = evalPermutation4(colors, weights, permutation, &start, &end); if (error < bestError) { bestError = error; bestPermutation = permutation; bestStart = start; bestEnd = end; } } if (bestStart < bestEnd) { swap(bestEnd, bestStart); bestPermutation ^= 0x55555555; // Flip indices. } for(int i = 0; i < 3; i++) { int pidx = idx + NUM_THREADS * i; if (pidx >= 160) break; ushort start, end; uint permutation = s_permutations[pidx]; float error = evalPermutation3(colors, weights, permutation, &start, &end); if (error < bestError) { bestError = error; bestPermutation = permutation; bestStart = start; bestEnd = end; if (bestStart > bestEnd) { swap(bestEnd, bestStart); bestPermutation ^= (~bestPermutation >> 1) & 0x55555555; // Flip indices. } } } errors[idx] = bestError; } */ __device__ void evalLevel4Permutations(const float3 * colors, float3 colorSum, const uint * permutations, ushort & bestStart, ushort & bestEnd, uint & bestPermutation, float * errors) { const int idx = threadIdx.x; float bestError = FLT_MAX; for(int i = 0; i < 16; i++) { int pidx = idx + NUM_THREADS * i; if (pidx >= 992) break; ushort start, end; uint permutation = permutations[pidx]; float error = evalPermutation4(colors, colorSum, permutation, &start, &end); if (error < bestError) { bestError = error; bestPermutation = permutation; bestStart = start; bestEnd = end; } } if (bestStart < bestEnd) { swap(bestEnd, bestStart); bestPermutation ^= 0x55555555; // Flip indices. } errors[idx] = bestError; } __device__ void evalLevel4Permutations(const float3 * colors, const float * weights, float3 colorSum, const uint * permutations, ushort & bestStart, ushort & bestEnd, uint & bestPermutation, float * errors) { const int idx = threadIdx.x; float bestError = FLT_MAX; for(int i = 0; i < 16; i++) { int pidx = idx + NUM_THREADS * i; if (pidx >= 992) break; ushort start, end; uint permutation = permutations[pidx]; float error = evalPermutation4(colors, weights, colorSum, permutation, &start, &end); if (error < bestError) { bestError = error; bestPermutation = permutation; bestStart = start; bestEnd = end; } } if (bestStart < bestEnd) { swap(bestEnd, bestStart); bestPermutation ^= 0x55555555; // Flip indices. } errors[idx] = bestError; } //////////////////////////////////////////////////////////////////////////////// // Find index with minimum error //////////////////////////////////////////////////////////////////////////////// __device__ int findMinError(float * errors) { const int idx = threadIdx.x; __shared__ int indices[NUM_THREADS]; indices[idx] = idx; #if __DEVICE_EMULATION__ for(int d = NUM_THREADS/2; d > 0; d >>= 1) { __syncthreads(); if (idx < d) { float err0 = errors[idx]; float err1 = errors[idx + d]; if (err1 < err0) { errors[idx] = err1; indices[idx] = indices[idx + d]; } } } #else for(int d = NUM_THREADS/2; d > 32; d >>= 1) { __syncthreads(); if (idx < d) { float err0 = errors[idx]; float err1 = errors[idx + d]; if (err1 < err0) { errors[idx] = err1; indices[idx] = indices[idx + d]; } } } __syncthreads(); // unroll last 6 iterations if (idx < 32) { if (errors[idx + 32] < errors[idx]) { errors[idx] = errors[idx + 32]; indices[idx] = indices[idx + 32]; } if (errors[idx + 16] < errors[idx]) { errors[idx] = errors[idx + 16]; indices[idx] = indices[idx + 16]; } if (errors[idx + 8] < errors[idx]) { errors[idx] = errors[idx + 8]; indices[idx] = indices[idx + 8]; } if (errors[idx + 4] < errors[idx]) { errors[idx] = errors[idx + 4]; indices[idx] = indices[idx + 4]; } if (errors[idx + 2] < errors[idx]) { errors[idx] = errors[idx + 2]; indices[idx] = indices[idx + 2]; } if (errors[idx + 1] < errors[idx]) { errors[idx] = errors[idx + 1]; indices[idx] = indices[idx + 1]; } } #endif __syncthreads(); return indices[0]; } //////////////////////////////////////////////////////////////////////////////// // Save DXT block //////////////////////////////////////////////////////////////////////////////// __device__ void saveBlockDXT1(ushort start, ushort end, uint permutation, int xrefs[16], uint2 * result) { const int bid = blockIdx.x; if (start == end) { permutation = 0; } // Reorder permutation. uint indices = 0; for(int i = 0; i < 16; i++) { int ref = xrefs[i]; indices |= ((permutation >> (2 * ref)) & 3) << (2 * i); } // Write endpoints. result[bid].x = (end << 16) | start; // Write palette indices. result[bid].y = indices; } __device__ void saveSingleColorBlockDXT1(float3 color, uint2 * result) { const int bid = blockIdx.x; int r = color.x * 255; int g = color.y * 255; int b = color.z * 255; ushort color0 = (OMatch5[r][0] << 11) | (OMatch6[g][0] << 5) | OMatch5[b][0]; ushort color1 = (OMatch5[r][1] << 11) | (OMatch6[g][1] << 5) | OMatch5[b][1]; if (color0 < color1) { result[bid].x = (color0 << 16) | color1; result[bid].y = 0xffffffff; } else { result[bid].x = (color1 << 16) | color0; result[bid].y = 0xaaaaaaaa; } } //////////////////////////////////////////////////////////////////////////////// // Compress color block //////////////////////////////////////////////////////////////////////////////// __global__ void compressDXT1(const uint * permutations, const uint * image, uint2 * result) { __shared__ float3 colors[16]; __shared__ float3 sums[16]; __shared__ int xrefs[16]; __shared__ int sameColor; loadColorBlock(image, colors, sums, xrefs, &sameColor); __syncthreads(); if (sameColor) { if (threadIdx.x == 0) saveSingleColorBlockDXT1(colors[0], result); return; } ushort bestStart, bestEnd; uint bestPermutation; __shared__ float errors[NUM_THREADS]; evalAllPermutations(colors, sums[0], permutations, bestStart, bestEnd, bestPermutation, errors); // Use a parallel reduction to find minimum error. const int minIdx = findMinError(errors); // Only write the result of the winner thread. if (threadIdx.x == minIdx) { saveBlockDXT1(bestStart, bestEnd, bestPermutation, xrefs, result); } } __global__ void compressLevel4DXT1(const uint * permutations, const uint * image, uint2 * result) { __shared__ float3 colors[16]; __shared__ float3 sums[16]; __shared__ int xrefs[16]; __shared__ int sameColor; loadColorBlock(image, colors, sums, xrefs, &sameColor); __syncthreads(); if (sameColor) { if (threadIdx.x == 0) saveSingleColorBlockDXT1(colors[0], result); return; } ushort bestStart, bestEnd; uint bestPermutation; __shared__ float errors[NUM_THREADS]; evalLevel4Permutations(colors, sums[0], permutations, bestStart, bestEnd, bestPermutation, errors); // Use a parallel reduction to find minimum error. const int minIdx = findMinError(errors); // Only write the result of the winner thread. if (threadIdx.x == minIdx) { saveBlockDXT1(bestStart, bestEnd, bestPermutation, xrefs, result); } } __global__ void compressWeightedDXT1(const uint * permutations, const uint * image, uint2 * result) { __shared__ float3 colors[16]; __shared__ float3 sums[16]; __shared__ float weights[16]; __shared__ int xrefs[16]; __shared__ int sameColor; loadColorBlock(image, colors, sums, weights, xrefs, &sameColor); __syncthreads(); if (sameColor) { if (threadIdx.x == 0) saveSingleColorBlockDXT1(colors[0], result); return; } ushort bestStart, bestEnd; uint bestPermutation; __shared__ float errors[NUM_THREADS]; evalLevel4Permutations(colors, weights, sums[0], permutations, bestStart, bestEnd, bestPermutation, errors); // Use a parallel reduction to find minimum error. int minIdx = findMinError(errors); // Only write the result of the winner thread. if (threadIdx.x == minIdx) { saveBlockDXT1(bestStart, bestEnd, bestPermutation, xrefs, result); } } /* __device__ float computeError(const float weights[16], uchar a0, uchar a1) { float palette[6]; palette[0] = (6.0f/7.0f * a0 + 1.0f/7.0f * a1); palette[1] = (5.0f/7.0f * a0 + 2.0f/7.0f * a1); palette[2] = (4.0f/7.0f * a0 + 3.0f/7.0f * a1); palette[3] = (3.0f/7.0f * a0 + 4.0f/7.0f * a1); palette[4] = (2.0f/7.0f * a0 + 5.0f/7.0f * a1); palette[5] = (1.0f/7.0f * a0 + 6.0f/7.0f * a1); float total = 0.0f; for (uint i = 0; i < 16; i++) { float alpha = weights[i]; float error = a0 - alpha; error = min(error, palette[0] - alpha); error = min(error, palette[1] - alpha); error = min(error, palette[2] - alpha); error = min(error, palette[3] - alpha); error = min(error, palette[4] - alpha); error = min(error, palette[5] - alpha); error = min(error, a1 - alpha); total += error; } return total; } inline __device__ uchar roundAndExpand(float a) { return rintf(__saturatef(a) * 255.0f); } */ /* __device__ void optimizeAlpha8(const float alphas[16], uchar & a0, uchar & a1) { float alpha2_sum = 0; float beta2_sum = 0; float alphabeta_sum = 0; float alphax_sum = 0; float betax_sum = 0; for (int i = 0; i < 16; i++) { uint idx = index[i]; float alpha; if (idx < 2) alpha = 1.0f - idx; else alpha = (8.0f - idx) / 7.0f; float beta = 1 - alpha; alpha2_sum += alpha * alpha; beta2_sum += beta * beta; alphabeta_sum += alpha * beta; alphax_sum += alpha * alphas[i]; betax_sum += beta * alphas[i]; } const float factor = 1.0f / (alpha2_sum * beta2_sum - alphabeta_sum * alphabeta_sum); float a = (alphax_sum * beta2_sum - betax_sum * alphabeta_sum) * factor; float b = (betax_sum * alpha2_sum - alphax_sum * alphabeta_sum) * factor; a0 = roundAndExpand8(a); a1 = roundAndExpand8(b); } */ /* __device__ void compressAlpha(const float alphas[16], uint4 * result) { const int tid = threadIdx.x; // Compress alpha block! // Brute force approach: // Try all color pairs: 256*256/2 = 32768, 32768/64 = 512 iterations? // Determine min & max alphas float A0, A1; if (tid < 16) { __shared__ uint s_alphas[16]; s_alphas[tid] = alphas[tid]; s_alphas[tid] = min(s_alphas[tid], s_alphas[tid^8]); s_alphas[tid] = min(s_alphas[tid], s_alphas[tid^4]); s_alphas[tid] = min(s_alphas[tid], s_alphas[tid^2]); s_alphas[tid] = min(s_alphas[tid], s_alphas[tid^1]); A0 = s_alphas[tid]; s_alphas[tid] = alphas[tid]; s_alphas[tid] = max(s_alphas[tid], s_alphas[tid^8]); s_alphas[tid] = max(s_alphas[tid], s_alphas[tid^4]); s_alphas[tid] = max(s_alphas[tid], s_alphas[tid^2]); s_alphas[tid] = max(s_alphas[tid], s_alphas[tid^1]); A1 = s_alphas[tid]; } __syncthreads(); int minIdx = 0; if (A1 - A0 > 8) { float bestError = FLT_MAX; // 64 threads -> 8x8 // divide [A1-A0] in partitions. // test endpoints for (int i = 0; i < 128; i++) { uint idx = (i * NUM_THREADS + tid) * 4; uchar a0 = idx & 255; uchar a1 = idx >> 8; float error = computeError(alphas, a0, a1); if (error < bestError) { bestError = error; A0 = a0; A1 = a1; } } __shared__ float errors[NUM_THREADS]; errors[tid] = bestError; // Minimize error. minIdx = findMinError(errors); } if (minIdx == tid) { // @@ Compute indices. // @@ Write alpha block. } } __global__ void compressDXT5(const uint * permutations, const uint * image, uint4 * result) { __shared__ float3 colors[16]; __shared__ float3 sums[16]; __shared__ float weights[16]; __shared__ int xrefs[16]; loadColorBlock(image, colors, sums, weights, xrefs); __syncthreads(); compressAlpha(weights, result); ushort bestStart, bestEnd; uint bestPermutation; __shared__ float errors[NUM_THREADS]; evalLevel4Permutations(colors, weights, sums[0], permutations, bestStart, bestEnd, bestPermutation, errors); // Use a parallel reduction to find minimum error. int minIdx = findMinError(errors); // Only write the result of the winner thread. if (threadIdx.x == minIdx) { saveBlockDXT1(bestStart, bestEnd, bestPermutation, xrefs, (uint2 *)result); } } */ //////////////////////////////////////////////////////////////////////////////// // Setup kernel //////////////////////////////////////////////////////////////////////////////// extern "C" void setupCompressKernel(const float weights[3]) { // Set constants. cudaMemcpyToSymbol(kColorMetric, weights, sizeof(float) * 3, 0); float weightsSqr[3]; weightsSqr[0] = weights[0] * weights[0]; weightsSqr[1] = weights[1] * weights[1]; weightsSqr[2] = weights[2] * weights[2]; cudaMemcpyToSymbol(kColorMetricSqr, weightsSqr, sizeof(float) * 3, 0); } //////////////////////////////////////////////////////////////////////////////// // Launch kernel //////////////////////////////////////////////////////////////////////////////// extern "C" void compressKernelDXT1(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps) { compressDXT1<<>>(d_bitmaps, d_data, (uint2 *)d_result); } extern "C" void compressKernelDXT1_Level4(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps) { compressLevel4DXT1<<>>(d_bitmaps, d_data, (uint2 *)d_result); } extern "C" void compressWeightedKernelDXT1(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps) { compressWeightedDXT1<<>>(d_bitmaps, d_data, (uint2 *)d_result); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/ConvolveKernel.cu000066400000000000000000000134341173441656100247040ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include "CudaMath.h" #define TW 16 #define TH 16 #define THREAD_COUNT (TW * TH) #define MAX_KERNEL_WIDTH 32 #define KW 4 #if __DEVICE_EMULATION__ #define __debugsync() __syncthreads() #else #define __debugsync() #endif #define TN 256 #define WARP_COUNT (TN / 32) #define HWARP_COUNT (TN / 16) // Window size #define WS 20 struct WrapClamp { int operator()(int i, int h) { i = min(max(i, 0), h-1); } }; struct WrapRepeat { int operator()(int i, int h) { i = abs(i) % h; // :( Non power of two! } }; struct WrapMirror { int operator()(int i, int h) { i = abs(i); while (i >= h) i = 2 * w - i - 2; } }; // Vertical convolution filter that processes vertical strips. __global__ void convolveStrip(float * d_channel, float * d_kernel, int width, int height) { __shared__ float s_kernel[32 * WS]; // Preload kernel in shared memory. for (int i = 0; i < 32 * WS / TN; i++) { int idx = i * TN + tid; if (idx < 32 * WS) s_kernel[idx] = d_kernel[idx]; } __shared__ float s_strip[32 * WS]; // TN/32 int wid = tid / 32 - WS/2; Mirror wrap; int row = wrap(wid); // Preload image block. for (int i = 0; i < 32 * WS / TN; i++) { } // @@ Apply kernel to TN/32 rows. // @@ Load } __constant__ float inputGamma, outputInverseGamma; __constant__ float kernel[MAX_KERNEL_WIDTH]; // Use texture to access input? // That's the most simple approach. texture<> image; //////////////////////////////////////////////////////////////////////////////// // Combined convolution filter //////////////////////////////////////////////////////////////////////////////// __global__ void convolve(float4 * output) { // @@ Use morton order to assing threads. int x = threadIdx.x; int y = threadIdx.y; float4 color = make_float4(0.0f, 0.0f, 0.0f, 0.0f); // texture coordinate. int2 t; t.x = 2 * (blockIdx.x * TW + x) - HW; t.y = blockIdx.y * TH + y; // @@ We might want to loop and process strips, to reuse the results of the horizontal convolutions. // Horizontal convolution. @@ Unroll loops. for (int e = HW; e > 0; e--) { t.x++; float w = kernel[e-1]; color += w * tex2D(image, tc); } for (int e = 0; e < HW; e++) { t.x++; float w = kernel[e]; color += w * tex2D(image, tc); } // Write color to shared memory. __shared__ float tile[4 * THREAD_COUNT]; int tileIdx = y * TW + x; tile[tileIdx + 0 * THREAD_COUNT] = color.x; tile[tileIdx + 1 * THREAD_COUNT] = color.y; tile[tileIdx + 2 * THREAD_COUNT] = color.z; tile[tileIdx + 3 * THREAD_COUNT] = color.w; __syncthreads(); // tile coordinate. t.x = x; t.y = y - HW; // Vertical convolution. @@ Unroll loops. for (int i = HW; i > 0; i--) { float w = kernel[i-1]; t.y++; int idx = t.y * TW + t.x; color.x += w * tile[idx + 0 * THREAD_COUNT]; color.y += w * tile[idx + 1 * THREAD_COUNT]; color.z += w * tile[idx + 2 * THREAD_COUNT]; color.w += w * tile[idx + 3 * THREAD_COUNT]; } for (int i = 0; i < HW; i++) { float w = kernel[i]; t.y++; int idx = t.y * TW + t.x; color.x += w * tile[idx + 0 * THREAD_COUNT]; color.y += w * tile[idx + 1 * THREAD_COUNT]; color.z += w * tile[idx + 2 * THREAD_COUNT]; color.w += w * tile[idx + 3 * THREAD_COUNT]; } it (x < w && y < h) { // @@ Prevent unaligned writes. output[y * w + h] = color; } } //////////////////////////////////////////////////////////////////////////////// // Monophase X convolution filter //////////////////////////////////////////////////////////////////////////////// __device__ void convolveY() { } //////////////////////////////////////////////////////////////////////////////// // Mipmap convolution filter //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Gamma correction //////////////////////////////////////////////////////////////////////////////// /* __device__ float toLinear(float f, float gamma = 2.2f) { return __pow(f, gamma); } __device__ float toGamma(float f, float gamma = 2.2f) { return pow(f, 1.0f / gamma); } */ //////////////////////////////////////////////////////////////////////////////// // Setup kernel //////////////////////////////////////////////////////////////////////////////// extern "C" void setupConvolveKernel(const float * k, int w) { w = min(w, MAX_KERNEL_WIDTH); cudaMemcpyToSymbol(kernel, k, sizeof(float) * w, 0); } //////////////////////////////////////////////////////////////////////////////// // Launch kernel //////////////////////////////////////////////////////////////////////////////// nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/CudaCompressDXT.cpp000066400000000000000000000241161173441656100250720ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include #include #include #include #include #include "CudaCompressDXT.h" #include "CudaUtils.h" #if defined HAVE_CUDA #include #endif #include #include using namespace nv; using namespace nvtt; #if defined HAVE_CUDA #define MAX_BLOCKS 8192U // 32768, 65535 extern "C" void setupCompressKernel(const float weights[3]); extern "C" void compressKernelDXT1(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps); extern "C" void compressKernelDXT1_Level4(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps); extern "C" void compressWeightedKernelDXT1(uint blockNum, uint * d_data, uint * d_result, uint * d_bitmaps); #include "Bitmaps.h" // @@ Rename to BitmapTable.h // Convert linear image to block linear. static void convertToBlockLinear(const Image * image, uint * blockLinearImage) { const uint w = (image->width() + 3) / 4; const uint h = (image->height() + 3) / 4; for(uint by = 0; by < h; by++) { for(uint bx = 0; bx < w; bx++) { const uint bw = min(image->width() - bx * 4, 4U); const uint bh = min(image->height() - by * 4, 4U); for (uint i = 0; i < 16; i++) { const int x = (i % 4) % bw; const int y = (i / 4) % bh; blockLinearImage[(by * w + bx) * 16 + i] = image->pixel(bx * 4 + x, by * 4 + y).u; } } } } #endif CudaCompressor::CudaCompressor() : m_bitmapTable(NULL), m_data(NULL), m_result(NULL) { #if defined HAVE_CUDA // Allocate and upload bitmaps. cudaMalloc((void**) &m_bitmapTable, 992 * sizeof(uint)); if (m_bitmapTable != NULL) { cudaMemcpy(m_bitmapTable, s_bitmapTable, 992 * sizeof(uint), cudaMemcpyHostToDevice); } // Allocate scratch buffers. cudaMalloc((void**) &m_data, MAX_BLOCKS * 64U); cudaMalloc((void**) &m_result, MAX_BLOCKS * 8U); #endif } CudaCompressor::~CudaCompressor() { #if defined HAVE_CUDA // Free device mem allocations. cudaFree(m_data); cudaFree(m_result); cudaFree(m_bitmapTable); #endif } bool CudaCompressor::isValid() const { #if defined HAVE_CUDA if (cudaGetLastError() != cudaSuccess) { return false; } #endif return m_data != NULL && m_result != NULL && m_bitmapTable != NULL; } // @@ This code is very repetitive and needs to be cleaned up. void CudaCompressor::setImage(const Image * image, nvtt::AlphaMode alphaMode) { m_image = image; m_alphaMode = alphaMode; } /// Compress image using CUDA. void CudaCompressor::compressDXT1(const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) { nvDebugCheck(cuda::isHardwarePresent()); #if defined HAVE_CUDA // Image size in blocks. const uint w = (m_image->width() + 3) / 4; const uint h = (m_image->height() + 3) / 4; uint imageSize = w * h * 16 * sizeof(Color32); uint * blockLinearImage = (uint *) malloc(imageSize); convertToBlockLinear(m_image, blockLinearImage); // @@ Do this in parallel with the GPU, or in the GPU! const uint blockNum = w * h; const uint compressedSize = blockNum * 8; clock_t start = clock(); setupCompressKernel(compressionOptions.colorWeight.ptr()); // TODO: Add support for multiple GPUs. uint bn = 0; while(bn != blockNum) { uint count = min(blockNum - bn, MAX_BLOCKS); cudaMemcpy(m_data, blockLinearImage + bn * 16, count * 64, cudaMemcpyHostToDevice); // Launch kernel. compressKernelDXT1(count, m_data, m_result, m_bitmapTable); // Check for errors. cudaError_t err = cudaGetLastError(); if (err != cudaSuccess) { nvDebug("CUDA Error: %s\n", cudaGetErrorString(err)); if (outputOptions.errorHandler != NULL) { outputOptions.errorHandler->error(Error_CudaError); } } // Copy result to host, overwrite swizzled image. cudaMemcpy(blockLinearImage, m_result, count * 8, cudaMemcpyDeviceToHost); // Output result. if (outputOptions.outputHandler != NULL) { outputOptions.outputHandler->writeData(blockLinearImage, count * 8); } bn += count; } clock_t end = clock(); //printf("\rCUDA time taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC); free(blockLinearImage); #else if (outputOptions.errorHandler != NULL) { outputOptions.errorHandler->error(Error_CudaError); } #endif } /// Compress image using CUDA. void CudaCompressor::compressDXT3(const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) { nvDebugCheck(cuda::isHardwarePresent()); #if defined HAVE_CUDA // Image size in blocks. const uint w = (m_image->width() + 3) / 4; const uint h = (m_image->height() + 3) / 4; uint imageSize = w * h * 16 * sizeof(Color32); uint * blockLinearImage = (uint *) malloc(imageSize); convertToBlockLinear(m_image, blockLinearImage); const uint blockNum = w * h; const uint compressedSize = blockNum * 8; AlphaBlockDXT3 * alphaBlocks = NULL; alphaBlocks = (AlphaBlockDXT3 *)malloc(min(compressedSize, MAX_BLOCKS * 8U)); setupCompressKernel(compressionOptions.colorWeight.ptr()); clock_t start = clock(); uint bn = 0; while(bn != blockNum) { uint count = min(blockNum - bn, MAX_BLOCKS); cudaMemcpy(m_data, blockLinearImage + bn * 16, count * 64, cudaMemcpyHostToDevice); // Launch kernel. if (m_alphaMode == AlphaMode_Transparency) { compressWeightedKernelDXT1(count, m_data, m_result, m_bitmapTable); } else { compressKernelDXT1_Level4(count, m_data, m_result, m_bitmapTable); } // Compress alpha in parallel with the GPU. for (uint i = 0; i < count; i++) { ColorBlock rgba(blockLinearImage + (bn + i) * 16); OptimalCompress::compressDXT3A(rgba, alphaBlocks + i); } // Check for errors. cudaError_t err = cudaGetLastError(); if (err != cudaSuccess) { nvDebug("CUDA Error: %s\n", cudaGetErrorString(err)); if (outputOptions.errorHandler != NULL) { outputOptions.errorHandler->error(Error_CudaError); } } // Copy result to host, overwrite swizzled image. cudaMemcpy(blockLinearImage, m_result, count * 8, cudaMemcpyDeviceToHost); // Output result. if (outputOptions.outputHandler != NULL) { for (uint i = 0; i < count; i++) { outputOptions.outputHandler->writeData(alphaBlocks + i, 8); outputOptions.outputHandler->writeData(blockLinearImage + i * 2, 8); } } bn += count; } clock_t end = clock(); //printf("\rCUDA time taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC); free(alphaBlocks); free(blockLinearImage); #else if (outputOptions.errorHandler != NULL) { outputOptions.errorHandler->error(Error_CudaError); } #endif } /// Compress image using CUDA. void CudaCompressor::compressDXT5(const CompressionOptions::Private & compressionOptions, const OutputOptions::Private & outputOptions) { nvDebugCheck(cuda::isHardwarePresent()); #if defined HAVE_CUDA // Image size in blocks. const uint w = (m_image->width() + 3) / 4; const uint h = (m_image->height() + 3) / 4; uint imageSize = w * h * 16 * sizeof(Color32); uint * blockLinearImage = (uint *) malloc(imageSize); convertToBlockLinear(m_image, blockLinearImage); const uint blockNum = w * h; const uint compressedSize = blockNum * 8; AlphaBlockDXT5 * alphaBlocks = NULL; alphaBlocks = (AlphaBlockDXT5 *)malloc(min(compressedSize, MAX_BLOCKS * 8U)); setupCompressKernel(compressionOptions.colorWeight.ptr()); clock_t start = clock(); uint bn = 0; while(bn != blockNum) { uint count = min(blockNum - bn, MAX_BLOCKS); cudaMemcpy(m_data, blockLinearImage + bn * 16, count * 64, cudaMemcpyHostToDevice); // Launch kernel. if (m_alphaMode == AlphaMode_Transparency) { compressWeightedKernelDXT1(count, m_data, m_result, m_bitmapTable); } else { compressKernelDXT1_Level4(count, m_data, m_result, m_bitmapTable); } // Compress alpha in parallel with the GPU. for (uint i = 0; i < count; i++) { ColorBlock rgba(blockLinearImage + (bn + i) * 16); QuickCompress::compressDXT5A(rgba, alphaBlocks + i); } // Check for errors. cudaError_t err = cudaGetLastError(); if (err != cudaSuccess) { nvDebug("CUDA Error: %s\n", cudaGetErrorString(err)); if (outputOptions.errorHandler != NULL) { outputOptions.errorHandler->error(Error_CudaError); } } // Copy result to host, overwrite swizzled image. cudaMemcpy(blockLinearImage, m_result, count * 8, cudaMemcpyDeviceToHost); // Output result. if (outputOptions.outputHandler != NULL) { for (uint i = 0; i < count; i++) { outputOptions.outputHandler->writeData(alphaBlocks + i, 8); outputOptions.outputHandler->writeData(blockLinearImage + i * 2, 8); } } bn += count; } clock_t end = clock(); //printf("\rCUDA time taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC); free(alphaBlocks); free(blockLinearImage); #else if (outputOptions.errorHandler != NULL) { outputOptions.errorHandler->error(Error_CudaError); } #endif } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/CudaCompressDXT.h000066400000000000000000000040261173441656100245350ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_CUDACOMPRESSDXT_H #define NV_TT_CUDACOMPRESSDXT_H #include #include namespace nv { class Image; class CudaCompressor { public: CudaCompressor(); ~CudaCompressor(); bool isValid() const; void setImage(const Image * image, nvtt::AlphaMode alphaMode); void compressDXT1(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); void compressDXT3(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); void compressDXT5(const nvtt::CompressionOptions::Private & compressionOptions, const nvtt::OutputOptions::Private & outputOptions); private: uint * m_bitmapTable; uint * m_data; uint * m_result; const Image * m_image; nvtt::AlphaMode m_alphaMode; }; } // nv namespace #endif // NV_TT_CUDAUTILS_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/CudaMath.h000066400000000000000000000160001173441656100232460ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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. // Math functions and operators to be used with vector types. #ifndef CUDAMATH_H #define CUDAMATH_H #include inline __device__ __host__ float3 operator *(float3 a, float3 b) { return make_float3(a.x*b.x, a.y*b.y, a.z*b.z); } inline __device__ __host__ float3 operator *(float f, float3 v) { return make_float3(v.x*f, v.y*f, v.z*f); } inline __device__ __host__ float3 operator *(float3 v, float f) { return make_float3(v.x*f, v.y*f, v.z*f); } inline __device__ __host__ float3 operator +(float3 a, float3 b) { return make_float3(a.x+b.x, a.y+b.y, a.z+b.z); } inline __device__ __host__ void operator +=(float3 & b, float3 a) { b.x += a.x; b.y += a.y; b.z += a.z; } inline __device__ __host__ float3 operator -(float3 a, float3 b) { return make_float3(a.x-b.x, a.y-b.y, a.z-b.z); } inline __device__ __host__ void operator -=(float3 & b, float3 a) { b.x -= a.x; b.y -= a.y; b.z -= a.z; } inline __device__ __host__ float3 operator /(float3 v, float f) { float inv = 1.0f / f; return v * inv; } inline __device__ __host__ void operator /=(float3 & b, float f) { float inv = 1.0f / f; b.x *= inv; b.y *= inv; b.z *= inv; } inline __device__ __host__ bool operator ==(float3 a, float3 b) { return a.x == b.x && a.y == b.y && a.z == b.z; } inline __device__ __host__ float dot(float3 a, float3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } inline __device__ __host__ float dot(float4 a, float4 b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } inline __device__ __host__ float clamp(float f, float a, float b) { return max(a, min(f, b)); } inline __device__ __host__ float3 clamp(float3 v, float a, float b) { return make_float3(clamp(v.x, a, b), clamp(v.y, a, b), clamp(v.z, a, b)); } inline __device__ __host__ float3 clamp(float3 v, float3 a, float3 b) { return make_float3(clamp(v.x, a.x, b.x), clamp(v.y, a.y, b.y), clamp(v.z, a.z, b.z)); } inline __device__ __host__ float3 normalize(float3 v) { float len = 1.0f / sqrtf(dot(v, v)); return make_float3(v.x * len, v.y * len, v.z * len); } // Use power method to find the first eigenvector. // http://www.miislita.com/information-retrieval-tutorial/matrix-tutorial-3-eigenvalues-eigenvectors.html inline __device__ __host__ float3 firstEigenVector( float matrix[6] ) { // 8 iterations seems to be more than enough. float3 row0 = make_float3(matrix[0], matrix[1], matrix[2]); float3 row1 = make_float3(matrix[1], matrix[3], matrix[4]); float3 row2 = make_float3(matrix[2], matrix[4], matrix[5]); float r0 = dot(row0, row0); float r1 = dot(row1, row1); float r2 = dot(row2, row2); float3 v; if (r0 > r1 && r0 > r2) v = row0; else if (r1 > r2) v = row1; else v = row2; //float3 v = make_float3(1.0f, 1.0f, 1.0f); for(int i = 0; i < 8; 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 m = max(max(x, y), z); float iv = 1.0f / m; if (m == 0.0f) iv = 0.0f; v = make_float3(x*iv, y*iv, z*iv); } return v; } inline __device__ bool singleColor(const float3 * colors) { #if __DEVICE_EMULATION__ bool sameColor = false; for (int i = 0; i < 16; i++) { sameColor &= (colors[i] == colors[0]); } return sameColor; #else __shared__ int sameColor[16]; const int idx = threadIdx.x; sameColor[idx] = (colors[idx] == colors[0]); sameColor[idx] &= sameColor[idx^8]; sameColor[idx] &= sameColor[idx^4]; sameColor[idx] &= sameColor[idx^2]; sameColor[idx] &= sameColor[idx^1]; return sameColor[0]; #endif } inline __device__ void colorSums(const float3 * colors, float3 * sums) { #if __DEVICE_EMULATION__ float3 color_sum = make_float3(0.0f, 0.0f, 0.0f); for (int i = 0; i < 16; i++) { color_sum += colors[i]; } for (int i = 0; i < 16; i++) { sums[i] = color_sum; } #else const int idx = threadIdx.x; sums[idx] = colors[idx]; sums[idx] += sums[idx^8]; sums[idx] += sums[idx^4]; sums[idx] += sums[idx^2]; sums[idx] += sums[idx^1]; #endif } inline __device__ float3 bestFitLine(const float3 * colors, float3 color_sum, float3 colorMetric) { // Compute covariance matrix of the given colors. #if __DEVICE_EMULATION__ float covariance[6] = {0, 0, 0, 0, 0, 0}; for (int i = 0; i < 16; i++) { float3 a = (colors[i] - color_sum * (1.0f / 16.0f)) * colorMetric; covariance[0] += a.x * a.x; covariance[1] += a.x * a.y; covariance[2] += a.x * a.z; covariance[3] += a.y * a.y; covariance[4] += a.y * a.z; covariance[5] += a.z * a.z; } #else const int idx = threadIdx.x; float3 diff = (colors[idx] - color_sum * (1.0f / 16.0f)) * colorMetric; // @@ Eliminate two-way bank conflicts here. // @@ It seems that doing that and unrolling the reduction doesn't help... __shared__ float covariance[16*6]; covariance[6 * idx + 0] = diff.x * diff.x; // 0, 6, 12, 2, 8, 14, 4, 10, 0 covariance[6 * idx + 1] = diff.x * diff.y; covariance[6 * idx + 2] = diff.x * diff.z; covariance[6 * idx + 3] = diff.y * diff.y; covariance[6 * idx + 4] = diff.y * diff.z; covariance[6 * idx + 5] = diff.z * diff.z; for(int d = 8; d > 0; d >>= 1) { if (idx < d) { covariance[6 * idx + 0] += covariance[6 * (idx+d) + 0]; covariance[6 * idx + 1] += covariance[6 * (idx+d) + 1]; covariance[6 * idx + 2] += covariance[6 * (idx+d) + 2]; covariance[6 * idx + 3] += covariance[6 * (idx+d) + 3]; covariance[6 * idx + 4] += covariance[6 * (idx+d) + 4]; covariance[6 * idx + 5] += covariance[6 * (idx+d) + 5]; } } #endif // Compute first eigen vector. return firstEigenVector(covariance); } #endif // CUDAMATH_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/CudaUtils.cpp000066400000000000000000000153471173441656100240250ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include "CudaUtils.h" #if defined HAVE_CUDA #include #include #endif using namespace nv; using namespace cuda; /* @@ Move this to win32 utils or somewhere else. #if NV_OS_WIN32 #define WINDOWS_LEAN_AND_MEAN #include static bool isWindowsVista() { OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); ::GetVersionEx(&osvi); return osvi.dwMajorVersion >= 6; } typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); static bool isWow32() { LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process"); BOOL bIsWow64 = FALSE; if (NULL != fnIsWow64Process) { if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) { // Assume 32 bits. return true; } } return !bIsWow64; } #endif */ static bool isCudaDriverAvailable(int version) { #if defined HAVE_CUDA #if NV_OS_WIN32 Library nvcuda("nvcuda.dll"); #else Library nvcuda(NV_LIBRARY_NAME(cuda)); #endif if (!nvcuda.isValid()) { nvDebug("*** CUDA driver not found.\n"); return false; } if (version >= 2000) { void * address = nvcuda.bindSymbol("cuStreamCreate"); if (address == NULL) { nvDebug("*** CUDA driver version < 2.0.\n"); return false; } } if (version >= 2010) { void * address = nvcuda.bindSymbol("cuModuleLoadDataEx"); if (address == NULL) { nvDebug("*** CUDA driver version < 2.1.\n"); return false; } } if (version >= 2020) { typedef CUresult (CUDAAPI * PFCU_DRIVERGETVERSION)(int * version); PFCU_DRIVERGETVERSION driverGetVersion = (PFCU_DRIVERGETVERSION)nvcuda.bindSymbol("cuDriverGetVersion"); if (driverGetVersion == NULL) { nvDebug("*** CUDA driver version < 2.2.\n"); return false; } int driverVersion; CUresult err = driverGetVersion(&driverVersion); if (err != CUDA_SUCCESS) { nvDebug("*** Error querying driver version: '%s'.\n", cudaGetErrorString((cudaError_t)err)); return false; } return driverVersion >= version; } #endif // HAVE_CUDA return true; } /// Determine if CUDA is available. bool nv::cuda::isHardwarePresent() { #if defined HAVE_CUDA // Make sure that CUDA driver matches CUDA runtime. if (!isCudaDriverAvailable(CUDART_VERSION)) { nvDebug("CUDA driver not available for CUDA runtime %d\n", CUDART_VERSION); return false; } int count = deviceCount(); if (count == 1) { // Make sure it's not an emulation device. cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, 0); // deviceProp.name != Device Emulation (CPU) if (deviceProp.major == -1 || deviceProp.minor == -1) { return false; } } // @@ Make sure that warp size == 32 // @@ Make sure available GPU is faster than the CPU. return count > 0; #else return false; #endif } /// Get number of CUDA enabled devices. int nv::cuda::deviceCount() { #if defined HAVE_CUDA int gpuCount = 0; cudaError_t result = cudaGetDeviceCount(&gpuCount); if (result == cudaSuccess) { return gpuCount; } #endif return 0; } // Make sure device meets requirements: // - Not an emulation device. // - Not an integrated device? // - Faster than CPU. bool nv::cuda::isValidDevice(int i) { #if defined HAVE_CUDA cudaDeviceProp device_properties; cudaGetDeviceProperties(&device_properties, i); int gflops = device_properties.multiProcessorCount * device_properties.clockRate; if (device_properties.major == -1 || device_properties.minor == -1) { // Emulation device. return false; } #if CUDART_VERSION >= 2030 // 2.3 /*if (device_properties.integrated) { // Integrated devices. return false; }*/ #endif return true; #else return false; #endif } int nv::cuda::getFastestDevice() { int max_gflops_device = -1; #if defined HAVE_CUDA int max_gflops = 0; const int device_count = deviceCount(); for (int i = 0; i < device_count; i++) { if (isValidDevice(i)) { cudaDeviceProp device_properties; cudaGetDeviceProperties(&device_properties, i); int gflops = device_properties.multiProcessorCount * device_properties.clockRate; if (gflops > max_gflops) { max_gflops = gflops; max_gflops_device = i; } } } #endif return max_gflops_device; } /// Activate the given devices. bool nv::cuda::initDevice(int * device_ptr) { nvDebugCheck(device_ptr != NULL); #if defined HAVE_CUDA #if CUDART_VERSION >= 2030 // 2.3 // Set device flags to yield in order to play nice with other threads and to find out if CUDA was already active. cudaError_t resul = cudaSetDeviceFlags(cudaDeviceScheduleYield); #endif int device = getFastestDevice(); if (device == -1) { // No device is fast enough. *device_ptr = -1; return false; } // Select CUDA device. cudaError_t result = cudaSetDevice(device); if (result == cudaErrorSetOnActiveProcess) { int device; result = cudaGetDevice(&device); *device_ptr = -1; // No device to cleanup. return isValidDevice(device); // Return true if device is valid. } else if (result != cudaSuccess) { nvDebug("*** CUDA Error: %s\n", cudaGetErrorString(result)); *device_ptr = -1; return false; } *device_ptr = device; return true; #else return false; #endif } void nv::cuda::exitDevice() { #if defined HAVE_CUDA cudaError_t result = cudaThreadExit(); if (result != cudaSuccess) { nvDebug("*** CUDA Error: %s\n", cudaGetErrorString(result)); } #endif } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/cuda/CudaUtils.h000066400000000000000000000027001173441656100234570ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_CUDAUTILS_H #define NV_TT_CUDAUTILS_H namespace nv { namespace cuda { bool isHardwarePresent(); int deviceCount(); int getFastestDevice(); bool isValidDevice(int i); bool initDevice(int * device_ptr); void exitDevice(); }; } // nv namespace #endif // NV_TT_CUDAUTILS_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/nvtt.cpp000066400000000000000000000034341173441656100222010ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 "nvtt.h" using namespace nvtt; /// Return a string for the given error. const char * nvtt::errorString(Error e) { switch(e) { case Error_Unknown: return "Unknown error"; case Error_InvalidInput: return "Invalid input"; case Error_UnsupportedFeature: return "Unsupported feature"; case Error_CudaError: return "CUDA error"; case Error_FileOpen: return "Error opening file"; case Error_FileWrite: return "Error writing through output handler"; } return "Invalid error"; } /// Return NVTT version. unsigned int nvtt::version() { return NVTT_VERSION; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/nvtt.h000066400000000000000000000206331173441656100216460ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NV_TT_H #define NV_TT_H // Function linkage #if NVTT_SHARED #if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__ || defined __MINGW32__ # ifdef NVTT_EXPORTS # define NVTT_API __declspec(dllexport) # else # define NVTT_API __declspec(dllimport) # endif #endif #if defined __GNUC__ >= 4 # ifdef NVTT_EXPORTS # define NVTT_API __attribute__((visibility("default"))) # endif #endif #endif // NVTT_SHARED #if !defined NVTT_API # define NVTT_API #endif #define NVTT_VERSION 200 #define NVTT_DECLARE_PIMPL(Class) \ private: \ Class(const Class &); \ void operator=(const Class &); \ public: \ struct Private; \ Private & m // Public interface. namespace nvtt { /// Supported compression formats. enum Format { // No compression. Format_RGB, Format_RGBA = Format_RGB, // DX9 formats. Format_DXT1, Format_DXT1a, // DXT1 with binary alpha. Format_DXT3, Format_DXT5, Format_DXT5n, // Compressed HILO: R=1, G=y, B=0, A=x // DX10 formats. Format_BC1 = Format_DXT1, Format_BC1a = Format_DXT1a, Format_BC2 = Format_DXT3, Format_BC3 = Format_DXT5, Format_BC3n = Format_DXT5n, Format_BC4, // ATI1 Format_BC5, // 3DC, ATI2 }; /// Quality modes. enum Quality { Quality_Fastest, Quality_Normal, Quality_Production, Quality_Highest, }; /// Compression options. This class describes the desired compression format and other compression settings. struct CompressionOptions { NVTT_DECLARE_PIMPL(CompressionOptions); NVTT_API CompressionOptions(); NVTT_API ~CompressionOptions(); NVTT_API void reset(); NVTT_API void setFormat(Format format); NVTT_API void setQuality(Quality quality); NVTT_API void setColorWeights(float red, float green, float blue, float alpha = 1.0f); NVTT_API void setExternalCompressor(const char * name); // Set color mask to describe the RGB/RGBA format. NVTT_API void setPixelFormat(unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask); NVTT_API void setQuantization(bool colorDithering, bool alphaDithering, bool binaryAlpha, int alphaThreshold = 127); }; /// Wrap modes. enum WrapMode { WrapMode_Clamp, WrapMode_Repeat, WrapMode_Mirror, }; /// Texture types. enum TextureType { TextureType_2D, TextureType_Cube, // TextureType_3D, }; /// Input formats. enum InputFormat { InputFormat_BGRA_8UB, // InputFormat_RGBE_8UB, // InputFormat_BGRA_32F, }; /// Mipmap downsampling filters. enum MipmapFilter { MipmapFilter_Box, ///< Box filter is quite good and very fast. MipmapFilter_Triangle, ///< Triangle filter blurs the results too much, but that might be what you want. MipmapFilter_Kaiser, ///< Kaiser-windowed Sinc filter is the best downsampling filter. }; /// Color transformation. enum ColorTransform { ColorTransform_None, ColorTransform_Linear, }; /// Extents rounding mode. enum RoundMode { RoundMode_None, RoundMode_ToNextPowerOfTwo, RoundMode_ToNearestPowerOfTwo, RoundMode_ToPreviousPowerOfTwo, }; /// Alpha mode. enum AlphaMode { AlphaMode_None, AlphaMode_Transparency, AlphaMode_Premultiplied, }; /// Input options. Specify format and layout of the input texture. struct InputOptions { NVTT_DECLARE_PIMPL(InputOptions); NVTT_API InputOptions(); NVTT_API ~InputOptions(); // Set default options. NVTT_API void reset(); // Setup input layout. NVTT_API void setTextureLayout(TextureType type, int w, int h, int d = 1); NVTT_API void resetTextureLayout(); // Set mipmap data. Copies the data. NVTT_API bool setMipmapData(const void * data, int w, int h, int d = 1, int face = 0, int mipmap = 0); // Describe the format of the input. NVTT_API void setFormat(InputFormat format); // Set the way the input alpha channel is interpreted. NVTT_API void setAlphaMode(AlphaMode alphaMode); // Set gamma settings. NVTT_API void setGamma(float inputGamma, float outputGamma); // Set texture wrappign mode. NVTT_API void setWrapMode(WrapMode mode); // Set mipmapping options. NVTT_API void setMipmapFilter(MipmapFilter filter); NVTT_API void setMipmapGeneration(bool enabled, int maxLevel = -1); NVTT_API void setKaiserParameters(float width, float alpha, float stretch); // Set normal map options. NVTT_API void setNormalMap(bool b); NVTT_API void setConvertToNormalMap(bool convert); NVTT_API void setHeightEvaluation(float redScale, float greenScale, float blueScale, float alphaScale); NVTT_API void setNormalFilter(float sm, float medium, float big, float large); NVTT_API void setNormalizeMipmaps(bool b); // Set color transforms. @@ Not implemented! NVTT_API void setColorTransform(ColorTransform t); NVTT_API void setLinearTransform(int channel, float w0, float w1, float w2, float w3); // Set resizing options. NVTT_API void setMaxExtents(int d); NVTT_API void setRoundMode(RoundMode mode); }; /// Output handler. struct OutputHandler { virtual ~OutputHandler() {} /// Indicate the start of a new compressed image that's part of the final texture. virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) = 0; /// Output data. Compressed data is output as soon as it's generated to minimize memory allocations. virtual bool writeData(const void * data, int size) = 0; }; /// Error codes. enum Error { Error_Unknown, Error_InvalidInput, Error_UnsupportedFeature, Error_CudaError, Error_FileOpen, Error_FileWrite, }; /// Error handler. struct ErrorHandler { virtual ~ErrorHandler() {} // Signal error. virtual void error(Error e) = 0; }; /// Output Options. This class holds pointers to the interfaces that are used to report the output of /// the compressor to the user. struct OutputOptions { NVTT_DECLARE_PIMPL(OutputOptions); NVTT_API OutputOptions(); NVTT_API ~OutputOptions(); // Set default options. NVTT_API void reset(); NVTT_API void setFileName(const char * fileName); NVTT_API void setOutputHandler(OutputHandler * outputHandler); NVTT_API void setErrorHandler(ErrorHandler * errorHandler); NVTT_API void setOutputHeader(bool outputHeader); }; /// Texture compressor. struct Compressor { NVTT_DECLARE_PIMPL(Compressor); NVTT_API Compressor(); NVTT_API ~Compressor(); NVTT_API void enableCudaAcceleration(bool enable); NVTT_API bool isCudaAccelerationEnabled() const; // Main entrypoint of the compression library. NVTT_API bool process(const InputOptions & inputOptions, const CompressionOptions & compressionOptions, const OutputOptions & outputOptions) const; // Estimate the size of compressing the input with the given options. NVTT_API int estimateSize(const InputOptions & inputOptions, const CompressionOptions & compressionOptions) const; }; // Return string for the given error code. NVTT_API const char * errorString(Error e); // Return NVTT version. NVTT_API unsigned int version(); } // nvtt namespace #endif // NV_TT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/nvtt_wrapper.cpp000066400000000000000000000147251173441656100237460ustar00rootroot00000000000000 #include "nvtt.h" #include "nvtt_wrapper.h" // InputOptions class. NvttInputOptions * nvttCreateInputOptions() { return new nvtt::InputOptions(); } void nvttDestroyInputOptions(NvttInputOptions * inputOptions) { delete inputOptions; } void nvttSetInputOptionsTextureLayout(NvttInputOptions * inputOptions, NvttTextureType type, int w, int h, int d) { inputOptions->setTextureLayout((nvtt::TextureType)type, w, h, d); } void nvttResetInputOptionsTextureLayout(NvttInputOptions * inputOptions) { inputOptions->resetTextureLayout(); } NvttBoolean nvttSetInputOptionsMipmapData(NvttInputOptions * inputOptions, const void * data, int w, int h, int d, int face, int mipmap) { return (NvttBoolean)inputOptions->setMipmapData(data, w, h, d, face, mipmap); } void nvttSetInputOptionsFormat(NvttInputOptions * inputOptions, NvttInputFormat format) { inputOptions->setFormat((nvtt::InputFormat)format); } void nvttSetInputOptionsAlphaMode(NvttInputOptions * inputOptions, NvttAlphaMode alphaMode) { inputOptions->setAlphaMode((nvtt::AlphaMode)alphaMode); } void nvttSetInputOptionsGamma(NvttInputOptions * inputOptions, float inputGamma, float outputGamma) { inputOptions->setGamma(inputGamma, outputGamma); } void nvttSetInputOptionsWrapMode(NvttInputOptions * inputOptions, NvttWrapMode mode) { inputOptions->setWrapMode((nvtt::WrapMode)mode); } void nvttSetInputOptionsMipmapFilter(NvttInputOptions * inputOptions, NvttMipmapFilter filter) { inputOptions->setMipmapFilter((nvtt::MipmapFilter)filter); } void nvttSetInputOptionsMipmapGeneration(NvttInputOptions * inputOptions, NvttBoolean enabled, int maxLevel) { inputOptions->setMipmapGeneration(enabled != NVTT_False, maxLevel); } void nvttSetInputOptionsKaiserParameters(NvttInputOptions * inputOptions, float width, float alpha, float stretch) { inputOptions->setKaiserParameters(width, alpha, stretch); } void nvttSetInputOptionsNormalMap(NvttInputOptions * inputOptions, NvttBoolean b) { inputOptions->setNormalMap(b != NVTT_False); } void nvttSetInputOptionsConvertToNormalMap(NvttInputOptions * inputOptions, NvttBoolean convert) { inputOptions->setConvertToNormalMap(convert != NVTT_False); } void nvttSetInputOptionsHeightEvaluation(NvttInputOptions * inputOptions, float redScale, float greenScale, float blueScale, float alphaScale) { inputOptions->setHeightEvaluation(redScale, greenScale, blueScale, alphaScale); } void nvttSetInputOptionsNormalFilter(NvttInputOptions * inputOptions, float small, float medium, float big, float large) { inputOptions->setNormalFilter(small, medium, big, large); } void nvttSetInputOptionsNormalizeMipmaps(NvttInputOptions * inputOptions, NvttBoolean b) { inputOptions->setNormalizeMipmaps(b != NVTT_False); } void nvttSetInputOptionsColorTransform(NvttInputOptions * inputOptions, NvttColorTransform t) { inputOptions->setColorTransform((nvtt::ColorTransform)t); } void nvttSetInputOptionsLinearTransfrom(NvttInputOptions * inputOptions, int channel, float w0, float w1, float w2, float w3) { inputOptions->setLinearTransform(channel, w0, w1, w2, w3); } void nvttSetInputOptionsMaxExtents(NvttInputOptions * inputOptions, int dim) { inputOptions->setMaxExtents(dim); } void nvttSetInputOptionsRoundMode(NvttInputOptions * inputOptions, NvttRoundMode mode) { inputOptions->setRoundMode((nvtt::RoundMode)mode); } // CompressionOptions class. NvttCompressionOptions * nvttCreateCompressionOptions() { return new nvtt::CompressionOptions(); } void nvttDestroyCompressionOptions(NvttCompressionOptions * compressionOptions) { delete compressionOptions; } void nvttSetCompressionOptionsFormat(NvttCompressionOptions * compressionOptions, NvttFormat format) { compressionOptions->setFormat((nvtt::Format)format); } void nvttSetCompressionOptionsQuality(NvttCompressionOptions * compressionOptions, NvttQuality quality) { compressionOptions->setQuality((nvtt::Quality)quality); } void nvttSetCompressionOptionsColorWeights(NvttCompressionOptions * compressionOptions, float red, float green, float blue, float alpha) { compressionOptions->setColorWeights(red, green, blue, alpha); } /*void nvttEnableCompressionOptionsCudaCompression(NvttCompressionOptions * compressionOptions, NvttBoolean enable) { compressionOptions->enableCudaCompression(enable != NVTT_False); }*/ void nvttSetCompressionOptionsPixelFormat(NvttCompressionOptions * compressionOptions, unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask) { compressionOptions->setPixelFormat(bitcount, rmask, gmask, bmask, amask); } void nvttSetCompressionOptionsQuantization(NvttCompressionOptions * compressionOptions, NvttBoolean colorDithering, NvttBoolean alphaDithering, NvttBoolean binaryAlpha, int alphaThreshold) { compressionOptions->setQuantization(colorDithering != NVTT_False, alphaDithering != NVTT_False, binaryAlpha != NVTT_False, alphaThreshold); } // OutputOptions class. NvttOutputOptions * nvttCreateOutputOptions() { return new nvtt::OutputOptions(); } void nvttDestroyOutputOptions(NvttOutputOptions * outputOptions) { delete outputOptions; } void nvttSetOutputOptionsFileName(NvttOutputOptions * outputOptions, const char * fileName) { outputOptions->setFileName(fileName); } void nvttSetOutputOptionsOutputHeader(NvttOutputOptions * outputOptions, NvttBoolean b) { outputOptions->setOutputHeader(b != NVTT_False); } /* void nvttSetOutputOptionsErrorHandler(NvttOutputOptions * outputOptions, nvttErrorHandler errorHandler) { outputOptions->setErrorHandler(errorHandler); } void nvttSetOutputOptionsOutputHandler(NvttOutputOptions * outputOptions, nvttOutputHandler outputHandler, nvttImageHandler imageHandler) { } */ // Compressor class. NvttBoolean nvttCompress(const NvttCompressor * compressor, const NvttInputOptions * inputOptions, const NvttCompressionOptions * compressionOptions, const NvttOutputOptions * outputOptions) { return (NvttBoolean)compressor->process(*inputOptions, *compressionOptions, *outputOptions); } int nvttEstimateSize(const NvttCompressor * compressor, const NvttInputOptions * inputOptions, const NvttCompressionOptions * compressionOptions) { return compressor->estimateSize(*inputOptions, *compressionOptions); } // Global functions. const char * nvttErrorString(NvttError e) { return nvtt::errorString((nvtt::Error)e); } unsigned int nvttVersion() { return nvtt::version(); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/nvtt_wrapper.h000066400000000000000000000214371173441656100234110ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 NVTT_WRAPPER_H #define NVTT_WRAPPER_H // Function linkage #if NVTT_SHARED #if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__ || defined __MINGW32__ # ifdef NVTT_EXPORTS # define NVTT_API __declspec(dllexport) # else # define NVTT_API __declspec(dllimport) # endif #endif #if defined __GNUC__ >= 4 # ifdef NVTT_EXPORTS # define NVTT_API __attribute__((visibility("default"))) # endif #endif #endif // NVTT_SHARED #if !defined NVTT_API # define NVTT_API #endif #define NVTT_VERSION 200 #ifdef __cplusplus typedef struct nvtt::InputOptions NvttInputOptions; typedef struct nvtt::CompressionOptions NvttCompressionOptions; typedef struct nvtt::OutputOptions NvttOutputOptions; typedef struct nvtt::Compressor NvttCompressor; #else typedef struct NvttInputOptions NvttInputOptions; typedef struct NvttCompressionOptions NvttCompressionOptions; typedef struct NvttOutputOptions NvttOutputOptions; typedef struct NvttCompressor NvttCompressor; #endif /// Supported compression formats. typedef enum { // No compression. NVTT_Format_RGB, NVTT_Format_RGBA = NVTT_Format_RGB, // DX9 formats. NVTT_Format_DXT1, NVTT_Format_DXT1a, NVTT_Format_DXT3, NVTT_Format_DXT5, NVTT_Format_DXT5n, // DX10 formats. NVTT_Format_BC1 = NVTT_Format_DXT1, NVTT_Format_BC1a = NVTT_Format_DXT1a, NVTT_Format_BC2 = NVTT_Format_DXT3, NVTT_Format_BC3 = NVTT_Format_DXT5, NVTT_Format_BC3n = NVTT_Format_DXT5n, NVTT_Format_BC4, NVTT_Format_BC5, } NvttFormat; /// Quality modes. typedef enum { NVTT_Quality_Fastest, NVTT_Quality_Normal, NVTT_Quality_Production, NVTT_Quality_Highest, } NvttQuality; /// Wrap modes. typedef enum { NVTT_WrapMode_Clamp, NVTT_WrapMode_Repeat, NVTT_WrapMode_Mirror, } NvttWrapMode; /// Texture types. typedef enum { NVTT_TextureType_2D, NVTT_TextureType_Cube, } NvttTextureType; /// Input formats. typedef enum { NVTT_InputFormat_BGRA_8UB, } NvttInputFormat; /// Mipmap downsampling filters. typedef enum { NVTT_MipmapFilter_Box, NVTT_MipmapFilter_Triangle, NVTT_MipmapFilter_Kaiser, } NvttMipmapFilter; /// Color transformation. typedef enum { NVTT_ColorTransform_None, NVTT_ColorTransform_Linear, } NvttColorTransform; /// Extents rounding mode. typedef enum { NVTT_RoundMode_None, NVTT_RoundMode_ToNextPowerOfTwo, NVTT_RoundMode_ToNearestPowerOfTwo, NVTT_RoundMode_ToPreviousPowerOfTwo, } NvttRoundMode; /// Alpha mode. typedef enum { NVTT_AlphaMode_None, NVTT_AlphaMode_Transparency, NVTT_AlphaMode_Premultiplied, } NvttAlphaMode; typedef enum { NVTT_Error_InvalidInput, NVTT_Error_UserInterruption, NVTT_Error_UnsupportedFeature, NVTT_Error_CudaError, NVTT_Error_Unknown, NVTT_Error_FileOpen, NVTT_Error_FileWrite, } NvttError; typedef enum { NVTT_False, NVTT_True, } NvttBoolean; #ifdef __cplusplus extern "C" { #endif // Callbacks //typedef void (* nvttErrorHandler)(NvttError e); //typedef void (* nvttOutputHandler)(const void * data, int size); //typedef void (* nvttImageHandler)(int size, int width, int height, int depth, int face, int miplevel); // InputOptions class. NVTT_API NvttInputOptions * nvttCreateInputOptions(); NVTT_API void nvttDestroyInputOptions(NvttInputOptions * inputOptions); NVTT_API void nvttSetInputOptionsTextureLayout(NvttInputOptions * inputOptions, NvttTextureType type, int w, int h, int d); NVTT_API void nvttResetInputOptionsTextureLayout(NvttInputOptions * inputOptions); NVTT_API NvttBoolean nvttSetInputOptionsMipmapData(NvttInputOptions * inputOptions, const void * data, int w, int h, int d, int face, int mipmap); NVTT_API void nvttSetInputOptionsFormat(NvttInputOptions * inputOptions, NvttInputFormat format); NVTT_API void nvttSetInputOptionsAlphaMode(NvttInputOptions * inputOptions, NvttAlphaMode alphaMode); NVTT_API void nvttSetInputOptionsGamma(NvttInputOptions * inputOptions, float inputGamma, float outputGamma); NVTT_API void nvttSetInputOptionsWrapMode(NvttInputOptions * inputOptions, NvttWrapMode mode); NVTT_API void nvttSetInputOptionsMipmapFilter(NvttInputOptions * inputOptions, NvttMipmapFilter filter); NVTT_API void nvttSetInputOptionsMipmapGeneration(NvttInputOptions * inputOptions, NvttBoolean enabled, int maxLevel); NVTT_API void nvttSetInputOptionsKaiserParameters(NvttInputOptions * inputOptions, float width, float alpha, float stretch); NVTT_API void nvttSetInputOptionsNormalMap(NvttInputOptions * inputOptions, NvttBoolean b); NVTT_API void nvttSetInputOptionsConvertToNormalMap(NvttInputOptions * inputOptions, NvttBoolean convert); NVTT_API void nvttSetInputOptionsHeightEvaluation(NvttInputOptions * inputOptions, float redScale, float greenScale, float blueScale, float alphaScale); NVTT_API void nvttSetInputOptionsNormalFilter(NvttInputOptions * inputOptions, float sm, float medium, float big, float large); NVTT_API void nvttSetInputOptionsNormalizeMipmaps(NvttInputOptions * inputOptions, NvttBoolean b); NVTT_API void nvttSetInputOptionsColorTransform(NvttInputOptions * inputOptions, NvttColorTransform t); NVTT_API void nvttSetInputOptionsLinearTransform(NvttInputOptions * inputOptions, int channel, float w0, float w1, float w2, float w3); NVTT_API void nvttSetInputOptionsMaxExtents(NvttInputOptions * inputOptions, int dim); NVTT_API void nvttSetInputOptionsRoundMode(NvttInputOptions * inputOptions, NvttRoundMode mode); // CompressionOptions class. NVTT_API NvttCompressionOptions * nvttCreateCompressionOptions(); NVTT_API void nvttDestroyCompressionOptions(NvttCompressionOptions * compressionOptions); NVTT_API void nvttSetCompressionOptionsFormat(NvttCompressionOptions * compressionOptions, NvttFormat format); NVTT_API void nvttSetCompressionOptionsQuality(NvttCompressionOptions * compressionOptions, NvttQuality quality); NVTT_API void nvttSetCompressionOptionsColorWeights(NvttCompressionOptions * compressionOptions, float red, float green, float blue, float alpha); NVTT_API void nvttSetCompressionOptionsPixelFormat(NvttCompressionOptions * compressionOptions, unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask); NVTT_API void nvttSetCompressionOptionsQuantization(NvttCompressionOptions * compressionOptions, NvttBoolean colorDithering, NvttBoolean alphaDithering, NvttBoolean binaryAlpha, int alphaThreshold); // OutputOptions class. NVTT_API NvttOutputOptions * nvttCreateOutputOptions(); NVTT_API void nvttDestroyOutputOptions(NvttOutputOptions * outputOptions); NVTT_API void nvttSetOutputOptionsFileName(NvttOutputOptions * outputOptions, const char * fileName); NVTT_API void nvttSetOutputOptionsOutputHeader(NvttOutputOptions * outputOptions, NvttBoolean b); //NVTT_API void nvttSetOutputOptionsErrorHandler(NvttOutputOptions * outputOptions, nvttErrorHandler errorHandler); //NVTT_API void nvttSetOutputOptionsOutputHandler(NvttOutputOptions * outputOptions, nvttOutputHandler outputHandler, nvttImageHandler imageHandler); // Compressor class. NVTT_API NvttCompressor * nvttCreateCompressor(); NVTT_API void nvttDestroyCompressor(NvttCompressor * compressor); NVTT_API NvttBoolean nvttCompress(const NvttCompressor * compressor, const NvttInputOptions * inputOptions, const NvttCompressionOptions * compressionOptions, const NvttOutputOptions * outputOptions); NVTT_API int nvttEstimateSize(const NvttCompressor * compressor, const NvttInputOptions * inputOptions, const NvttCompressionOptions * compressionOptions); // Global functions. NVTT_API const char * nvttErrorString(NvttError e); NVTT_API unsigned int nvttVersion(); #ifdef __cplusplus } // extern "C" #endif #endif // NVTT_WRAPPER_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/000077500000000000000000000000001173441656100220125ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/CMakeLists.txt000066400000000000000000000007451173441656100245600ustar00rootroot00000000000000PROJECT(squish) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(SQUISH_SRCS 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 simd.h simd_sse.h simd_ve.h) ADD_LIBRARY(squish STATIC ${SQUISH_SRCS}) IF(CMAKE_COMPILER_IS_GNUCXX) SET_TARGET_PROPERTIES(squish PROPERTIES COMPILE_FLAGS -fPIC) ENDIF(CMAKE_COMPILER_IS_GNUCXX) nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/ChangeLog000066400000000000000000000022771173441656100235740ustar00rootroot00000000000000 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/Doxyfile000066400000000000000000000203111173441656100235150ustar00rootroot00000000000000# 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/README000066400000000000000000000027211173441656100226740ustar00rootroot00000000000000LICENSE ------- 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/alpha.cpp000066400000000000000000000170701173441656100236100ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/alpha.h000066400000000000000000000031711173441656100232520ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/clusterfit.cpp000066400000000000000000000312341173441656100247050ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 namespace squish { ClusterFit::ClusterFit() { } void ClusterFit::SetColourSet( ColourSet const* colours, int flags ) { ColourFit::SetColourSet( colours, flags ); // initialise the best error #if SQUISH_USE_SIMD m_besterror = VEC4_CONST( FLT_MAX ); Vec3 metric = m_metric.GetVec3(); #else m_besterror = FLT_MAX; Vec3 metric = m_metric; #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(), metric ); // 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 m_metricSqr = m_metric * m_metric; } float ClusterFit::GetBestError() 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_metricSqr; 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_metricSqr ); //if (debug) printf(" - %f\n", error); // save the start and end start = a; end = b; return error; } #endif } // namespace squish nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/clusterfit.h000066400000000000000000000045041173441656100243520ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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(); void SetColourSet( ColourSet const* colours, int flags ); void SetMetric(float r, float g, float b); float GetBestError() 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_metricSqr; 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; Vec3 m_metricSqr; 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/colourblock.cpp000066400000000000000000000146121173441656100250400ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/colourblock.h000066400000000000000000000035431173441656100245060ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/colourfit.cpp000066400000000000000000000033361173441656100245310ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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() { } void ColourFit::SetColourSet( ColourSet const* colours, int flags ) { m_colours = colours; m_flags = flags; } void ColourFit::Compress( void* block ) { bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 ); if( isDxt1 ) { Compress3( block ); if( !m_colours->IsTransparent() ) { Compress4( block ); } } else { Compress4( block ); } } } // namespace squish nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/colourfit.h000066400000000000000000000033401173441656100241710ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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(); void SetColourSet( 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/colourset.cpp000066400000000000000000000103041173441656100245330ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 { // @@ Add flags: // - MatchTransparent // - WeightColorByAlpha ColourSet::ColourSet( u8 const* rgba, int flags, bool createMinimalSet/*=false*/ ) : m_count( 0 ), m_transparent( false ) { // check the compression mode for dxt1 bool isDxt1 = ( ( flags & kDxt1 ) != 0 ); bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 ); // create the minimal set for( int i = 0; i < 16; ++i ) { if (createMinimalSet) { // check for transparent pixels when using dxt1 if( isDxt1 && rgba[4*i + 3] == 0 ) { m_remap[i] = -1; m_transparent = true; continue; } // loop over previous points for a match for( int j = 0;; ++j ) { // allocate a new point if( j == i ) { // normalise coordinates to [0,1] float x = ( float )rgba[4*i + 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 ); // @@ I think this check is not necessary. 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; } } } else { // check for transparent pixels when using dxt1 if( isDxt1 && rgba[4*i + 3] == 0 ) { m_remap[i] = -1; m_transparent = true; } else { m_remap[i] = m_count; } // 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 ); // advance ++m_count; } } #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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/colourset.h000066400000000000000000000042531173441656100242060ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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, bool createMinimalSet = false ); 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/config000066400000000000000000000006251173441656100232050ustar00rootroot00000000000000# 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/config.h000066400000000000000000000037451173441656100234410ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/extra/000077500000000000000000000000001173441656100231355ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/extra/squishgen.cpp000066400000000000000000000102451173441656100256510ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 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 ); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/extra/squishpng.cpp000066400000000000000000000361001173441656100256620ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #include #include #include #include #include #include #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] " << 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; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/extra/squishtest.cpp000066400000000000000000000122331173441656100260560ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #include #include #include 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 ); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/fastclusterfit.cpp000066400000000000000000000353061173441656100255670ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #include "fastclusterlookup.inl" namespace squish { FastClusterFit::FastClusterFit() { } void FastClusterFit::SetColourSet( ColourSet const* colours, int flags ) { ColourFit::SetColourSet( colours, flags ); // initialise the best error #if SQUISH_USE_SIMD m_besterror = VEC4_CONST( FLT_MAX ); Vec3 metric = m_metric.GetVec3(); #else m_besterror = FLT_MAX; Vec3 metric = m_metric; #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(), metric ); // 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]; } } 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 m_metricSqr = m_metric * m_metric; } float FastClusterFit::GetBestError() const { #if SQUISH_USE_SIMD Vec4 x = m_xxsum * m_metricSqr; Vec4 error = m_besterror + x.SplatX() + x.SplatY() + x.SplatZ(); return error.GetVec3().X(); #else return m_besterror + Dot(m_xxsum, m_metricSqr); #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 constants = Vec4((const float *)&s_threeElement[i]); Vec4 const alpha2_sum = constants.SplatX(); Vec4 const beta2_sum = constants.SplatY(); Vec4 const alphabeta_sum = constants.SplatZ(); Vec4 const factor = constants.SplatW(); 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_metricSqr; 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]; m_colours->RemapIndices( ordered, bestindices ); // Set alpha indices. // 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 constants = Vec4((const float *)&s_fourElement[i]); Vec4 const alpha2_sum = constants.SplatX(); Vec4 const beta2_sum = constants.SplatY(); Vec4 const alphabeta_sum = constants.SplatZ(); Vec4 const factor = constants.SplatW(); 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_metricSqr; 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_metricSqr ); // 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_metricSqr ); // 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/fastclusterfit.h000066400000000000000000000042341173441656100252300ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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(); void SetColourSet( ColourSet const* colours, int flags ); void SetMetric(float r, float g, float b); float GetBestError() const; // 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_metricSqr; Vec4 m_xxsum; Vec4 m_xsum; Vec4 m_besterror; #else Vec3 m_unweighted[16]; Vec3 m_metric; Vec3 m_metricSqr; Vec3 m_xxsum; Vec3 m_xsum; float m_besterror; #endif int m_order[16]; }; } // namespace squish #endif // ndef SQUISH_FASTCLUSTERFIT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/fastclusterlookup.inl000066400000000000000000002236321173441656100263170ustar00rootroot00000000000000struct Precomp { float alpha2_sum; float beta2_sum; float alphabeta_sum; float factor; }; static const SQUISH_ALIGN_16 Precomp s_threeElement[153] = { { 0.000000f, 16.000000f, 0.000000f, FLT_MAX }, // 0 (0 0 16) { 0.250000f, 15.250000f, 0.250000f, 0.266667f }, // 1 (0 1 15) { 0.500000f, 14.500000f, 0.500000f, 0.142857f }, // 2 (0 2 14) { 0.750000f, 13.750000f, 0.750000f, 0.102564f }, // 3 (0 3 13) { 1.000000f, 13.000000f, 1.000000f, 0.083333f }, // 4 (0 4 12) { 1.250000f, 12.250000f, 1.250000f, 0.072727f }, // 5 (0 5 11) { 1.500000f, 11.500000f, 1.500000f, 0.066667f }, // 6 (0 6 10) { 1.750000f, 10.750000f, 1.750000f, 0.063492f }, // 7 (0 7 9) { 2.000000f, 10.000000f, 2.000000f, 0.062500f }, // 8 (0 8 8) { 2.250000f, 9.250000f, 2.250000f, 0.063492f }, // 9 (0 9 7) { 2.500000f, 8.500000f, 2.500000f, 0.066667f }, // 10 (0 10 6) { 2.750000f, 7.750000f, 2.750000f, 0.072727f }, // 11 (0 11 5) { 3.000000f, 7.000000f, 3.000000f, 0.083333f }, // 12 (0 12 4) { 3.250000f, 6.250000f, 3.250000f, 0.102564f }, // 13 (0 13 3) { 3.500000f, 5.500000f, 3.500000f, 0.142857f }, // 14 (0 14 2) { 3.750000f, 4.750000f, 3.750000f, 0.266667f }, // 15 (0 15 1) { 4.000000f, 4.000000f, 4.000000f, FLT_MAX }, // 16 (0 16 0) { 1.000000f, 15.000000f, 0.000000f, 0.066667f }, // 17 (1 0 15) { 1.250000f, 14.250000f, 0.250000f, 0.056338f }, // 18 (1 1 14) { 1.500000f, 13.500000f, 0.500000f, 0.050000f }, // 19 (1 2 13) { 1.750000f, 12.750000f, 0.750000f, 0.045977f }, // 20 (1 3 12) { 2.000000f, 12.000000f, 1.000000f, 0.043478f }, // 21 (1 4 11) { 2.250000f, 11.250000f, 1.250000f, 0.042105f }, // 22 (1 5 10) { 2.500000f, 10.500000f, 1.500000f, 0.041667f }, // 23 (1 6 9) { 2.750000f, 9.750000f, 1.750000f, 0.042105f }, // 24 (1 7 8) { 3.000000f, 9.000000f, 2.000000f, 0.043478f }, // 25 (1 8 7) { 3.250000f, 8.250000f, 2.250000f, 0.045977f }, // 26 (1 9 6) { 3.500000f, 7.500000f, 2.500000f, 0.050000f }, // 27 (1 10 5) { 3.750000f, 6.750000f, 2.750000f, 0.056338f }, // 28 (1 11 4) { 4.000000f, 6.000000f, 3.000000f, 0.066667f }, // 29 (1 12 3) { 4.250000f, 5.250000f, 3.250000f, 0.085106f }, // 30 (1 13 2) { 4.500000f, 4.500000f, 3.500000f, 0.125000f }, // 31 (1 14 1) { 4.750000f, 3.750000f, 3.750000f, 0.266667f }, // 32 (1 15 0) { 2.000000f, 14.000000f, 0.000000f, 0.035714f }, // 33 (2 0 14) { 2.250000f, 13.250000f, 0.250000f, 0.033613f }, // 34 (2 1 13) { 2.500000f, 12.500000f, 0.500000f, 0.032258f }, // 35 (2 2 12) { 2.750000f, 11.750000f, 0.750000f, 0.031496f }, // 36 (2 3 11) { 3.000000f, 11.000000f, 1.000000f, 0.031250f }, // 37 (2 4 10) { 3.250000f, 10.250000f, 1.250000f, 0.031496f }, // 38 (2 5 9) { 3.500000f, 9.500000f, 1.500000f, 0.032258f }, // 39 (2 6 8) { 3.750000f, 8.750000f, 1.750000f, 0.033613f }, // 40 (2 7 7) { 4.000000f, 8.000000f, 2.000000f, 0.035714f }, // 41 (2 8 6) { 4.250000f, 7.250000f, 2.250000f, 0.038835f }, // 42 (2 9 5) { 4.500000f, 6.500000f, 2.500000f, 0.043478f }, // 43 (2 10 4) { 4.750000f, 5.750000f, 2.750000f, 0.050633f }, // 44 (2 11 3) { 5.000000f, 5.000000f, 3.000000f, 0.062500f }, // 45 (2 12 2) { 5.250000f, 4.250000f, 3.250000f, 0.085106f }, // 46 (2 13 1) { 5.500000f, 3.500000f, 3.500000f, 0.142857f }, // 47 (2 14 0) { 3.000000f, 13.000000f, 0.000000f, 0.025641f }, // 48 (3 0 13) { 3.250000f, 12.250000f, 0.250000f, 0.025157f }, // 49 (3 1 12) { 3.500000f, 11.500000f, 0.500000f, 0.025000f }, // 50 (3 2 11) { 3.750000f, 10.750000f, 0.750000f, 0.025157f }, // 51 (3 3 10) { 4.000000f, 10.000000f, 1.000000f, 0.025641f }, // 52 (3 4 9) { 4.250000f, 9.250000f, 1.250000f, 0.026490f }, // 53 (3 5 8) { 4.500000f, 8.500000f, 1.500000f, 0.027778f }, // 54 (3 6 7) { 4.750000f, 7.750000f, 1.750000f, 0.029630f }, // 55 (3 7 6) { 5.000000f, 7.000000f, 2.000000f, 0.032258f }, // 56 (3 8 5) { 5.250000f, 6.250000f, 2.250000f, 0.036036f }, // 57 (3 9 4) { 5.500000f, 5.500000f, 2.500000f, 0.041667f }, // 58 (3 10 3) { 5.750000f, 4.750000f, 2.750000f, 0.050633f }, // 59 (3 11 2) { 6.000000f, 4.000000f, 3.000000f, 0.066667f }, // 60 (3 12 1) { 6.250000f, 3.250000f, 3.250000f, 0.102564f }, // 61 (3 13 0) { 4.000000f, 12.000000f, 0.000000f, 0.020833f }, // 62 (4 0 12) { 4.250000f, 11.250000f, 0.250000f, 0.020942f }, // 63 (4 1 11) { 4.500000f, 10.500000f, 0.500000f, 0.021277f }, // 64 (4 2 10) { 4.750000f, 9.750000f, 0.750000f, 0.021858f }, // 65 (4 3 9) { 5.000000f, 9.000000f, 1.000000f, 0.022727f }, // 66 (4 4 8) { 5.250000f, 8.250000f, 1.250000f, 0.023952f }, // 67 (4 5 7) { 5.500000f, 7.500000f, 1.500000f, 0.025641f }, // 68 (4 6 6) { 5.750000f, 6.750000f, 1.750000f, 0.027972f }, // 69 (4 7 5) { 6.000000f, 6.000000f, 2.000000f, 0.031250f }, // 70 (4 8 4) { 6.250000f, 5.250000f, 2.250000f, 0.036036f }, // 71 (4 9 3) { 6.500000f, 4.500000f, 2.500000f, 0.043478f }, // 72 (4 10 2) { 6.750000f, 3.750000f, 2.750000f, 0.056338f }, // 73 (4 11 1) { 7.000000f, 3.000000f, 3.000000f, 0.083333f }, // 74 (4 12 0) { 5.000000f, 11.000000f, 0.000000f, 0.018182f }, // 75 (5 0 11) { 5.250000f, 10.250000f, 0.250000f, 0.018605f }, // 76 (5 1 10) { 5.500000f, 9.500000f, 0.500000f, 0.019231f }, // 77 (5 2 9) { 5.750000f, 8.750000f, 0.750000f, 0.020101f }, // 78 (5 3 8) { 6.000000f, 8.000000f, 1.000000f, 0.021277f }, // 79 (5 4 7) { 6.250000f, 7.250000f, 1.250000f, 0.022857f }, // 80 (5 5 6) { 6.500000f, 6.500000f, 1.500000f, 0.025000f }, // 81 (5 6 5) { 6.750000f, 5.750000f, 1.750000f, 0.027972f }, // 82 (5 7 4) { 7.000000f, 5.000000f, 2.000000f, 0.032258f }, // 83 (5 8 3) { 7.250000f, 4.250000f, 2.250000f, 0.038835f }, // 84 (5 9 2) { 7.500000f, 3.500000f, 2.500000f, 0.050000f }, // 85 (5 10 1) { 7.750000f, 2.750000f, 2.750000f, 0.072727f }, // 86 (5 11 0) { 6.000000f, 10.000000f, 0.000000f, 0.016667f }, // 87 (6 0 10) { 6.250000f, 9.250000f, 0.250000f, 0.017316f }, // 88 (6 1 9) { 6.500000f, 8.500000f, 0.500000f, 0.018182f }, // 89 (6 2 8) { 6.750000f, 7.750000f, 0.750000f, 0.019324f }, // 90 (6 3 7) { 7.000000f, 7.000000f, 1.000000f, 0.020833f }, // 91 (6 4 6) { 7.250000f, 6.250000f, 1.250000f, 0.022857f }, // 92 (6 5 5) { 7.500000f, 5.500000f, 1.500000f, 0.025641f }, // 93 (6 6 4) { 7.750000f, 4.750000f, 1.750000f, 0.029630f }, // 94 (6 7 3) { 8.000000f, 4.000000f, 2.000000f, 0.035714f }, // 95 (6 8 2) { 8.250000f, 3.250000f, 2.250000f, 0.045977f }, // 96 (6 9 1) { 8.500000f, 2.500000f, 2.500000f, 0.066667f }, // 97 (6 10 0) { 7.000000f, 9.000000f, 0.000000f, 0.015873f }, // 98 (7 0 9) { 7.250000f, 8.250000f, 0.250000f, 0.016736f }, // 99 (7 1 8) { 7.500000f, 7.500000f, 0.500000f, 0.017857f }, // 100 (7 2 7) { 7.750000f, 6.750000f, 0.750000f, 0.019324f }, // 101 (7 3 6) { 8.000000f, 6.000000f, 1.000000f, 0.021277f }, // 102 (7 4 5) { 8.250000f, 5.250000f, 1.250000f, 0.023952f }, // 103 (7 5 4) { 8.500000f, 4.500000f, 1.500000f, 0.027778f }, // 104 (7 6 3) { 8.750000f, 3.750000f, 1.750000f, 0.033613f }, // 105 (7 7 2) { 9.000000f, 3.000000f, 2.000000f, 0.043478f }, // 106 (7 8 1) { 9.250000f, 2.250000f, 2.250000f, 0.063492f }, // 107 (7 9 0) { 8.000000f, 8.000000f, 0.000000f, 0.015625f }, // 108 (8 0 8) { 8.250000f, 7.250000f, 0.250000f, 0.016736f }, // 109 (8 1 7) { 8.500000f, 6.500000f, 0.500000f, 0.018182f }, // 110 (8 2 6) { 8.750000f, 5.750000f, 0.750000f, 0.020101f }, // 111 (8 3 5) { 9.000000f, 5.000000f, 1.000000f, 0.022727f }, // 112 (8 4 4) { 9.250000f, 4.250000f, 1.250000f, 0.026490f }, // 113 (8 5 3) { 9.500000f, 3.500000f, 1.500000f, 0.032258f }, // 114 (8 6 2) { 9.750000f, 2.750000f, 1.750000f, 0.042105f }, // 115 (8 7 1) { 10.000000f, 2.000000f, 2.000000f, 0.062500f }, // 116 (8 8 0) { 9.000000f, 7.000000f, 0.000000f, 0.015873f }, // 117 (9 0 7) { 9.250000f, 6.250000f, 0.250000f, 0.017316f }, // 118 (9 1 6) { 9.500000f, 5.500000f, 0.500000f, 0.019231f }, // 119 (9 2 5) { 9.750000f, 4.750000f, 0.750000f, 0.021858f }, // 120 (9 3 4) { 10.000000f, 4.000000f, 1.000000f, 0.025641f }, // 121 (9 4 3) { 10.250000f, 3.250000f, 1.250000f, 0.031496f }, // 122 (9 5 2) { 10.500000f, 2.500000f, 1.500000f, 0.041667f }, // 123 (9 6 1) { 10.750000f, 1.750000f, 1.750000f, 0.063492f }, // 124 (9 7 0) { 10.000000f, 6.000000f, 0.000000f, 0.016667f }, // 125 (10 0 6) { 10.250000f, 5.250000f, 0.250000f, 0.018605f }, // 126 (10 1 5) { 10.500000f, 4.500000f, 0.500000f, 0.021277f }, // 127 (10 2 4) { 10.750000f, 3.750000f, 0.750000f, 0.025157f }, // 128 (10 3 3) { 11.000000f, 3.000000f, 1.000000f, 0.031250f }, // 129 (10 4 2) { 11.250000f, 2.250000f, 1.250000f, 0.042105f }, // 130 (10 5 1) { 11.500000f, 1.500000f, 1.500000f, 0.066667f }, // 131 (10 6 0) { 11.000000f, 5.000000f, 0.000000f, 0.018182f }, // 132 (11 0 5) { 11.250000f, 4.250000f, 0.250000f, 0.020942f }, // 133 (11 1 4) { 11.500000f, 3.500000f, 0.500000f, 0.025000f }, // 134 (11 2 3) { 11.750000f, 2.750000f, 0.750000f, 0.031496f }, // 135 (11 3 2) { 12.000000f, 2.000000f, 1.000000f, 0.043478f }, // 136 (11 4 1) { 12.250000f, 1.250000f, 1.250000f, 0.072727f }, // 137 (11 5 0) { 12.000000f, 4.000000f, 0.000000f, 0.020833f }, // 138 (12 0 4) { 12.250000f, 3.250000f, 0.250000f, 0.025157f }, // 139 (12 1 3) { 12.500000f, 2.500000f, 0.500000f, 0.032258f }, // 140 (12 2 2) { 12.750000f, 1.750000f, 0.750000f, 0.045977f }, // 141 (12 3 1) { 13.000000f, 1.000000f, 1.000000f, 0.083333f }, // 142 (12 4 0) { 13.000000f, 3.000000f, 0.000000f, 0.025641f }, // 143 (13 0 3) { 13.250000f, 2.250000f, 0.250000f, 0.033613f }, // 144 (13 1 2) { 13.500000f, 1.500000f, 0.500000f, 0.050000f }, // 145 (13 2 1) { 13.750000f, 0.750000f, 0.750000f, 0.102564f }, // 146 (13 3 0) { 14.000000f, 2.000000f, 0.000000f, 0.035714f }, // 147 (14 0 2) { 14.250000f, 1.250000f, 0.250000f, 0.056338f }, // 148 (14 1 1) { 14.500000f, 0.500000f, 0.500000f, 0.142857f }, // 149 (14 2 0) { 15.000000f, 1.000000f, 0.000000f, 0.066667f }, // 150 (15 0 1) { 15.250000f, 0.250000f, 0.250000f, 0.266667f }, // 151 (15 1 0) { 16.000000f, 0.000000f, 0.000000f, FLT_MAX }, // 152 (16 0 0) }; // 153 three cluster elements static const SQUISH_ALIGN_16 Precomp s_fourElement[969] = { { 0.000000f, 16.000000f, 0.000000f, FLT_MAX }, // 0 (0 0 0 16) { 0.111111f, 15.444445f, 0.222222f, 0.600000f }, // 1 (0 0 1 15) { 0.222222f, 14.888889f, 0.444444f, 0.321429f }, // 2 (0 0 2 14) { 0.333333f, 14.333333f, 0.666667f, 0.230769f }, // 3 (0 0 3 13) { 0.444444f, 13.777778f, 0.888889f, 0.187500f }, // 4 (0 0 4 12) { 0.555556f, 13.222222f, 1.111111f, 0.163636f }, // 5 (0 0 5 11) { 0.666667f, 12.666667f, 1.333333f, 0.150000f }, // 6 (0 0 6 10) { 0.777778f, 12.111111f, 1.555556f, 0.142857f }, // 7 (0 0 7 9) { 0.888889f, 11.555555f, 1.777778f, 0.140625f }, // 8 (0 0 8 8) { 1.000000f, 11.000000f, 2.000000f, 0.142857f }, // 9 (0 0 9 7) { 1.111111f, 10.444445f, 2.222222f, 0.150000f }, // 10 (0 0 10 6) { 1.222222f, 9.888889f, 2.444444f, 0.163636f }, // 11 (0 0 11 5) { 1.333333f, 9.333333f, 2.666667f, 0.187500f }, // 12 (0 0 12 4) { 1.444444f, 8.777778f, 2.888889f, 0.230769f }, // 13 (0 0 13 3) { 1.555556f, 8.222222f, 3.111111f, 0.321429f }, // 14 (0 0 14 2) { 1.666667f, 7.666667f, 3.333333f, 0.600000f }, // 15 (0 0 15 1) { 1.777778f, 7.111111f, 3.555556f, FLT_MAX }, // 16 (0 0 16 0) { 0.444444f, 15.111111f, 0.222222f, 0.150000f }, // 17 (0 1 0 15) { 0.555556f, 14.555555f, 0.444444f, 0.126761f }, // 18 (0 1 1 14) { 0.666667f, 14.000000f, 0.666667f, 0.112500f }, // 19 (0 1 2 13) { 0.777778f, 13.444445f, 0.888889f, 0.103448f }, // 20 (0 1 3 12) { 0.888889f, 12.888889f, 1.111111f, 0.097826f }, // 21 (0 1 4 11) { 1.000000f, 12.333333f, 1.333333f, 0.094737f }, // 22 (0 1 5 10) { 1.111111f, 11.777778f, 1.555556f, 0.093750f }, // 23 (0 1 6 9) { 1.222222f, 11.222222f, 1.777778f, 0.094737f }, // 24 (0 1 7 8) { 1.333333f, 10.666667f, 2.000000f, 0.097826f }, // 25 (0 1 8 7) { 1.444444f, 10.111111f, 2.222222f, 0.103448f }, // 26 (0 1 9 6) { 1.555556f, 9.555555f, 2.444444f, 0.112500f }, // 27 (0 1 10 5) { 1.666667f, 9.000000f, 2.666667f, 0.126761f }, // 28 (0 1 11 4) { 1.777778f, 8.444445f, 2.888889f, 0.150000f }, // 29 (0 1 12 3) { 1.888889f, 7.888889f, 3.111111f, 0.191489f }, // 30 (0 1 13 2) { 2.000000f, 7.333333f, 3.333333f, 0.281250f }, // 31 (0 1 14 1) { 2.111111f, 6.777778f, 3.555556f, 0.600000f }, // 32 (0 1 15 0) { 0.888889f, 14.222222f, 0.444444f, 0.080357f }, // 33 (0 2 0 14) { 1.000000f, 13.666667f, 0.666667f, 0.075630f }, // 34 (0 2 1 13) { 1.111111f, 13.111111f, 0.888889f, 0.072581f }, // 35 (0 2 2 12) { 1.222222f, 12.555555f, 1.111111f, 0.070866f }, // 36 (0 2 3 11) { 1.333333f, 12.000000f, 1.333333f, 0.070313f }, // 37 (0 2 4 10) { 1.444444f, 11.444445f, 1.555556f, 0.070866f }, // 38 (0 2 5 9) { 1.555556f, 10.888889f, 1.777778f, 0.072581f }, // 39 (0 2 6 8) { 1.666667f, 10.333333f, 2.000000f, 0.075630f }, // 40 (0 2 7 7) { 1.777778f, 9.777778f, 2.222222f, 0.080357f }, // 41 (0 2 8 6) { 1.888889f, 9.222222f, 2.444444f, 0.087379f }, // 42 (0 2 9 5) { 2.000000f, 8.666667f, 2.666667f, 0.097826f }, // 43 (0 2 10 4) { 2.111111f, 8.111111f, 2.888889f, 0.113924f }, // 44 (0 2 11 3) { 2.222222f, 7.555556f, 3.111111f, 0.140625f }, // 45 (0 2 12 2) { 2.333333f, 7.000000f, 3.333333f, 0.191489f }, // 46 (0 2 13 1) { 2.444444f, 6.444445f, 3.555556f, 0.321429f }, // 47 (0 2 14 0) { 1.333333f, 13.333333f, 0.666667f, 0.057692f }, // 48 (0 3 0 13) { 1.444444f, 12.777778f, 0.888889f, 0.056604f }, // 49 (0 3 1 12) { 1.555556f, 12.222222f, 1.111111f, 0.056250f }, // 50 (0 3 2 11) { 1.666667f, 11.666667f, 1.333333f, 0.056604f }, // 51 (0 3 3 10) { 1.777778f, 11.111111f, 1.555556f, 0.057692f }, // 52 (0 3 4 9) { 1.888889f, 10.555555f, 1.777778f, 0.059603f }, // 53 (0 3 5 8) { 2.000000f, 10.000000f, 2.000000f, 0.062500f }, // 54 (0 3 6 7) { 2.111111f, 9.444445f, 2.222222f, 0.066667f }, // 55 (0 3 7 6) { 2.222222f, 8.888889f, 2.444444f, 0.072581f }, // 56 (0 3 8 5) { 2.333333f, 8.333333f, 2.666667f, 0.081081f }, // 57 (0 3 9 4) { 2.444444f, 7.777778f, 2.888889f, 0.093750f }, // 58 (0 3 10 3) { 2.555556f, 7.222222f, 3.111111f, 0.113924f }, // 59 (0 3 11 2) { 2.666667f, 6.666667f, 3.333333f, 0.150000f }, // 60 (0 3 12 1) { 2.777778f, 6.111111f, 3.555556f, 0.230769f }, // 61 (0 3 13 0) { 1.777778f, 12.444445f, 0.888889f, 0.046875f }, // 62 (0 4 0 12) { 1.888889f, 11.888889f, 1.111111f, 0.047120f }, // 63 (0 4 1 11) { 2.000000f, 11.333333f, 1.333333f, 0.047872f }, // 64 (0 4 2 10) { 2.111111f, 10.777778f, 1.555556f, 0.049180f }, // 65 (0 4 3 9) { 2.222222f, 10.222222f, 1.777778f, 0.051136f }, // 66 (0 4 4 8) { 2.333333f, 9.666667f, 2.000000f, 0.053892f }, // 67 (0 4 5 7) { 2.444444f, 9.111111f, 2.222222f, 0.057692f }, // 68 (0 4 6 6) { 2.555556f, 8.555555f, 2.444444f, 0.062937f }, // 69 (0 4 7 5) { 2.666667f, 8.000000f, 2.666667f, 0.070313f }, // 70 (0 4 8 4) { 2.777778f, 7.444445f, 2.888889f, 0.081081f }, // 71 (0 4 9 3) { 2.888889f, 6.888889f, 3.111111f, 0.097826f }, // 72 (0 4 10 2) { 3.000000f, 6.333333f, 3.333333f, 0.126761f }, // 73 (0 4 11 1) { 3.111111f, 5.777778f, 3.555556f, 0.187500f }, // 74 (0 4 12 0) { 2.222222f, 11.555555f, 1.111111f, 0.040909f }, // 75 (0 5 0 11) { 2.333333f, 11.000000f, 1.333333f, 0.041860f }, // 76 (0 5 1 10) { 2.444444f, 10.444445f, 1.555556f, 0.043269f }, // 77 (0 5 2 9) { 2.555556f, 9.888889f, 1.777778f, 0.045226f }, // 78 (0 5 3 8) { 2.666667f, 9.333333f, 2.000000f, 0.047872f }, // 79 (0 5 4 7) { 2.777778f, 8.777778f, 2.222222f, 0.051429f }, // 80 (0 5 5 6) { 2.888889f, 8.222222f, 2.444444f, 0.056250f }, // 81 (0 5 6 5) { 3.000000f, 7.666667f, 2.666667f, 0.062937f }, // 82 (0 5 7 4) { 3.111111f, 7.111111f, 2.888889f, 0.072581f }, // 83 (0 5 8 3) { 3.222222f, 6.555556f, 3.111111f, 0.087379f }, // 84 (0 5 9 2) { 3.333333f, 6.000000f, 3.333333f, 0.112500f }, // 85 (0 5 10 1) { 3.444444f, 5.444445f, 3.555556f, 0.163636f }, // 86 (0 5 11 0) { 2.666667f, 10.666667f, 1.333333f, 0.037500f }, // 87 (0 6 0 10) { 2.777778f, 10.111111f, 1.555556f, 0.038961f }, // 88 (0 6 1 9) { 2.888889f, 9.555555f, 1.777778f, 0.040909f }, // 89 (0 6 2 8) { 3.000000f, 9.000000f, 2.000000f, 0.043478f }, // 90 (0 6 3 7) { 3.111111f, 8.444445f, 2.222222f, 0.046875f }, // 91 (0 6 4 6) { 3.222222f, 7.888889f, 2.444444f, 0.051429f }, // 92 (0 6 5 5) { 3.333333f, 7.333333f, 2.666667f, 0.057692f }, // 93 (0 6 6 4) { 3.444444f, 6.777778f, 2.888889f, 0.066667f }, // 94 (0 6 7 3) { 3.555556f, 6.222222f, 3.111111f, 0.080357f }, // 95 (0 6 8 2) { 3.666667f, 5.666667f, 3.333333f, 0.103448f }, // 96 (0 6 9 1) { 3.777778f, 5.111111f, 3.555556f, 0.150000f }, // 97 (0 6 10 0) { 3.111111f, 9.777778f, 1.555556f, 0.035714f }, // 98 (0 7 0 9) { 3.222222f, 9.222222f, 1.777778f, 0.037657f }, // 99 (0 7 1 8) { 3.333333f, 8.666667f, 2.000000f, 0.040179f }, // 100 (0 7 2 7) { 3.444444f, 8.111111f, 2.222222f, 0.043478f }, // 101 (0 7 3 6) { 3.555556f, 7.555555f, 2.444444f, 0.047872f }, // 102 (0 7 4 5) { 3.666667f, 7.000000f, 2.666667f, 0.053892f }, // 103 (0 7 5 4) { 3.777778f, 6.444445f, 2.888889f, 0.062500f }, // 104 (0 7 6 3) { 3.888889f, 5.888889f, 3.111111f, 0.075630f }, // 105 (0 7 7 2) { 4.000000f, 5.333333f, 3.333333f, 0.097826f }, // 106 (0 7 8 1) { 4.111111f, 4.777778f, 3.555556f, 0.142857f }, // 107 (0 7 9 0) { 3.555556f, 8.888889f, 1.777778f, 0.035156f }, // 108 (0 8 0 8) { 3.666667f, 8.333333f, 2.000000f, 0.037657f }, // 109 (0 8 1 7) { 3.777778f, 7.777778f, 2.222222f, 0.040909f }, // 110 (0 8 2 6) { 3.888889f, 7.222222f, 2.444444f, 0.045226f }, // 111 (0 8 3 5) { 4.000000f, 6.666667f, 2.666667f, 0.051136f }, // 112 (0 8 4 4) { 4.111111f, 6.111111f, 2.888889f, 0.059603f }, // 113 (0 8 5 3) { 4.222222f, 5.555555f, 3.111111f, 0.072581f }, // 114 (0 8 6 2) { 4.333333f, 5.000000f, 3.333333f, 0.094737f }, // 115 (0 8 7 1) { 4.444445f, 4.444445f, 3.555556f, 0.140625f }, // 116 (0 8 8 0) { 4.000000f, 8.000000f, 2.000000f, 0.035714f }, // 117 (0 9 0 7) { 4.111111f, 7.444445f, 2.222222f, 0.038961f }, // 118 (0 9 1 6) { 4.222222f, 6.888889f, 2.444444f, 0.043269f }, // 119 (0 9 2 5) { 4.333333f, 6.333333f, 2.666667f, 0.049180f }, // 120 (0 9 3 4) { 4.444445f, 5.777778f, 2.888889f, 0.057692f }, // 121 (0 9 4 3) { 4.555556f, 5.222222f, 3.111111f, 0.070866f }, // 122 (0 9 5 2) { 4.666667f, 4.666667f, 3.333333f, 0.093750f }, // 123 (0 9 6 1) { 4.777778f, 4.111111f, 3.555556f, 0.142857f }, // 124 (0 9 7 0) { 4.444445f, 7.111111f, 2.222222f, 0.037500f }, // 125 (0 10 0 6) { 4.555556f, 6.555555f, 2.444444f, 0.041860f }, // 126 (0 10 1 5) { 4.666667f, 6.000000f, 2.666667f, 0.047872f }, // 127 (0 10 2 4) { 4.777778f, 5.444445f, 2.888889f, 0.056604f }, // 128 (0 10 3 3) { 4.888889f, 4.888889f, 3.111111f, 0.070313f }, // 129 (0 10 4 2) { 5.000000f, 4.333333f, 3.333333f, 0.094737f }, // 130 (0 10 5 1) { 5.111111f, 3.777778f, 3.555556f, 0.150000f }, // 131 (0 10 6 0) { 4.888889f, 6.222222f, 2.444444f, 0.040909f }, // 132 (0 11 0 5) { 5.000000f, 5.666667f, 2.666667f, 0.047120f }, // 133 (0 11 1 4) { 5.111111f, 5.111111f, 2.888889f, 0.056250f }, // 134 (0 11 2 3) { 5.222222f, 4.555555f, 3.111111f, 0.070866f }, // 135 (0 11 3 2) { 5.333333f, 4.000000f, 3.333333f, 0.097826f }, // 136 (0 11 4 1) { 5.444445f, 3.444444f, 3.555556f, 0.163636f }, // 137 (0 11 5 0) { 5.333333f, 5.333333f, 2.666667f, 0.046875f }, // 138 (0 12 0 4) { 5.444445f, 4.777778f, 2.888889f, 0.056604f }, // 139 (0 12 1 3) { 5.555556f, 4.222222f, 3.111111f, 0.072581f }, // 140 (0 12 2 2) { 5.666667f, 3.666667f, 3.333333f, 0.103448f }, // 141 (0 12 3 1) { 5.777778f, 3.111111f, 3.555556f, 0.187500f }, // 142 (0 12 4 0) { 5.777778f, 4.444445f, 2.888889f, 0.057692f }, // 143 (0 13 0 3) { 5.888889f, 3.888889f, 3.111111f, 0.075630f }, // 144 (0 13 1 2) { 6.000000f, 3.333333f, 3.333333f, 0.112500f }, // 145 (0 13 2 1) { 6.111111f, 2.777778f, 3.555556f, 0.230769f }, // 146 (0 13 3 0) { 6.222222f, 3.555556f, 3.111111f, 0.080357f }, // 147 (0 14 0 2) { 6.333333f, 3.000000f, 3.333333f, 0.126761f }, // 148 (0 14 1 1) { 6.444445f, 2.444444f, 3.555556f, 0.321429f }, // 149 (0 14 2 0) { 6.666667f, 2.666667f, 3.333333f, 0.150000f }, // 150 (0 15 0 1) { 6.777778f, 2.111111f, 3.555556f, 0.600000f }, // 151 (0 15 1 0) { 7.111111f, 1.777778f, 3.555556f, FLT_MAX }, // 152 (0 16 0 0) { 1.000000f, 15.000000f, 0.000000f, 0.066667f }, // 153 (1 0 0 15) { 1.111111f, 14.444445f, 0.222222f, 0.062500f }, // 154 (1 0 1 14) { 1.222222f, 13.888889f, 0.444444f, 0.059603f }, // 155 (1 0 2 13) { 1.333333f, 13.333333f, 0.666667f, 0.057692f }, // 156 (1 0 3 12) { 1.444444f, 12.777778f, 0.888889f, 0.056604f }, // 157 (1 0 4 11) { 1.555556f, 12.222222f, 1.111111f, 0.056250f }, // 158 (1 0 5 10) { 1.666667f, 11.666667f, 1.333333f, 0.056604f }, // 159 (1 0 6 9) { 1.777778f, 11.111111f, 1.555556f, 0.057692f }, // 160 (1 0 7 8) { 1.888889f, 10.555555f, 1.777778f, 0.059603f }, // 161 (1 0 8 7) { 2.000000f, 10.000000f, 2.000000f, 0.062500f }, // 162 (1 0 9 6) { 2.111111f, 9.444445f, 2.222222f, 0.066667f }, // 163 (1 0 10 5) { 2.222222f, 8.888889f, 2.444444f, 0.072581f }, // 164 (1 0 11 4) { 2.333333f, 8.333333f, 2.666667f, 0.081081f }, // 165 (1 0 12 3) { 2.444444f, 7.777778f, 2.888889f, 0.093750f }, // 166 (1 0 13 2) { 2.555556f, 7.222222f, 3.111111f, 0.113924f }, // 167 (1 0 14 1) { 2.666667f, 6.666667f, 3.333333f, 0.150000f }, // 168 (1 0 15 0) { 1.444444f, 14.111111f, 0.222222f, 0.049180f }, // 169 (1 1 0 14) { 1.555556f, 13.555555f, 0.444444f, 0.047872f }, // 170 (1 1 1 13) { 1.666667f, 13.000000f, 0.666667f, 0.047120f }, // 171 (1 1 2 12) { 1.777778f, 12.444445f, 0.888889f, 0.046875f }, // 172 (1 1 3 11) { 1.888889f, 11.888889f, 1.111111f, 0.047120f }, // 173 (1 1 4 10) { 2.000000f, 11.333333f, 1.333333f, 0.047872f }, // 174 (1 1 5 9) { 2.111111f, 10.777778f, 1.555556f, 0.049180f }, // 175 (1 1 6 8) { 2.222222f, 10.222222f, 1.777778f, 0.051136f }, // 176 (1 1 7 7) { 2.333333f, 9.666667f, 2.000000f, 0.053892f }, // 177 (1 1 8 6) { 2.444444f, 9.111111f, 2.222222f, 0.057692f }, // 178 (1 1 9 5) { 2.555556f, 8.555555f, 2.444444f, 0.062937f }, // 179 (1 1 10 4) { 2.666667f, 8.000000f, 2.666667f, 0.070313f }, // 180 (1 1 11 3) { 2.777778f, 7.444445f, 2.888889f, 0.081081f }, // 181 (1 1 12 2) { 2.888889f, 6.888889f, 3.111111f, 0.097826f }, // 182 (1 1 13 1) { 3.000000f, 6.333333f, 3.333333f, 0.126761f }, // 183 (1 1 14 0) { 1.888889f, 13.222222f, 0.444444f, 0.040359f }, // 184 (1 2 0 13) { 2.000000f, 12.666667f, 0.666667f, 0.040179f }, // 185 (1 2 1 12) { 2.111111f, 12.111111f, 0.888889f, 0.040359f }, // 186 (1 2 2 11) { 2.222222f, 11.555555f, 1.111111f, 0.040909f }, // 187 (1 2 3 10) { 2.333333f, 11.000000f, 1.333333f, 0.041860f }, // 188 (1 2 4 9) { 2.444444f, 10.444445f, 1.555556f, 0.043269f }, // 189 (1 2 5 8) { 2.555556f, 9.888889f, 1.777778f, 0.045226f }, // 190 (1 2 6 7) { 2.666667f, 9.333333f, 2.000000f, 0.047872f }, // 191 (1 2 7 6) { 2.777778f, 8.777778f, 2.222222f, 0.051429f }, // 192 (1 2 8 5) { 2.888889f, 8.222222f, 2.444444f, 0.056250f }, // 193 (1 2 9 4) { 3.000000f, 7.666667f, 2.666667f, 0.062937f }, // 194 (1 2 10 3) { 3.111111f, 7.111111f, 2.888889f, 0.072581f }, // 195 (1 2 11 2) { 3.222222f, 6.555556f, 3.111111f, 0.087379f }, // 196 (1 2 12 1) { 3.333333f, 6.000000f, 3.333333f, 0.112500f }, // 197 (1 2 13 0) { 2.333333f, 12.333333f, 0.666667f, 0.035294f }, // 198 (1 3 0 12) { 2.444444f, 11.777778f, 0.888889f, 0.035714f }, // 199 (1 3 1 11) { 2.555556f, 11.222222f, 1.111111f, 0.036437f }, // 200 (1 3 2 10) { 2.666667f, 10.666667f, 1.333333f, 0.037500f }, // 201 (1 3 3 9) { 2.777778f, 10.111111f, 1.555556f, 0.038961f }, // 202 (1 3 4 8) { 2.888889f, 9.555555f, 1.777778f, 0.040909f }, // 203 (1 3 5 7) { 3.000000f, 9.000000f, 2.000000f, 0.043478f }, // 204 (1 3 6 6) { 3.111111f, 8.444445f, 2.222222f, 0.046875f }, // 205 (1 3 7 5) { 3.222222f, 7.888889f, 2.444444f, 0.051429f }, // 206 (1 3 8 4) { 3.333333f, 7.333333f, 2.666667f, 0.057692f }, // 207 (1 3 9 3) { 3.444444f, 6.777778f, 2.888889f, 0.066667f }, // 208 (1 3 10 2) { 3.555556f, 6.222222f, 3.111111f, 0.080357f }, // 209 (1 3 11 1) { 3.666667f, 5.666667f, 3.333333f, 0.103448f }, // 210 (1 3 12 0) { 2.777778f, 11.444445f, 0.888889f, 0.032258f }, // 211 (1 4 0 11) { 2.888889f, 10.888889f, 1.111111f, 0.033088f }, // 212 (1 4 1 10) { 3.000000f, 10.333333f, 1.333333f, 0.034221f }, // 213 (1 4 2 9) { 3.111111f, 9.777778f, 1.555556f, 0.035714f }, // 214 (1 4 3 8) { 3.222222f, 9.222222f, 1.777778f, 0.037657f }, // 215 (1 4 4 7) { 3.333333f, 8.666667f, 2.000000f, 0.040179f }, // 216 (1 4 5 6) { 3.444444f, 8.111111f, 2.222222f, 0.043478f }, // 217 (1 4 6 5) { 3.555556f, 7.555555f, 2.444444f, 0.047872f }, // 218 (1 4 7 4) { 3.666667f, 7.000000f, 2.666667f, 0.053892f }, // 219 (1 4 8 3) { 3.777778f, 6.444445f, 2.888889f, 0.062500f }, // 220 (1 4 9 2) { 3.888889f, 5.888889f, 3.111111f, 0.075630f }, // 221 (1 4 10 1) { 4.000000f, 5.333333f, 3.333333f, 0.097826f }, // 222 (1 4 11 0) { 3.222222f, 10.555555f, 1.111111f, 0.030508f }, // 223 (1 5 0 10) { 3.333333f, 10.000000f, 1.333333f, 0.031690f }, // 224 (1 5 1 9) { 3.444444f, 9.444445f, 1.555556f, 0.033210f }, // 225 (1 5 2 8) { 3.555556f, 8.888889f, 1.777778f, 0.035156f }, // 226 (1 5 3 7) { 3.666667f, 8.333333f, 2.000000f, 0.037657f }, // 227 (1 5 4 6) { 3.777778f, 7.777778f, 2.222222f, 0.040909f }, // 228 (1 5 5 5) { 3.888889f, 7.222222f, 2.444444f, 0.045226f }, // 229 (1 5 6 4) { 4.000000f, 6.666667f, 2.666667f, 0.051136f }, // 230 (1 5 7 3) { 4.111111f, 6.111111f, 2.888889f, 0.059603f }, // 231 (1 5 8 2) { 4.222222f, 5.555556f, 3.111111f, 0.072581f }, // 232 (1 5 9 1) { 4.333333f, 5.000000f, 3.333333f, 0.094737f }, // 233 (1 5 10 0) { 3.666667f, 9.666667f, 1.333333f, 0.029703f }, // 234 (1 6 0 9) { 3.777778f, 9.111111f, 1.555556f, 0.031250f }, // 235 (1 6 1 8) { 3.888889f, 8.555555f, 1.777778f, 0.033210f }, // 236 (1 6 2 7) { 4.000000f, 8.000000f, 2.000000f, 0.035714f }, // 237 (1 6 3 6) { 4.111111f, 7.444445f, 2.222222f, 0.038961f }, // 238 (1 6 4 5) { 4.222222f, 6.888889f, 2.444444f, 0.043269f }, // 239 (1 6 5 4) { 4.333333f, 6.333333f, 2.666667f, 0.049180f }, // 240 (1 6 6 3) { 4.444445f, 5.777778f, 2.888889f, 0.057692f }, // 241 (1 6 7 2) { 4.555555f, 5.222222f, 3.111111f, 0.070866f }, // 242 (1 6 8 1) { 4.666667f, 4.666667f, 3.333333f, 0.093750f }, // 243 (1 6 9 0) { 4.111111f, 8.777778f, 1.555556f, 0.029703f }, // 244 (1 7 0 8) { 4.222222f, 8.222222f, 1.777778f, 0.031690f }, // 245 (1 7 1 7) { 4.333333f, 7.666667f, 2.000000f, 0.034221f }, // 246 (1 7 2 6) { 4.444445f, 7.111111f, 2.222222f, 0.037500f }, // 247 (1 7 3 5) { 4.555555f, 6.555555f, 2.444444f, 0.041860f }, // 248 (1 7 4 4) { 4.666667f, 6.000000f, 2.666667f, 0.047872f }, // 249 (1 7 5 3) { 4.777778f, 5.444445f, 2.888889f, 0.056604f }, // 250 (1 7 6 2) { 4.888889f, 4.888889f, 3.111111f, 0.070313f }, // 251 (1 7 7 1) { 5.000000f, 4.333333f, 3.333333f, 0.094737f }, // 252 (1 7 8 0) { 4.555555f, 7.888889f, 1.777778f, 0.030508f }, // 253 (1 8 0 7) { 4.666667f, 7.333333f, 2.000000f, 0.033088f }, // 254 (1 8 1 6) { 4.777778f, 6.777778f, 2.222222f, 0.036437f }, // 255 (1 8 2 5) { 4.888889f, 6.222222f, 2.444444f, 0.040909f }, // 256 (1 8 3 4) { 5.000000f, 5.666667f, 2.666667f, 0.047120f }, // 257 (1 8 4 3) { 5.111111f, 5.111111f, 2.888889f, 0.056250f }, // 258 (1 8 5 2) { 5.222222f, 4.555555f, 3.111111f, 0.070866f }, // 259 (1 8 6 1) { 5.333333f, 4.000000f, 3.333333f, 0.097826f }, // 260 (1 8 7 0) { 5.000000f, 7.000000f, 2.000000f, 0.032258f }, // 261 (1 9 0 6) { 5.111111f, 6.444445f, 2.222222f, 0.035714f }, // 262 (1 9 1 5) { 5.222222f, 5.888889f, 2.444444f, 0.040359f }, // 263 (1 9 2 4) { 5.333333f, 5.333333f, 2.666667f, 0.046875f }, // 264 (1 9 3 3) { 5.444445f, 4.777778f, 2.888889f, 0.056604f }, // 265 (1 9 4 2) { 5.555556f, 4.222222f, 3.111111f, 0.072581f }, // 266 (1 9 5 1) { 5.666667f, 3.666667f, 3.333333f, 0.103448f }, // 267 (1 9 6 0) { 5.444445f, 6.111111f, 2.222222f, 0.035294f }, // 268 (1 10 0 5) { 5.555556f, 5.555555f, 2.444444f, 0.040179f }, // 269 (1 10 1 4) { 5.666667f, 5.000000f, 2.666667f, 0.047120f }, // 270 (1 10 2 3) { 5.777778f, 4.444445f, 2.888889f, 0.057692f }, // 271 (1 10 3 2) { 5.888889f, 3.888889f, 3.111111f, 0.075630f }, // 272 (1 10 4 1) { 6.000000f, 3.333333f, 3.333333f, 0.112500f }, // 273 (1 10 5 0) { 5.888889f, 5.222222f, 2.444444f, 0.040359f }, // 274 (1 11 0 4) { 6.000000f, 4.666667f, 2.666667f, 0.047872f }, // 275 (1 11 1 3) { 6.111111f, 4.111111f, 2.888889f, 0.059603f }, // 276 (1 11 2 2) { 6.222222f, 3.555556f, 3.111111f, 0.080357f }, // 277 (1 11 3 1) { 6.333333f, 3.000000f, 3.333333f, 0.126761f }, // 278 (1 11 4 0) { 6.333333f, 4.333333f, 2.666667f, 0.049180f }, // 279 (1 12 0 3) { 6.444445f, 3.777778f, 2.888889f, 0.062500f }, // 280 (1 12 1 2) { 6.555556f, 3.222222f, 3.111111f, 0.087379f }, // 281 (1 12 2 1) { 6.666667f, 2.666667f, 3.333333f, 0.150000f }, // 282 (1 12 3 0) { 6.777778f, 3.444444f, 2.888889f, 0.066667f }, // 283 (1 13 0 2) { 6.888889f, 2.888889f, 3.111111f, 0.097826f }, // 284 (1 13 1 1) { 7.000000f, 2.333333f, 3.333333f, 0.191489f }, // 285 (1 13 2 0) { 7.222222f, 2.555556f, 3.111111f, 0.113924f }, // 286 (1 14 0 1) { 7.333333f, 2.000000f, 3.333333f, 0.281250f }, // 287 (1 14 1 0) { 7.666667f, 1.666667f, 3.333333f, 0.600000f }, // 288 (1 15 0 0) { 2.000000f, 14.000000f, 0.000000f, 0.035714f }, // 289 (2 0 0 14) { 2.111111f, 13.444445f, 0.222222f, 0.035294f }, // 290 (2 0 1 13) { 2.222222f, 12.888889f, 0.444444f, 0.035156f }, // 291 (2 0 2 12) { 2.333333f, 12.333333f, 0.666667f, 0.035294f }, // 292 (2 0 3 11) { 2.444444f, 11.777778f, 0.888889f, 0.035714f }, // 293 (2 0 4 10) { 2.555556f, 11.222222f, 1.111111f, 0.036437f }, // 294 (2 0 5 9) { 2.666667f, 10.666667f, 1.333333f, 0.037500f }, // 295 (2 0 6 8) { 2.777778f, 10.111111f, 1.555556f, 0.038961f }, // 296 (2 0 7 7) { 2.888889f, 9.555555f, 1.777778f, 0.040909f }, // 297 (2 0 8 6) { 3.000000f, 9.000000f, 2.000000f, 0.043478f }, // 298 (2 0 9 5) { 3.111111f, 8.444445f, 2.222222f, 0.046875f }, // 299 (2 0 10 4) { 3.222222f, 7.888889f, 2.444444f, 0.051429f }, // 300 (2 0 11 3) { 3.333333f, 7.333333f, 2.666667f, 0.057692f }, // 301 (2 0 12 2) { 3.444444f, 6.777778f, 2.888889f, 0.066667f }, // 302 (2 0 13 1) { 3.555556f, 6.222222f, 3.111111f, 0.080357f }, // 303 (2 0 14 0) { 2.444444f, 13.111111f, 0.222222f, 0.031250f }, // 304 (2 1 0 13) { 2.555556f, 12.555555f, 0.444444f, 0.031359f }, // 305 (2 1 1 12) { 2.666667f, 12.000000f, 0.666667f, 0.031690f }, // 306 (2 1 2 11) { 2.777778f, 11.444445f, 0.888889f, 0.032258f }, // 307 (2 1 3 10) { 2.888889f, 10.888889f, 1.111111f, 0.033088f }, // 308 (2 1 4 9) { 3.000000f, 10.333333f, 1.333333f, 0.034221f }, // 309 (2 1 5 8) { 3.111111f, 9.777778f, 1.555556f, 0.035714f }, // 310 (2 1 6 7) { 3.222222f, 9.222222f, 1.777778f, 0.037657f }, // 311 (2 1 7 6) { 3.333333f, 8.666667f, 2.000000f, 0.040179f }, // 312 (2 1 8 5) { 3.444444f, 8.111111f, 2.222222f, 0.043478f }, // 313 (2 1 9 4) { 3.555556f, 7.555556f, 2.444444f, 0.047872f }, // 314 (2 1 10 3) { 3.666667f, 7.000000f, 2.666667f, 0.053892f }, // 315 (2 1 11 2) { 3.777778f, 6.444445f, 2.888889f, 0.062500f }, // 316 (2 1 12 1) { 3.888889f, 5.888889f, 3.111111f, 0.075630f }, // 317 (2 1 13 0) { 2.888889f, 12.222222f, 0.444444f, 0.028481f }, // 318 (2 2 0 12) { 3.000000f, 11.666667f, 0.666667f, 0.028939f }, // 319 (2 2 1 11) { 3.111111f, 11.111111f, 0.888889f, 0.029605f }, // 320 (2 2 2 10) { 3.222222f, 10.555555f, 1.111111f, 0.030508f }, // 321 (2 2 3 9) { 3.333333f, 10.000000f, 1.333333f, 0.031690f }, // 322 (2 2 4 8) { 3.444444f, 9.444445f, 1.555556f, 0.033210f }, // 323 (2 2 5 7) { 3.555556f, 8.888889f, 1.777778f, 0.035156f }, // 324 (2 2 6 6) { 3.666667f, 8.333333f, 2.000000f, 0.037657f }, // 325 (2 2 7 5) { 3.777778f, 7.777778f, 2.222222f, 0.040909f }, // 326 (2 2 8 4) { 3.888889f, 7.222222f, 2.444444f, 0.045226f }, // 327 (2 2 9 3) { 4.000000f, 6.666667f, 2.666667f, 0.051136f }, // 328 (2 2 10 2) { 4.111111f, 6.111111f, 2.888889f, 0.059603f }, // 329 (2 2 11 1) { 4.222222f, 5.555556f, 3.111111f, 0.072581f }, // 330 (2 2 12 0) { 3.333333f, 11.333333f, 0.666667f, 0.026786f }, // 331 (2 3 0 11) { 3.444444f, 10.777778f, 0.888889f, 0.027523f }, // 332 (2 3 1 10) { 3.555556f, 10.222222f, 1.111111f, 0.028481f }, // 333 (2 3 2 9) { 3.666667f, 9.666667f, 1.333333f, 0.029703f }, // 334 (2 3 3 8) { 3.777778f, 9.111111f, 1.555556f, 0.031250f }, // 335 (2 3 4 7) { 3.888889f, 8.555555f, 1.777778f, 0.033210f }, // 336 (2 3 5 6) { 4.000000f, 8.000000f, 2.000000f, 0.035714f }, // 337 (2 3 6 5) { 4.111111f, 7.444445f, 2.222222f, 0.038961f }, // 338 (2 3 7 4) { 4.222222f, 6.888889f, 2.444444f, 0.043269f }, // 339 (2 3 8 3) { 4.333333f, 6.333333f, 2.666667f, 0.049180f }, // 340 (2 3 9 2) { 4.444445f, 5.777778f, 2.888889f, 0.057692f }, // 341 (2 3 10 1) { 4.555555f, 5.222222f, 3.111111f, 0.070866f }, // 342 (2 3 11 0) { 3.777778f, 10.444445f, 0.888889f, 0.025862f }, // 343 (2 4 0 10) { 3.888889f, 9.888889f, 1.111111f, 0.026866f }, // 344 (2 4 1 9) { 4.000000f, 9.333333f, 1.333333f, 0.028125f }, // 345 (2 4 2 8) { 4.111111f, 8.777778f, 1.555556f, 0.029703f }, // 346 (2 4 3 7) { 4.222222f, 8.222222f, 1.777778f, 0.031690f }, // 347 (2 4 4 6) { 4.333333f, 7.666667f, 2.000000f, 0.034221f }, // 348 (2 4 5 5) { 4.444445f, 7.111111f, 2.222222f, 0.037500f }, // 349 (2 4 6 4) { 4.555555f, 6.555555f, 2.444444f, 0.041860f }, // 350 (2 4 7 3) { 4.666667f, 6.000000f, 2.666667f, 0.047872f }, // 351 (2 4 8 2) { 4.777778f, 5.444445f, 2.888889f, 0.056604f }, // 352 (2 4 9 1) { 4.888889f, 4.888889f, 3.111111f, 0.070313f }, // 353 (2 4 10 0) { 4.222222f, 9.555555f, 1.111111f, 0.025568f }, // 354 (2 5 0 9) { 4.333333f, 9.000000f, 1.333333f, 0.026866f }, // 355 (2 5 1 8) { 4.444445f, 8.444445f, 1.555556f, 0.028481f }, // 356 (2 5 2 7) { 4.555555f, 7.888889f, 1.777778f, 0.030508f }, // 357 (2 5 3 6) { 4.666667f, 7.333333f, 2.000000f, 0.033088f }, // 358 (2 5 4 5) { 4.777778f, 6.777778f, 2.222222f, 0.036437f }, // 359 (2 5 5 4) { 4.888889f, 6.222222f, 2.444444f, 0.040909f }, // 360 (2 5 6 3) { 5.000000f, 5.666667f, 2.666667f, 0.047120f }, // 361 (2 5 7 2) { 5.111111f, 5.111111f, 2.888889f, 0.056250f }, // 362 (2 5 8 1) { 5.222222f, 4.555556f, 3.111111f, 0.070866f }, // 363 (2 5 9 0) { 4.666667f, 8.666667f, 1.333333f, 0.025862f }, // 364 (2 6 0 8) { 4.777778f, 8.111111f, 1.555556f, 0.027523f }, // 365 (2 6 1 7) { 4.888889f, 7.555555f, 1.777778f, 0.029605f }, // 366 (2 6 2 6) { 5.000000f, 7.000000f, 2.000000f, 0.032258f }, // 367 (2 6 3 5) { 5.111111f, 6.444445f, 2.222222f, 0.035714f }, // 368 (2 6 4 4) { 5.222222f, 5.888889f, 2.444444f, 0.040359f }, // 369 (2 6 5 3) { 5.333333f, 5.333333f, 2.666667f, 0.046875f }, // 370 (2 6 6 2) { 5.444445f, 4.777778f, 2.888889f, 0.056604f }, // 371 (2 6 7 1) { 5.555555f, 4.222222f, 3.111111f, 0.072581f }, // 372 (2 6 8 0) { 5.111111f, 7.777778f, 1.555556f, 0.026786f }, // 373 (2 7 0 7) { 5.222222f, 7.222222f, 1.777778f, 0.028939f }, // 374 (2 7 1 6) { 5.333333f, 6.666667f, 2.000000f, 0.031690f }, // 375 (2 7 2 5) { 5.444445f, 6.111111f, 2.222222f, 0.035294f }, // 376 (2 7 3 4) { 5.555555f, 5.555555f, 2.444444f, 0.040179f }, // 377 (2 7 4 3) { 5.666667f, 5.000000f, 2.666667f, 0.047120f }, // 378 (2 7 5 2) { 5.777778f, 4.444445f, 2.888889f, 0.057692f }, // 379 (2 7 6 1) { 5.888889f, 3.888889f, 3.111111f, 0.075630f }, // 380 (2 7 7 0) { 5.555555f, 6.888889f, 1.777778f, 0.028481f }, // 381 (2 8 0 6) { 5.666667f, 6.333333f, 2.000000f, 0.031359f }, // 382 (2 8 1 5) { 5.777778f, 5.777778f, 2.222222f, 0.035156f }, // 383 (2 8 2 4) { 5.888889f, 5.222222f, 2.444444f, 0.040359f }, // 384 (2 8 3 3) { 6.000000f, 4.666667f, 2.666667f, 0.047872f }, // 385 (2 8 4 2) { 6.111111f, 4.111111f, 2.888889f, 0.059603f }, // 386 (2 8 5 1) { 6.222222f, 3.555556f, 3.111111f, 0.080357f }, // 387 (2 8 6 0) { 6.000000f, 6.000000f, 2.000000f, 0.031250f }, // 388 (2 9 0 5) { 6.111111f, 5.444445f, 2.222222f, 0.035294f }, // 389 (2 9 1 4) { 6.222222f, 4.888889f, 2.444444f, 0.040909f }, // 390 (2 9 2 3) { 6.333333f, 4.333333f, 2.666667f, 0.049180f }, // 391 (2 9 3 2) { 6.444445f, 3.777778f, 2.888889f, 0.062500f }, // 392 (2 9 4 1) { 6.555556f, 3.222222f, 3.111111f, 0.087379f }, // 393 (2 9 5 0) { 6.444445f, 5.111111f, 2.222222f, 0.035714f }, // 394 (2 10 0 4) { 6.555556f, 4.555555f, 2.444444f, 0.041860f }, // 395 (2 10 1 3) { 6.666667f, 4.000000f, 2.666667f, 0.051136f }, // 396 (2 10 2 2) { 6.777778f, 3.444444f, 2.888889f, 0.066667f }, // 397 (2 10 3 1) { 6.888889f, 2.888889f, 3.111111f, 0.097826f }, // 398 (2 10 4 0) { 6.888889f, 4.222222f, 2.444444f, 0.043269f }, // 399 (2 11 0 3) { 7.000000f, 3.666667f, 2.666667f, 0.053892f }, // 400 (2 11 1 2) { 7.111111f, 3.111111f, 2.888889f, 0.072581f }, // 401 (2 11 2 1) { 7.222222f, 2.555556f, 3.111111f, 0.113924f }, // 402 (2 11 3 0) { 7.333333f, 3.333333f, 2.666667f, 0.057692f }, // 403 (2 12 0 2) { 7.444445f, 2.777778f, 2.888889f, 0.081081f }, // 404 (2 12 1 1) { 7.555556f, 2.222222f, 3.111111f, 0.140625f }, // 405 (2 12 2 0) { 7.777778f, 2.444444f, 2.888889f, 0.093750f }, // 406 (2 13 0 1) { 7.888889f, 1.888889f, 3.111111f, 0.191489f }, // 407 (2 13 1 0) { 8.222222f, 1.555556f, 3.111111f, 0.321429f }, // 408 (2 14 0 0) { 3.000000f, 13.000000f, 0.000000f, 0.025641f }, // 409 (3 0 0 13) { 3.111111f, 12.444445f, 0.222222f, 0.025862f }, // 410 (3 0 1 12) { 3.222222f, 11.888889f, 0.444444f, 0.026239f }, // 411 (3 0 2 11) { 3.333333f, 11.333333f, 0.666667f, 0.026786f }, // 412 (3 0 3 10) { 3.444444f, 10.777778f, 0.888889f, 0.027523f }, // 413 (3 0 4 9) { 3.555556f, 10.222222f, 1.111111f, 0.028481f }, // 414 (3 0 5 8) { 3.666667f, 9.666667f, 1.333333f, 0.029703f }, // 415 (3 0 6 7) { 3.777778f, 9.111111f, 1.555556f, 0.031250f }, // 416 (3 0 7 6) { 3.888889f, 8.555555f, 1.777778f, 0.033210f }, // 417 (3 0 8 5) { 4.000000f, 8.000000f, 2.000000f, 0.035714f }, // 418 (3 0 9 4) { 4.111111f, 7.444445f, 2.222222f, 0.038961f }, // 419 (3 0 10 3) { 4.222222f, 6.888889f, 2.444444f, 0.043269f }, // 420 (3 0 11 2) { 4.333333f, 6.333333f, 2.666667f, 0.049180f }, // 421 (3 0 12 1) { 4.444445f, 5.777778f, 2.888889f, 0.057692f }, // 422 (3 0 13 0) { 3.444444f, 12.111111f, 0.222222f, 0.024000f }, // 423 (3 1 0 12) { 3.555556f, 11.555555f, 0.444444f, 0.024457f }, // 424 (3 1 1 11) { 3.666667f, 11.000000f, 0.666667f, 0.025070f }, // 425 (3 1 2 10) { 3.777778f, 10.444445f, 0.888889f, 0.025862f }, // 426 (3 1 3 9) { 3.888889f, 9.888889f, 1.111111f, 0.026866f }, // 427 (3 1 4 8) { 4.000000f, 9.333333f, 1.333333f, 0.028125f }, // 428 (3 1 5 7) { 4.111111f, 8.777778f, 1.555556f, 0.029703f }, // 429 (3 1 6 6) { 4.222222f, 8.222222f, 1.777778f, 0.031690f }, // 430 (3 1 7 5) { 4.333333f, 7.666667f, 2.000000f, 0.034221f }, // 431 (3 1 8 4) { 4.444445f, 7.111111f, 2.222222f, 0.037500f }, // 432 (3 1 9 3) { 4.555555f, 6.555556f, 2.444444f, 0.041860f }, // 433 (3 1 10 2) { 4.666667f, 6.000000f, 2.666667f, 0.047872f }, // 434 (3 1 11 1) { 4.777778f, 5.444445f, 2.888889f, 0.056604f }, // 435 (3 1 12 0) { 3.888889f, 11.222222f, 0.444444f, 0.023018f }, // 436 (3 2 0 11) { 4.000000f, 10.666667f, 0.666667f, 0.023684f }, // 437 (3 2 1 10) { 4.111111f, 10.111111f, 0.888889f, 0.024523f }, // 438 (3 2 2 9) { 4.222222f, 9.555555f, 1.111111f, 0.025568f }, // 439 (3 2 3 8) { 4.333333f, 9.000000f, 1.333333f, 0.026866f }, // 440 (3 2 4 7) { 4.444445f, 8.444445f, 1.555556f, 0.028481f }, // 441 (3 2 5 6) { 4.555555f, 7.888889f, 1.777778f, 0.030508f }, // 442 (3 2 6 5) { 4.666667f, 7.333333f, 2.000000f, 0.033088f }, // 443 (3 2 7 4) { 4.777778f, 6.777778f, 2.222222f, 0.036437f }, // 444 (3 2 8 3) { 4.888889f, 6.222222f, 2.444444f, 0.040909f }, // 445 (3 2 9 2) { 5.000000f, 5.666667f, 2.666667f, 0.047120f }, // 446 (3 2 10 1) { 5.111111f, 5.111111f, 2.888889f, 0.056250f }, // 447 (3 2 11 0) { 4.333333f, 10.333333f, 0.666667f, 0.022556f }, // 448 (3 3 0 10) { 4.444445f, 9.777778f, 0.888889f, 0.023438f }, // 449 (3 3 1 9) { 4.555555f, 9.222222f, 1.111111f, 0.024523f }, // 450 (3 3 2 8) { 4.666667f, 8.666667f, 1.333333f, 0.025862f }, // 451 (3 3 3 7) { 4.777778f, 8.111111f, 1.555556f, 0.027523f }, // 452 (3 3 4 6) { 4.888889f, 7.555555f, 1.777778f, 0.029605f }, // 453 (3 3 5 5) { 5.000000f, 7.000000f, 2.000000f, 0.032258f }, // 454 (3 3 6 4) { 5.111111f, 6.444445f, 2.222222f, 0.035714f }, // 455 (3 3 7 3) { 5.222222f, 5.888889f, 2.444444f, 0.040359f }, // 456 (3 3 8 2) { 5.333333f, 5.333333f, 2.666667f, 0.046875f }, // 457 (3 3 9 1) { 5.444445f, 4.777778f, 2.888889f, 0.056604f }, // 458 (3 3 10 0) { 4.777778f, 9.444445f, 0.888889f, 0.022556f }, // 459 (3 4 0 9) { 4.888889f, 8.888889f, 1.111111f, 0.023684f }, // 460 (3 4 1 8) { 5.000000f, 8.333333f, 1.333333f, 0.025070f }, // 461 (3 4 2 7) { 5.111111f, 7.777778f, 1.555556f, 0.026786f }, // 462 (3 4 3 6) { 5.222222f, 7.222222f, 1.777778f, 0.028939f }, // 463 (3 4 4 5) { 5.333333f, 6.666667f, 2.000000f, 0.031690f }, // 464 (3 4 5 4) { 5.444445f, 6.111111f, 2.222222f, 0.035294f }, // 465 (3 4 6 3) { 5.555555f, 5.555555f, 2.444444f, 0.040179f }, // 466 (3 4 7 2) { 5.666667f, 5.000000f, 2.666667f, 0.047120f }, // 467 (3 4 8 1) { 5.777778f, 4.444445f, 2.888889f, 0.057692f }, // 468 (3 4 9 0) { 5.222222f, 8.555555f, 1.111111f, 0.023018f }, // 469 (3 5 0 8) { 5.333333f, 8.000000f, 1.333333f, 0.024457f }, // 470 (3 5 1 7) { 5.444445f, 7.444445f, 1.555556f, 0.026239f }, // 471 (3 5 2 6) { 5.555555f, 6.888889f, 1.777778f, 0.028481f }, // 472 (3 5 3 5) { 5.666667f, 6.333333f, 2.000000f, 0.031359f }, // 473 (3 5 4 4) { 5.777778f, 5.777778f, 2.222222f, 0.035156f }, // 474 (3 5 5 3) { 5.888889f, 5.222222f, 2.444444f, 0.040359f }, // 475 (3 5 6 2) { 6.000000f, 4.666667f, 2.666667f, 0.047872f }, // 476 (3 5 7 1) { 6.111111f, 4.111111f, 2.888889f, 0.059603f }, // 477 (3 5 8 0) { 5.666667f, 7.666667f, 1.333333f, 0.024000f }, // 478 (3 6 0 7) { 5.777778f, 7.111111f, 1.555556f, 0.025862f }, // 479 (3 6 1 6) { 5.888889f, 6.555555f, 1.777778f, 0.028213f }, // 480 (3 6 2 5) { 6.000000f, 6.000000f, 2.000000f, 0.031250f }, // 481 (3 6 3 4) { 6.111111f, 5.444445f, 2.222222f, 0.035294f }, // 482 (3 6 4 3) { 6.222222f, 4.888889f, 2.444444f, 0.040909f }, // 483 (3 6 5 2) { 6.333333f, 4.333333f, 2.666667f, 0.049180f }, // 484 (3 6 6 1) { 6.444445f, 3.777778f, 2.888889f, 0.062500f }, // 485 (3 6 7 0) { 6.111111f, 6.777778f, 1.555556f, 0.025641f }, // 486 (3 7 0 6) { 6.222222f, 6.222222f, 1.777778f, 0.028125f }, // 487 (3 7 1 5) { 6.333333f, 5.666667f, 2.000000f, 0.031359f }, // 488 (3 7 2 4) { 6.444445f, 5.111111f, 2.222222f, 0.035714f }, // 489 (3 7 3 3) { 6.555555f, 4.555555f, 2.444444f, 0.041860f }, // 490 (3 7 4 2) { 6.666667f, 4.000000f, 2.666667f, 0.051136f }, // 491 (3 7 5 1) { 6.777778f, 3.444444f, 2.888889f, 0.066667f }, // 492 (3 7 6 0) { 6.555555f, 5.888889f, 1.777778f, 0.028213f }, // 493 (3 8 0 5) { 6.666667f, 5.333333f, 2.000000f, 0.031690f }, // 494 (3 8 1 4) { 6.777778f, 4.777778f, 2.222222f, 0.036437f }, // 495 (3 8 2 3) { 6.888889f, 4.222222f, 2.444444f, 0.043269f }, // 496 (3 8 3 2) { 7.000000f, 3.666667f, 2.666667f, 0.053892f }, // 497 (3 8 4 1) { 7.111111f, 3.111111f, 2.888889f, 0.072581f }, // 498 (3 8 5 0) { 7.000000f, 5.000000f, 2.000000f, 0.032258f }, // 499 (3 9 0 4) { 7.111111f, 4.444445f, 2.222222f, 0.037500f }, // 500 (3 9 1 3) { 7.222222f, 3.888889f, 2.444444f, 0.045226f }, // 501 (3 9 2 2) { 7.333333f, 3.333333f, 2.666667f, 0.057692f }, // 502 (3 9 3 1) { 7.444445f, 2.777778f, 2.888889f, 0.081081f }, // 503 (3 9 4 0) { 7.444445f, 4.111111f, 2.222222f, 0.038961f }, // 504 (3 10 0 3) { 7.555556f, 3.555556f, 2.444444f, 0.047872f }, // 505 (3 10 1 2) { 7.666667f, 3.000000f, 2.666667f, 0.062937f }, // 506 (3 10 2 1) { 7.777778f, 2.444444f, 2.888889f, 0.093750f }, // 507 (3 10 3 0) { 7.888889f, 3.222222f, 2.444444f, 0.051429f }, // 508 (3 11 0 2) { 8.000000f, 2.666667f, 2.666667f, 0.070313f }, // 509 (3 11 1 1) { 8.111111f, 2.111111f, 2.888889f, 0.113924f }, // 510 (3 11 2 0) { 8.333333f, 2.333333f, 2.666667f, 0.081081f }, // 511 (3 12 0 1) { 8.444445f, 1.777778f, 2.888889f, 0.150000f }, // 512 (3 12 1 0) { 8.777778f, 1.444444f, 2.888889f, 0.230769f }, // 513 (3 13 0 0) { 4.000000f, 12.000000f, 0.000000f, 0.020833f }, // 514 (4 0 0 12) { 4.111111f, 11.444445f, 0.222222f, 0.021277f }, // 515 (4 0 1 11) { 4.222222f, 10.888889f, 0.444444f, 0.021845f }, // 516 (4 0 2 10) { 4.333333f, 10.333333f, 0.666667f, 0.022556f }, // 517 (4 0 3 9) { 4.444445f, 9.777778f, 0.888889f, 0.023438f }, // 518 (4 0 4 8) { 4.555555f, 9.222222f, 1.111111f, 0.024523f }, // 519 (4 0 5 7) { 4.666667f, 8.666667f, 1.333333f, 0.025862f }, // 520 (4 0 6 6) { 4.777778f, 8.111111f, 1.555556f, 0.027523f }, // 521 (4 0 7 5) { 4.888889f, 7.555555f, 1.777778f, 0.029605f }, // 522 (4 0 8 4) { 5.000000f, 7.000000f, 2.000000f, 0.032258f }, // 523 (4 0 9 3) { 5.111111f, 6.444445f, 2.222222f, 0.035714f }, // 524 (4 0 10 2) { 5.222222f, 5.888889f, 2.444444f, 0.040359f }, // 525 (4 0 11 1) { 5.333333f, 5.333333f, 2.666667f, 0.046875f }, // 526 (4 0 12 0) { 4.444445f, 11.111111f, 0.222222f, 0.020270f }, // 527 (4 1 0 11) { 4.555555f, 10.555555f, 0.444444f, 0.020882f }, // 528 (4 1 1 10) { 4.666667f, 10.000000f, 0.666667f, 0.021635f }, // 529 (4 1 2 9) { 4.777778f, 9.444445f, 0.888889f, 0.022556f }, // 530 (4 1 3 8) { 4.888889f, 8.888889f, 1.111111f, 0.023684f }, // 531 (4 1 4 7) { 5.000000f, 8.333333f, 1.333333f, 0.025070f }, // 532 (4 1 5 6) { 5.111111f, 7.777778f, 1.555556f, 0.026786f }, // 533 (4 1 6 5) { 5.222222f, 7.222222f, 1.777778f, 0.028939f }, // 534 (4 1 7 4) { 5.333333f, 6.666667f, 2.000000f, 0.031690f }, // 535 (4 1 8 3) { 5.444445f, 6.111111f, 2.222222f, 0.035294f }, // 536 (4 1 9 2) { 5.555555f, 5.555556f, 2.444444f, 0.040179f }, // 537 (4 1 10 1) { 5.666667f, 5.000000f, 2.666667f, 0.047120f }, // 538 (4 1 11 0) { 4.888889f, 10.222222f, 0.444444f, 0.020089f }, // 539 (4 2 0 10) { 5.000000f, 9.666667f, 0.666667f, 0.020882f }, // 540 (4 2 1 9) { 5.111111f, 9.111111f, 0.888889f, 0.021845f }, // 541 (4 2 2 8) { 5.222222f, 8.555555f, 1.111111f, 0.023018f }, // 542 (4 2 3 7) { 5.333333f, 8.000000f, 1.333333f, 0.024457f }, // 543 (4 2 4 6) { 5.444445f, 7.444445f, 1.555556f, 0.026239f }, // 544 (4 2 5 5) { 5.555555f, 6.888889f, 1.777778f, 0.028481f }, // 545 (4 2 6 4) { 5.666667f, 6.333333f, 2.000000f, 0.031359f }, // 546 (4 2 7 3) { 5.777778f, 5.777778f, 2.222222f, 0.035156f }, // 547 (4 2 8 2) { 5.888889f, 5.222222f, 2.444444f, 0.040359f }, // 548 (4 2 9 1) { 6.000000f, 4.666667f, 2.666667f, 0.047872f }, // 549 (4 2 10 0) { 5.333333f, 9.333333f, 0.666667f, 0.020270f }, // 550 (4 3 0 9) { 5.444445f, 8.777778f, 0.888889f, 0.021277f }, // 551 (4 3 1 8) { 5.555555f, 8.222222f, 1.111111f, 0.022500f }, // 552 (4 3 2 7) { 5.666667f, 7.666667f, 1.333333f, 0.024000f }, // 553 (4 3 3 6) { 5.777778f, 7.111111f, 1.555556f, 0.025862f }, // 554 (4 3 4 5) { 5.888889f, 6.555555f, 1.777778f, 0.028213f }, // 555 (4 3 5 4) { 6.000000f, 6.000000f, 2.000000f, 0.031250f }, // 556 (4 3 6 3) { 6.111111f, 5.444445f, 2.222222f, 0.035294f }, // 557 (4 3 7 2) { 6.222222f, 4.888889f, 2.444444f, 0.040909f }, // 558 (4 3 8 1) { 6.333333f, 4.333333f, 2.666667f, 0.049180f }, // 559 (4 3 9 0) { 5.777778f, 8.444445f, 0.888889f, 0.020833f }, // 560 (4 4 0 8) { 5.888889f, 7.888889f, 1.111111f, 0.022113f }, // 561 (4 4 1 7) { 6.000000f, 7.333333f, 1.333333f, 0.023684f }, // 562 (4 4 2 6) { 6.111111f, 6.777778f, 1.555556f, 0.025641f }, // 563 (4 4 3 5) { 6.222222f, 6.222222f, 1.777778f, 0.028125f }, // 564 (4 4 4 4) { 6.333333f, 5.666667f, 2.000000f, 0.031359f }, // 565 (4 4 5 3) { 6.444445f, 5.111111f, 2.222222f, 0.035714f }, // 566 (4 4 6 2) { 6.555555f, 4.555555f, 2.444444f, 0.041860f }, // 567 (4 4 7 1) { 6.666667f, 4.000000f, 2.666667f, 0.051136f }, // 568 (4 4 8 0) { 6.222222f, 7.555555f, 1.111111f, 0.021845f }, // 569 (4 5 0 7) { 6.333333f, 7.000000f, 1.333333f, 0.023499f }, // 570 (4 5 1 6) { 6.444445f, 6.444445f, 1.555556f, 0.025568f }, // 571 (4 5 2 5) { 6.555555f, 5.888889f, 1.777778f, 0.028213f }, // 572 (4 5 3 4) { 6.666667f, 5.333333f, 2.000000f, 0.031690f }, // 573 (4 5 4 3) { 6.777778f, 4.777778f, 2.222222f, 0.036437f }, // 574 (4 5 5 2) { 6.888889f, 4.222222f, 2.444444f, 0.043269f }, // 575 (4 5 6 1) { 7.000000f, 3.666667f, 2.666667f, 0.053892f }, // 576 (4 5 7 0) { 6.666667f, 6.666667f, 1.333333f, 0.023438f }, // 577 (4 6 0 6) { 6.777778f, 6.111111f, 1.555556f, 0.025641f }, // 578 (4 6 1 5) { 6.888889f, 5.555555f, 1.777778f, 0.028481f }, // 579 (4 6 2 4) { 7.000000f, 5.000000f, 2.000000f, 0.032258f }, // 580 (4 6 3 3) { 7.111111f, 4.444445f, 2.222222f, 0.037500f }, // 581 (4 6 4 2) { 7.222222f, 3.888889f, 2.444444f, 0.045226f }, // 582 (4 6 5 1) { 7.333333f, 3.333333f, 2.666667f, 0.057692f }, // 583 (4 6 6 0) { 7.111111f, 5.777778f, 1.555556f, 0.025862f }, // 584 (4 7 0 5) { 7.222222f, 5.222222f, 1.777778f, 0.028939f }, // 585 (4 7 1 4) { 7.333333f, 4.666667f, 2.000000f, 0.033088f }, // 586 (4 7 2 3) { 7.444445f, 4.111111f, 2.222222f, 0.038961f }, // 587 (4 7 3 2) { 7.555555f, 3.555556f, 2.444444f, 0.047872f }, // 588 (4 7 4 1) { 7.666667f, 3.000000f, 2.666667f, 0.062937f }, // 589 (4 7 5 0) { 7.555555f, 4.888889f, 1.777778f, 0.029605f }, // 590 (4 8 0 4) { 7.666667f, 4.333333f, 2.000000f, 0.034221f }, // 591 (4 8 1 3) { 7.777778f, 3.777778f, 2.222222f, 0.040909f }, // 592 (4 8 2 2) { 7.888889f, 3.222222f, 2.444444f, 0.051429f }, // 593 (4 8 3 1) { 8.000000f, 2.666667f, 2.666667f, 0.070313f }, // 594 (4 8 4 0) { 8.000000f, 4.000000f, 2.000000f, 0.035714f }, // 595 (4 9 0 3) { 8.111111f, 3.444444f, 2.222222f, 0.043478f }, // 596 (4 9 1 2) { 8.222222f, 2.888889f, 2.444444f, 0.056250f }, // 597 (4 9 2 1) { 8.333333f, 2.333333f, 2.666667f, 0.081081f }, // 598 (4 9 3 0) { 8.444445f, 3.111111f, 2.222222f, 0.046875f }, // 599 (4 10 0 2) { 8.555555f, 2.555556f, 2.444444f, 0.062937f }, // 600 (4 10 1 1) { 8.666667f, 2.000000f, 2.666667f, 0.097826f }, // 601 (4 10 2 0) { 8.888889f, 2.222222f, 2.444444f, 0.072581f }, // 602 (4 11 0 1) { 9.000000f, 1.666667f, 2.666667f, 0.126761f }, // 603 (4 11 1 0) { 9.333333f, 1.333333f, 2.666667f, 0.187500f }, // 604 (4 12 0 0) { 5.000000f, 11.000000f, 0.000000f, 0.018182f }, // 605 (5 0 0 11) { 5.111111f, 10.444445f, 0.222222f, 0.018750f }, // 606 (5 0 1 10) { 5.222222f, 9.888889f, 0.444444f, 0.019438f }, // 607 (5 0 2 9) { 5.333333f, 9.333333f, 0.666667f, 0.020270f }, // 608 (5 0 3 8) { 5.444445f, 8.777778f, 0.888889f, 0.021277f }, // 609 (5 0 4 7) { 5.555555f, 8.222222f, 1.111111f, 0.022500f }, // 610 (5 0 5 6) { 5.666667f, 7.666667f, 1.333333f, 0.024000f }, // 611 (5 0 6 5) { 5.777778f, 7.111111f, 1.555556f, 0.025862f }, // 612 (5 0 7 4) { 5.888889f, 6.555555f, 1.777778f, 0.028213f }, // 613 (5 0 8 3) { 6.000000f, 6.000000f, 2.000000f, 0.031250f }, // 614 (5 0 9 2) { 6.111111f, 5.444445f, 2.222222f, 0.035294f }, // 615 (5 0 10 1) { 6.222222f, 4.888889f, 2.444444f, 0.040909f }, // 616 (5 0 11 0) { 5.444445f, 10.111111f, 0.222222f, 0.018182f }, // 617 (5 1 0 10) { 5.555555f, 9.555555f, 0.444444f, 0.018908f }, // 618 (5 1 1 9) { 5.666667f, 9.000000f, 0.666667f, 0.019780f }, // 619 (5 1 2 8) { 5.777778f, 8.444445f, 0.888889f, 0.020833f }, // 620 (5 1 3 7) { 5.888889f, 7.888889f, 1.111111f, 0.022113f }, // 621 (5 1 4 6) { 6.000000f, 7.333333f, 1.333333f, 0.023684f }, // 622 (5 1 5 5) { 6.111111f, 6.777778f, 1.555556f, 0.025641f }, // 623 (5 1 6 4) { 6.222222f, 6.222222f, 1.777778f, 0.028125f }, // 624 (5 1 7 3) { 6.333333f, 5.666667f, 2.000000f, 0.031359f }, // 625 (5 1 8 2) { 6.444445f, 5.111111f, 2.222222f, 0.035714f }, // 626 (5 1 9 1) { 6.555555f, 4.555556f, 2.444444f, 0.041860f }, // 627 (5 1 10 0) { 5.888889f, 9.222222f, 0.444444f, 0.018480f }, // 628 (5 2 0 9) { 6.000000f, 8.666667f, 0.666667f, 0.019397f }, // 629 (5 2 1 8) { 6.111111f, 8.111111f, 0.888889f, 0.020501f }, // 630 (5 2 2 7) { 6.222222f, 7.555555f, 1.111111f, 0.021845f }, // 631 (5 2 3 6) { 6.333333f, 7.000000f, 1.333333f, 0.023499f }, // 632 (5 2 4 5) { 6.444445f, 6.444445f, 1.555556f, 0.025568f }, // 633 (5 2 5 4) { 6.555555f, 5.888889f, 1.777778f, 0.028213f }, // 634 (5 2 6 3) { 6.666667f, 5.333333f, 2.000000f, 0.031690f }, // 635 (5 2 7 2) { 6.777778f, 4.777778f, 2.222222f, 0.036437f }, // 636 (5 2 8 1) { 6.888889f, 4.222222f, 2.444444f, 0.043269f }, // 637 (5 2 9 0) { 6.333333f, 8.333333f, 0.666667f, 0.019108f }, // 638 (5 3 0 8) { 6.444445f, 7.777778f, 0.888889f, 0.020270f }, // 639 (5 3 1 7) { 6.555555f, 7.222222f, 1.111111f, 0.021687f }, // 640 (5 3 2 6) { 6.666667f, 6.666667f, 1.333333f, 0.023438f }, // 641 (5 3 3 5) { 6.777778f, 6.111111f, 1.555556f, 0.025641f }, // 642 (5 3 4 4) { 6.888889f, 5.555555f, 1.777778f, 0.028481f }, // 643 (5 3 5 3) { 7.000000f, 5.000000f, 2.000000f, 0.032258f }, // 644 (5 3 6 2) { 7.111111f, 4.444445f, 2.222222f, 0.037500f }, // 645 (5 3 7 1) { 7.222222f, 3.888889f, 2.444444f, 0.045226f }, // 646 (5 3 8 0) { 6.777778f, 7.444445f, 0.888889f, 0.020134f }, // 647 (5 4 0 7) { 6.888889f, 6.888889f, 1.111111f, 0.021635f }, // 648 (5 4 1 6) { 7.000000f, 6.333333f, 1.333333f, 0.023499f }, // 649 (5 4 2 5) { 7.111111f, 5.777778f, 1.555556f, 0.025862f }, // 650 (5 4 3 4) { 7.222222f, 5.222222f, 1.777778f, 0.028939f }, // 651 (5 4 4 3) { 7.333333f, 4.666667f, 2.000000f, 0.033088f }, // 652 (5 4 5 2) { 7.444445f, 4.111111f, 2.222222f, 0.038961f }, // 653 (5 4 6 1) { 7.555555f, 3.555556f, 2.444444f, 0.047872f }, // 654 (5 4 7 0) { 7.222222f, 6.555555f, 1.111111f, 0.021687f }, // 655 (5 5 0 6) { 7.333333f, 6.000000f, 1.333333f, 0.023684f }, // 656 (5 5 1 5) { 7.444445f, 5.444445f, 1.555556f, 0.026239f }, // 657 (5 5 2 4) { 7.555555f, 4.888889f, 1.777778f, 0.029605f }, // 658 (5 5 3 3) { 7.666667f, 4.333333f, 2.000000f, 0.034221f }, // 659 (5 5 4 2) { 7.777778f, 3.777778f, 2.222222f, 0.040909f }, // 660 (5 5 5 1) { 7.888889f, 3.222222f, 2.444444f, 0.051429f }, // 661 (5 5 6 0) { 7.666667f, 5.666667f, 1.333333f, 0.024000f }, // 662 (5 6 0 5) { 7.777778f, 5.111111f, 1.555556f, 0.026786f }, // 663 (5 6 1 4) { 7.888889f, 4.555555f, 1.777778f, 0.030508f }, // 664 (5 6 2 3) { 8.000000f, 4.000000f, 2.000000f, 0.035714f }, // 665 (5 6 3 2) { 8.111111f, 3.444444f, 2.222222f, 0.043478f }, // 666 (5 6 4 1) { 8.222222f, 2.888889f, 2.444444f, 0.056250f }, // 667 (5 6 5 0) { 8.111111f, 4.777778f, 1.555556f, 0.027523f }, // 668 (5 7 0 4) { 8.222222f, 4.222222f, 1.777778f, 0.031690f }, // 669 (5 7 1 3) { 8.333333f, 3.666667f, 2.000000f, 0.037657f }, // 670 (5 7 2 2) { 8.444445f, 3.111111f, 2.222222f, 0.046875f }, // 671 (5 7 3 1) { 8.555555f, 2.555556f, 2.444444f, 0.062937f }, // 672 (5 7 4 0) { 8.555555f, 3.888889f, 1.777778f, 0.033210f }, // 673 (5 8 0 3) { 8.666667f, 3.333333f, 2.000000f, 0.040179f }, // 674 (5 8 1 2) { 8.777778f, 2.777778f, 2.222222f, 0.051429f }, // 675 (5 8 2 1) { 8.888889f, 2.222222f, 2.444444f, 0.072581f }, // 676 (5 8 3 0) { 9.000000f, 3.000000f, 2.000000f, 0.043478f }, // 677 (5 9 0 2) { 9.111111f, 2.444444f, 2.222222f, 0.057692f }, // 678 (5 9 1 1) { 9.222222f, 1.888889f, 2.444444f, 0.087379f }, // 679 (5 9 2 0) { 9.444445f, 2.111111f, 2.222222f, 0.066667f }, // 680 (5 10 0 1) { 9.555555f, 1.555556f, 2.444444f, 0.112500f }, // 681 (5 10 1 0) { 9.888889f, 1.222222f, 2.444444f, 0.163636f }, // 682 (5 11 0 0) { 6.000000f, 10.000000f, 0.000000f, 0.016667f }, // 683 (6 0 0 10) { 6.111111f, 9.444445f, 0.222222f, 0.017341f }, // 684 (6 0 1 9) { 6.222222f, 8.888889f, 0.444444f, 0.018145f }, // 685 (6 0 2 8) { 6.333333f, 8.333333f, 0.666667f, 0.019108f }, // 686 (6 0 3 7) { 6.444445f, 7.777778f, 0.888889f, 0.020270f }, // 687 (6 0 4 6) { 6.555555f, 7.222222f, 1.111111f, 0.021687f }, // 688 (6 0 5 5) { 6.666667f, 6.666667f, 1.333333f, 0.023438f }, // 689 (6 0 6 4) { 6.777778f, 6.111111f, 1.555556f, 0.025641f }, // 690 (6 0 7 3) { 6.888889f, 5.555555f, 1.777778f, 0.028481f }, // 691 (6 0 8 2) { 7.000000f, 5.000000f, 2.000000f, 0.032258f }, // 692 (6 0 9 1) { 7.111111f, 4.444445f, 2.222222f, 0.037500f }, // 693 (6 0 10 0) { 6.444445f, 9.111111f, 0.222222f, 0.017045f }, // 694 (6 1 0 9) { 6.555555f, 8.555555f, 0.444444f, 0.017893f }, // 695 (6 1 1 8) { 6.666667f, 8.000000f, 0.666667f, 0.018908f }, // 696 (6 1 2 7) { 6.777778f, 7.444445f, 0.888889f, 0.020134f }, // 697 (6 1 3 6) { 6.888889f, 6.888889f, 1.111111f, 0.021635f }, // 698 (6 1 4 5) { 7.000000f, 6.333333f, 1.333333f, 0.023499f }, // 699 (6 1 5 4) { 7.111111f, 5.777778f, 1.555556f, 0.025862f }, // 700 (6 1 6 3) { 7.222222f, 5.222222f, 1.777778f, 0.028939f }, // 701 (6 1 7 2) { 7.333333f, 4.666667f, 2.000000f, 0.033088f }, // 702 (6 1 8 1) { 7.444445f, 4.111111f, 2.222222f, 0.038961f }, // 703 (6 1 9 0) { 6.888889f, 8.222222f, 0.444444f, 0.017717f }, // 704 (6 2 0 8) { 7.000000f, 7.666667f, 0.666667f, 0.018789f }, // 705 (6 2 1 7) { 7.111111f, 7.111111f, 0.888889f, 0.020089f }, // 706 (6 2 2 6) { 7.222222f, 6.555555f, 1.111111f, 0.021687f }, // 707 (6 2 3 5) { 7.333333f, 6.000000f, 1.333333f, 0.023684f }, // 708 (6 2 4 4) { 7.444445f, 5.444445f, 1.555556f, 0.026239f }, // 709 (6 2 5 3) { 7.555555f, 4.888889f, 1.777778f, 0.029605f }, // 710 (6 2 6 2) { 7.666667f, 4.333333f, 2.000000f, 0.034221f }, // 711 (6 2 7 1) { 7.777778f, 3.777778f, 2.222222f, 0.040909f }, // 712 (6 2 8 0) { 7.333333f, 7.333333f, 0.666667f, 0.018750f }, // 713 (6 3 0 7) { 7.444445f, 6.777778f, 0.888889f, 0.020134f }, // 714 (6 3 1 6) { 7.555555f, 6.222222f, 1.111111f, 0.021845f }, // 715 (6 3 2 5) { 7.666667f, 5.666667f, 1.333333f, 0.024000f }, // 716 (6 3 3 4) { 7.777778f, 5.111111f, 1.555556f, 0.026786f }, // 717 (6 3 4 3) { 7.888889f, 4.555555f, 1.777778f, 0.030508f }, // 718 (6 3 5 2) { 8.000000f, 4.000000f, 2.000000f, 0.035714f }, // 719 (6 3 6 1) { 8.111111f, 3.444444f, 2.222222f, 0.043478f }, // 720 (6 3 7 0) { 7.777778f, 6.444445f, 0.888889f, 0.020270f }, // 721 (6 4 0 6) { 7.888889f, 5.888889f, 1.111111f, 0.022113f }, // 722 (6 4 1 5) { 8.000000f, 5.333333f, 1.333333f, 0.024457f }, // 723 (6 4 2 4) { 8.111111f, 4.777778f, 1.555556f, 0.027523f }, // 724 (6 4 3 3) { 8.222222f, 4.222222f, 1.777778f, 0.031690f }, // 725 (6 4 4 2) { 8.333333f, 3.666667f, 2.000000f, 0.037657f }, // 726 (6 4 5 1) { 8.444445f, 3.111111f, 2.222222f, 0.046875f }, // 727 (6 4 6 0) { 8.222222f, 5.555555f, 1.111111f, 0.022500f }, // 728 (6 5 0 5) { 8.333333f, 5.000000f, 1.333333f, 0.025070f }, // 729 (6 5 1 4) { 8.444445f, 4.444445f, 1.555556f, 0.028481f }, // 730 (6 5 2 3) { 8.555555f, 3.888889f, 1.777778f, 0.033210f }, // 731 (6 5 3 2) { 8.666667f, 3.333333f, 2.000000f, 0.040179f }, // 732 (6 5 4 1) { 8.777778f, 2.777778f, 2.222222f, 0.051429f }, // 733 (6 5 5 0) { 8.666667f, 4.666667f, 1.333333f, 0.025862f }, // 734 (6 6 0 4) { 8.777778f, 4.111111f, 1.555556f, 0.029703f }, // 735 (6 6 1 3) { 8.888889f, 3.555556f, 1.777778f, 0.035156f }, // 736 (6 6 2 2) { 9.000000f, 3.000000f, 2.000000f, 0.043478f }, // 737 (6 6 3 1) { 9.111111f, 2.444444f, 2.222222f, 0.057692f }, // 738 (6 6 4 0) { 9.111111f, 3.777778f, 1.555556f, 0.031250f }, // 739 (6 7 0 3) { 9.222222f, 3.222222f, 1.777778f, 0.037657f }, // 740 (6 7 1 2) { 9.333333f, 2.666667f, 2.000000f, 0.047872f }, // 741 (6 7 2 1) { 9.444445f, 2.111111f, 2.222222f, 0.066667f }, // 742 (6 7 3 0) { 9.555555f, 2.888889f, 1.777778f, 0.040909f }, // 743 (6 8 0 2) { 9.666667f, 2.333333f, 2.000000f, 0.053892f }, // 744 (6 8 1 1) { 9.777778f, 1.777778f, 2.222222f, 0.080357f }, // 745 (6 8 2 0) { 10.000000f, 2.000000f, 2.000000f, 0.062500f }, // 746 (6 9 0 1) { 10.111111f, 1.444444f, 2.222222f, 0.103448f }, // 747 (6 9 1 0) { 10.444445f, 1.111111f, 2.222222f, 0.150000f }, // 748 (6 10 0 0) { 7.000000f, 9.000000f, 0.000000f, 0.015873f }, // 749 (7 0 0 9) { 7.111111f, 8.444445f, 0.222222f, 0.016667f }, // 750 (7 0 1 8) { 7.222222f, 7.888889f, 0.444444f, 0.017613f }, // 751 (7 0 2 7) { 7.333333f, 7.333333f, 0.666667f, 0.018750f }, // 752 (7 0 3 6) { 7.444445f, 6.777778f, 0.888889f, 0.020134f }, // 753 (7 0 4 5) { 7.555555f, 6.222222f, 1.111111f, 0.021845f }, // 754 (7 0 5 4) { 7.666667f, 5.666667f, 1.333333f, 0.024000f }, // 755 (7 0 6 3) { 7.777778f, 5.111111f, 1.555556f, 0.026786f }, // 756 (7 0 7 2) { 7.888889f, 4.555555f, 1.777778f, 0.030508f }, // 757 (7 0 8 1) { 8.000000f, 4.000000f, 2.000000f, 0.035714f }, // 758 (7 0 9 0) { 7.444445f, 8.111111f, 0.222222f, 0.016575f }, // 759 (7 1 0 8) { 7.555555f, 7.555555f, 0.444444f, 0.017578f }, // 760 (7 1 1 7) { 7.666667f, 7.000000f, 0.666667f, 0.018789f }, // 761 (7 1 2 6) { 7.777778f, 6.444445f, 0.888889f, 0.020270f }, // 762 (7 1 3 5) { 7.888889f, 5.888889f, 1.111111f, 0.022113f }, // 763 (7 1 4 4) { 8.000000f, 5.333333f, 1.333333f, 0.024457f }, // 764 (7 1 5 3) { 8.111111f, 4.777778f, 1.555556f, 0.027523f }, // 765 (7 1 6 2) { 8.222222f, 4.222222f, 1.777778f, 0.031690f }, // 766 (7 1 7 1) { 8.333333f, 3.666667f, 2.000000f, 0.037657f }, // 767 (7 1 8 0) { 7.888889f, 7.222222f, 0.444444f, 0.017613f }, // 768 (7 2 0 7) { 8.000000f, 6.666667f, 0.666667f, 0.018908f }, // 769 (7 2 1 6) { 8.111111f, 6.111111f, 0.888889f, 0.020501f }, // 770 (7 2 2 5) { 8.222222f, 5.555555f, 1.111111f, 0.022500f }, // 771 (7 2 3 4) { 8.333333f, 5.000000f, 1.333333f, 0.025070f }, // 772 (7 2 4 3) { 8.444445f, 4.444445f, 1.555556f, 0.028481f }, // 773 (7 2 5 2) { 8.555555f, 3.888889f, 1.777778f, 0.033210f }, // 774 (7 2 6 1) { 8.666667f, 3.333333f, 2.000000f, 0.040179f }, // 775 (7 2 7 0) { 8.333333f, 6.333333f, 0.666667f, 0.019108f }, // 776 (7 3 0 6) { 8.444445f, 5.777778f, 0.888889f, 0.020833f }, // 777 (7 3 1 5) { 8.555555f, 5.222222f, 1.111111f, 0.023018f }, // 778 (7 3 2 4) { 8.666667f, 4.666667f, 1.333333f, 0.025862f }, // 779 (7 3 3 3) { 8.777778f, 4.111111f, 1.555556f, 0.029703f }, // 780 (7 3 4 2) { 8.888889f, 3.555556f, 1.777778f, 0.035156f }, // 781 (7 3 5 1) { 9.000000f, 3.000000f, 2.000000f, 0.043478f }, // 782 (7 3 6 0) { 8.777778f, 5.444445f, 0.888889f, 0.021277f }, // 783 (7 4 0 5) { 8.888889f, 4.888889f, 1.111111f, 0.023684f }, // 784 (7 4 1 4) { 9.000000f, 4.333333f, 1.333333f, 0.026866f }, // 785 (7 4 2 3) { 9.111111f, 3.777778f, 1.555556f, 0.031250f }, // 786 (7 4 3 2) { 9.222222f, 3.222222f, 1.777778f, 0.037657f }, // 787 (7 4 4 1) { 9.333333f, 2.666667f, 2.000000f, 0.047872f }, // 788 (7 4 5 0) { 9.222222f, 4.555555f, 1.111111f, 0.024523f }, // 789 (7 5 0 4) { 9.333333f, 4.000000f, 1.333333f, 0.028125f }, // 790 (7 5 1 3) { 9.444445f, 3.444444f, 1.555556f, 0.033210f }, // 791 (7 5 2 2) { 9.555555f, 2.888889f, 1.777778f, 0.040909f }, // 792 (7 5 3 1) { 9.666667f, 2.333333f, 2.000000f, 0.053892f }, // 793 (7 5 4 0) { 9.666667f, 3.666667f, 1.333333f, 0.029703f }, // 794 (7 6 0 3) { 9.777778f, 3.111111f, 1.555556f, 0.035714f }, // 795 (7 6 1 2) { 9.888889f, 2.555556f, 1.777778f, 0.045226f }, // 796 (7 6 2 1) { 10.000000f, 2.000000f, 2.000000f, 0.062500f }, // 797 (7 6 3 0) { 10.111111f, 2.777778f, 1.555556f, 0.038961f }, // 798 (7 7 0 2) { 10.222222f, 2.222222f, 1.777778f, 0.051136f }, // 799 (7 7 1 1) { 10.333333f, 1.666667f, 2.000000f, 0.075630f }, // 800 (7 7 2 0) { 10.555555f, 1.888889f, 1.777778f, 0.059603f }, // 801 (7 8 0 1) { 10.666667f, 1.333333f, 2.000000f, 0.097826f }, // 802 (7 8 1 0) { 11.000000f, 1.000000f, 2.000000f, 0.142857f }, // 803 (7 9 0 0) { 8.000000f, 8.000000f, 0.000000f, 0.015625f }, // 804 (8 0 0 8) { 8.111111f, 7.444445f, 0.222222f, 0.016575f }, // 805 (8 0 1 7) { 8.222222f, 6.888889f, 0.444444f, 0.017717f }, // 806 (8 0 2 6) { 8.333333f, 6.333333f, 0.666667f, 0.019108f }, // 807 (8 0 3 5) { 8.444445f, 5.777778f, 0.888889f, 0.020833f }, // 808 (8 0 4 4) { 8.555555f, 5.222222f, 1.111111f, 0.023018f }, // 809 (8 0 5 3) { 8.666667f, 4.666667f, 1.333333f, 0.025862f }, // 810 (8 0 6 2) { 8.777778f, 4.111111f, 1.555556f, 0.029703f }, // 811 (8 0 7 1) { 8.888889f, 3.555556f, 1.777778f, 0.035156f }, // 812 (8 0 8 0) { 8.444445f, 7.111111f, 0.222222f, 0.016667f }, // 813 (8 1 0 7) { 8.555555f, 6.555555f, 0.444444f, 0.017893f }, // 814 (8 1 1 6) { 8.666667f, 6.000000f, 0.666667f, 0.019397f }, // 815 (8 1 2 5) { 8.777778f, 5.444445f, 0.888889f, 0.021277f }, // 816 (8 1 3 4) { 8.888889f, 4.888889f, 1.111111f, 0.023684f }, // 817 (8 1 4 3) { 9.000000f, 4.333333f, 1.333333f, 0.026866f }, // 818 (8 1 5 2) { 9.111111f, 3.777778f, 1.555556f, 0.031250f }, // 819 (8 1 6 1) { 9.222222f, 3.222222f, 1.777778f, 0.037657f }, // 820 (8 1 7 0) { 8.888889f, 6.222222f, 0.444444f, 0.018145f }, // 821 (8 2 0 6) { 9.000000f, 5.666667f, 0.666667f, 0.019780f }, // 822 (8 2 1 5) { 9.111111f, 5.111111f, 0.888889f, 0.021845f }, // 823 (8 2 2 4) { 9.222222f, 4.555555f, 1.111111f, 0.024523f }, // 824 (8 2 3 3) { 9.333333f, 4.000000f, 1.333333f, 0.028125f }, // 825 (8 2 4 2) { 9.444445f, 3.444444f, 1.555556f, 0.033210f }, // 826 (8 2 5 1) { 9.555555f, 2.888889f, 1.777778f, 0.040909f }, // 827 (8 2 6 0) { 9.333333f, 5.333333f, 0.666667f, 0.020270f }, // 828 (8 3 0 5) { 9.444445f, 4.777778f, 0.888889f, 0.022556f }, // 829 (8 3 1 4) { 9.555555f, 4.222222f, 1.111111f, 0.025568f }, // 830 (8 3 2 3) { 9.666667f, 3.666667f, 1.333333f, 0.029703f }, // 831 (8 3 3 2) { 9.777778f, 3.111111f, 1.555556f, 0.035714f }, // 832 (8 3 4 1) { 9.888889f, 2.555556f, 1.777778f, 0.045226f }, // 833 (8 3 5 0) { 9.777778f, 4.444445f, 0.888889f, 0.023438f }, // 834 (8 4 0 4) { 9.888889f, 3.888889f, 1.111111f, 0.026866f }, // 835 (8 4 1 3) { 10.000000f, 3.333333f, 1.333333f, 0.031690f }, // 836 (8 4 2 2) { 10.111111f, 2.777778f, 1.555556f, 0.038961f }, // 837 (8 4 3 1) { 10.222222f, 2.222222f, 1.777778f, 0.051136f }, // 838 (8 4 4 0) { 10.222222f, 3.555556f, 1.111111f, 0.028481f }, // 839 (8 5 0 3) { 10.333333f, 3.000000f, 1.333333f, 0.034221f }, // 840 (8 5 1 2) { 10.444445f, 2.444444f, 1.555556f, 0.043269f }, // 841 (8 5 2 1) { 10.555555f, 1.888889f, 1.777778f, 0.059603f }, // 842 (8 5 3 0) { 10.666667f, 2.666667f, 1.333333f, 0.037500f }, // 843 (8 6 0 2) { 10.777778f, 2.111111f, 1.555556f, 0.049180f }, // 844 (8 6 1 1) { 10.888889f, 1.555556f, 1.777778f, 0.072581f }, // 845 (8 6 2 0) { 11.111111f, 1.777778f, 1.555556f, 0.057692f }, // 846 (8 7 0 1) { 11.222222f, 1.222222f, 1.777778f, 0.094737f }, // 847 (8 7 1 0) { 11.555555f, 0.888889f, 1.777778f, 0.140625f }, // 848 (8 8 0 0) { 9.000000f, 7.000000f, 0.000000f, 0.015873f }, // 849 (9 0 0 7) { 9.111111f, 6.444445f, 0.222222f, 0.017045f }, // 850 (9 0 1 6) { 9.222222f, 5.888889f, 0.444444f, 0.018480f }, // 851 (9 0 2 5) { 9.333333f, 5.333333f, 0.666667f, 0.020270f }, // 852 (9 0 3 4) { 9.444445f, 4.777778f, 0.888889f, 0.022556f }, // 853 (9 0 4 3) { 9.555555f, 4.222222f, 1.111111f, 0.025568f }, // 854 (9 0 5 2) { 9.666667f, 3.666667f, 1.333333f, 0.029703f }, // 855 (9 0 6 1) { 9.777778f, 3.111111f, 1.555556f, 0.035714f }, // 856 (9 0 7 0) { 9.444445f, 6.111111f, 0.222222f, 0.017341f }, // 857 (9 1 0 6) { 9.555555f, 5.555555f, 0.444444f, 0.018908f }, // 858 (9 1 1 5) { 9.666667f, 5.000000f, 0.666667f, 0.020882f }, // 859 (9 1 2 4) { 9.777778f, 4.444445f, 0.888889f, 0.023438f }, // 860 (9 1 3 3) { 9.888889f, 3.888889f, 1.111111f, 0.026866f }, // 861 (9 1 4 2) { 10.000000f, 3.333333f, 1.333333f, 0.031690f }, // 862 (9 1 5 1) { 10.111111f, 2.777778f, 1.555556f, 0.038961f }, // 863 (9 1 6 0) { 9.888889f, 5.222222f, 0.444444f, 0.019438f }, // 864 (9 2 0 5) { 10.000000f, 4.666667f, 0.666667f, 0.021635f }, // 865 (9 2 1 4) { 10.111111f, 4.111111f, 0.888889f, 0.024523f }, // 866 (9 2 2 3) { 10.222222f, 3.555556f, 1.111111f, 0.028481f }, // 867 (9 2 3 2) { 10.333333f, 3.000000f, 1.333333f, 0.034221f }, // 868 (9 2 4 1) { 10.444445f, 2.444444f, 1.555556f, 0.043269f }, // 869 (9 2 5 0) { 10.333333f, 4.333333f, 0.666667f, 0.022556f }, // 870 (9 3 0 4) { 10.444445f, 3.777778f, 0.888889f, 0.025862f }, // 871 (9 3 1 3) { 10.555555f, 3.222222f, 1.111111f, 0.030508f }, // 872 (9 3 2 2) { 10.666667f, 2.666667f, 1.333333f, 0.037500f }, // 873 (9 3 3 1) { 10.777778f, 2.111111f, 1.555556f, 0.049180f }, // 874 (9 3 4 0) { 10.777778f, 3.444444f, 0.888889f, 0.027523f }, // 875 (9 4 0 3) { 10.888889f, 2.888889f, 1.111111f, 0.033088f }, // 876 (9 4 1 2) { 11.000000f, 2.333333f, 1.333333f, 0.041860f }, // 877 (9 4 2 1) { 11.111111f, 1.777778f, 1.555556f, 0.057692f }, // 878 (9 4 3 0) { 11.222222f, 2.555556f, 1.111111f, 0.036437f }, // 879 (9 5 0 2) { 11.333333f, 2.000000f, 1.333333f, 0.047872f }, // 880 (9 5 1 1) { 11.444445f, 1.444444f, 1.555556f, 0.070866f }, // 881 (9 5 2 0) { 11.666667f, 1.666667f, 1.333333f, 0.056604f }, // 882 (9 6 0 1) { 11.777778f, 1.111111f, 1.555556f, 0.093750f }, // 883 (9 6 1 0) { 12.111111f, 0.777778f, 1.555556f, 0.142857f }, // 884 (9 7 0 0) { 10.000000f, 6.000000f, 0.000000f, 0.016667f }, // 885 (10 0 0 6) { 10.111111f, 5.444445f, 0.222222f, 0.018182f }, // 886 (10 0 1 5) { 10.222222f, 4.888889f, 0.444444f, 0.020089f }, // 887 (10 0 2 4) { 10.333333f, 4.333333f, 0.666667f, 0.022556f }, // 888 (10 0 3 3) { 10.444445f, 3.777778f, 0.888889f, 0.025862f }, // 889 (10 0 4 2) { 10.555555f, 3.222222f, 1.111111f, 0.030508f }, // 890 (10 0 5 1) { 10.666667f, 2.666667f, 1.333333f, 0.037500f }, // 891 (10 0 6 0) { 10.444445f, 5.111111f, 0.222222f, 0.018750f }, // 892 (10 1 0 5) { 10.555555f, 4.555555f, 0.444444f, 0.020882f }, // 893 (10 1 1 4) { 10.666667f, 4.000000f, 0.666667f, 0.023684f }, // 894 (10 1 2 3) { 10.777778f, 3.444444f, 0.888889f, 0.027523f }, // 895 (10 1 3 2) { 10.888889f, 2.888889f, 1.111111f, 0.033088f }, // 896 (10 1 4 1) { 11.000000f, 2.333333f, 1.333333f, 0.041860f }, // 897 (10 1 5 0) { 10.888889f, 4.222222f, 0.444444f, 0.021845f }, // 898 (10 2 0 4) { 11.000000f, 3.666667f, 0.666667f, 0.025070f }, // 899 (10 2 1 3) { 11.111111f, 3.111111f, 0.888889f, 0.029605f }, // 900 (10 2 2 2) { 11.222222f, 2.555556f, 1.111111f, 0.036437f }, // 901 (10 2 3 1) { 11.333333f, 2.000000f, 1.333333f, 0.047872f }, // 902 (10 2 4 0) { 11.333333f, 3.333333f, 0.666667f, 0.026786f }, // 903 (10 3 0 3) { 11.444445f, 2.777778f, 0.888889f, 0.032258f }, // 904 (10 3 1 2) { 11.555555f, 2.222222f, 1.111111f, 0.040909f }, // 905 (10 3 2 1) { 11.666667f, 1.666667f, 1.333333f, 0.056604f }, // 906 (10 3 3 0) { 11.777778f, 2.444444f, 0.888889f, 0.035714f }, // 907 (10 4 0 2) { 11.888889f, 1.888889f, 1.111111f, 0.047120f }, // 908 (10 4 1 1) { 12.000000f, 1.333333f, 1.333333f, 0.070313f }, // 909 (10 4 2 0) { 12.222222f, 1.555556f, 1.111111f, 0.056250f }, // 910 (10 5 0 1) { 12.333333f, 1.000000f, 1.333333f, 0.094737f }, // 911 (10 5 1 0) { 12.666667f, 0.666667f, 1.333333f, 0.150000f }, // 912 (10 6 0 0) { 11.000000f, 5.000000f, 0.000000f, 0.018182f }, // 913 (11 0 0 5) { 11.111111f, 4.444445f, 0.222222f, 0.020270f }, // 914 (11 0 1 4) { 11.222222f, 3.888889f, 0.444444f, 0.023018f }, // 915 (11 0 2 3) { 11.333333f, 3.333333f, 0.666667f, 0.026786f }, // 916 (11 0 3 2) { 11.444445f, 2.777778f, 0.888889f, 0.032258f }, // 917 (11 0 4 1) { 11.555555f, 2.222222f, 1.111111f, 0.040909f }, // 918 (11 0 5 0) { 11.444445f, 4.111111f, 0.222222f, 0.021277f }, // 919 (11 1 0 4) { 11.555555f, 3.555556f, 0.444444f, 0.024457f }, // 920 (11 1 1 3) { 11.666667f, 3.000000f, 0.666667f, 0.028939f }, // 921 (11 1 2 2) { 11.777778f, 2.444444f, 0.888889f, 0.035714f }, // 922 (11 1 3 1) { 11.888889f, 1.888889f, 1.111111f, 0.047120f }, // 923 (11 1 4 0) { 11.888889f, 3.222222f, 0.444444f, 0.026239f }, // 924 (11 2 0 3) { 12.000000f, 2.666667f, 0.666667f, 0.031690f }, // 925 (11 2 1 2) { 12.111111f, 2.111111f, 0.888889f, 0.040359f }, // 926 (11 2 2 1) { 12.222222f, 1.555556f, 1.111111f, 0.056250f }, // 927 (11 2 3 0) { 12.333333f, 2.333333f, 0.666667f, 0.035294f }, // 928 (11 3 0 2) { 12.444445f, 1.777778f, 0.888889f, 0.046875f }, // 929 (11 3 1 1) { 12.555555f, 1.222222f, 1.111111f, 0.070866f }, // 930 (11 3 2 0) { 12.777778f, 1.444444f, 0.888889f, 0.056604f }, // 931 (11 4 0 1) { 12.888889f, 0.888889f, 1.111111f, 0.097826f }, // 932 (11 4 1 0) { 13.222222f, 0.555556f, 1.111111f, 0.163636f }, // 933 (11 5 0 0) { 12.000000f, 4.000000f, 0.000000f, 0.020833f }, // 934 (12 0 0 4) { 12.111111f, 3.444444f, 0.222222f, 0.024000f }, // 935 (12 0 1 3) { 12.222222f, 2.888889f, 0.444444f, 0.028481f }, // 936 (12 0 2 2) { 12.333333f, 2.333333f, 0.666667f, 0.035294f }, // 937 (12 0 3 1) { 12.444445f, 1.777778f, 0.888889f, 0.046875f }, // 938 (12 0 4 0) { 12.444445f, 3.111111f, 0.222222f, 0.025862f }, // 939 (12 1 0 3) { 12.555555f, 2.555556f, 0.444444f, 0.031359f }, // 940 (12 1 1 2) { 12.666667f, 2.000000f, 0.666667f, 0.040179f }, // 941 (12 1 2 1) { 12.777778f, 1.444444f, 0.888889f, 0.056604f }, // 942 (12 1 3 0) { 12.888889f, 2.222222f, 0.444444f, 0.035156f }, // 943 (12 2 0 2) { 13.000000f, 1.666667f, 0.666667f, 0.047120f }, // 944 (12 2 1 1) { 13.111111f, 1.111111f, 0.888889f, 0.072581f }, // 945 (12 2 2 0) { 13.333333f, 1.333333f, 0.666667f, 0.057692f }, // 946 (12 3 0 1) { 13.444445f, 0.777778f, 0.888889f, 0.103448f }, // 947 (12 3 1 0) { 13.777778f, 0.444444f, 0.888889f, 0.187500f }, // 948 (12 4 0 0) { 13.000000f, 3.000000f, 0.000000f, 0.025641f }, // 949 (13 0 0 3) { 13.111111f, 2.444444f, 0.222222f, 0.031250f }, // 950 (13 0 1 2) { 13.222222f, 1.888889f, 0.444444f, 0.040359f }, // 951 (13 0 2 1) { 13.333333f, 1.333333f, 0.666667f, 0.057692f }, // 952 (13 0 3 0) { 13.444445f, 2.111111f, 0.222222f, 0.035294f }, // 953 (13 1 0 2) { 13.555555f, 1.555556f, 0.444444f, 0.047872f }, // 954 (13 1 1 1) { 13.666667f, 1.000000f, 0.666667f, 0.075630f }, // 955 (13 1 2 0) { 13.888889f, 1.222222f, 0.444444f, 0.059603f }, // 956 (13 2 0 1) { 14.000000f, 0.666667f, 0.666667f, 0.112500f }, // 957 (13 2 1 0) { 14.333333f, 0.333333f, 0.666667f, 0.230769f }, // 958 (13 3 0 0) { 14.000000f, 2.000000f, 0.000000f, 0.035714f }, // 959 (14 0 0 2) { 14.111111f, 1.444444f, 0.222222f, 0.049180f }, // 960 (14 0 1 1) { 14.222222f, 0.888889f, 0.444444f, 0.080357f }, // 961 (14 0 2 0) { 14.444445f, 1.111111f, 0.222222f, 0.062500f }, // 962 (14 1 0 1) { 14.555555f, 0.555556f, 0.444444f, 0.126761f }, // 963 (14 1 1 0) { 14.888889f, 0.222222f, 0.444444f, 0.321429f }, // 964 (14 2 0 0) { 15.000000f, 1.000000f, 0.000000f, 0.066667f }, // 965 (15 0 0 1) { 15.111111f, 0.444444f, 0.222222f, 0.150000f }, // 966 (15 0 1 0) { 15.444445f, 0.111111f, 0.222222f, 0.600000f }, // 967 (15 1 0 0) { 16.000000f, 0.000000f, 0.000000f, FLT_MAX }, // 968 (16 0 0 0) }; // 969 four cluster elements nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/maths.cpp000066400000000000000000000074741173441656100236460ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 "maths.h" #include "simd.h" #include namespace squish { Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights, Vec3::Arg metric ) { // 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) * metric; 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 EstimatePrincipleComponent( Sym3x3 const& matrix ) { Vec3 const row0(matrix[0], matrix[1], matrix[2]); Vec3 const row1(matrix[1], matrix[3], matrix[4]); Vec3 const row2(matrix[2], matrix[4], matrix[5]); float r0 = Dot(row0, row0); float r1 = Dot(row1, row1); float r2 = Dot(row2, row2); if (r0 > r1 && r0 > r2) return row0; if (r1 > r2) return row1; return row2; } #define POWER_ITERATION_COUNT 8 #if SQUISH_USE_SIMD Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ) { Vec4 const row0( matrix[0], matrix[1], matrix[2], 0.0f ); Vec4 const row1( matrix[1], matrix[3], matrix[4], 0.0f ); Vec4 const row2( matrix[2], matrix[4], matrix[5], 0.0f ); //Vec4 v = VEC4_CONST( 1.0f ); //Vec4 v = row0; // row1, row2 Vec3 v3 = EstimatePrincipleComponent( matrix ); Vec4 v( v3.X(), v3.Y(), v3.Z(), 0.0f ); for( int i = 0; i < POWER_ITERATION_COUNT; ++i ) { // matrix multiply Vec4 w = row0*v.SplatX(); w = MultiplyAdd(row1, v.SplatY(), w); w = MultiplyAdd(row2, v.SplatZ(), w); // get max component from xyz in all channels Vec4 a = Max(w.SplatX(), Max(w.SplatY(), w.SplatZ())); // divide through and advance v = w*Reciprocal(a); } return v.GetVec3(); } #else Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ) { Vec3 v = EstimatePrincipleComponent( matrix ); for (int i = 0; i < POWER_ITERATION_COUNT; 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; } #endif } // namespace squish nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/maths.h000066400000000000000000000104361173441656100233030ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #include #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::Arg metric ); Vec3 ComputePrincipleComponent( Sym3x3 const& matrix ); } // namespace squish #endif // ndef SQUISH_MATHS_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/rangefit.cpp000066400000000000000000000117001173441656100243140ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/rangefit.h000066400000000000000000000033211173441656100237610ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/simd.h000066400000000000000000000031261173441656100231210ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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" #ifdef __GNUC__ # define SQUISH_ALIGN_16 __attribute__ ((__aligned__ (16))) #else # define SQUISH_ALIGN_16 __declspec(align(16)) #endif #if SQUISH_USE_ALTIVEC #include "simd_ve.h" #endif #if SQUISH_USE_SSE #include "simd_sse.h" #endif #endif // ndef SQUISH_SIMD_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/simd_3dnow.h000066400000000000000000000126731173441656100242420ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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_3DNOW_H #define SQUISH_SIMD_3DNOW_H //#include #include #include //#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() {} Vec4( __m64 v0, __m64 v1 ) : m_v0( v0 ), m_v1( v1 ) {} Vec4( Vec4 const& arg ) : m_v0( arg.m_v0 ), m_v1( arg.m_v1 ) {} Vec4& operator=( Vec4 const& arg ) { m_v0 = arg.m_v0; m_v1 = arg.m_v1; return *this; } Vec4( float x, float y, float z, float w ) { m_v0 = _mm_set_pi32( *(int *)&x, *(int *)&y ); m_v1 = _mm_set_pi32( *(int *)&z, *(int *)&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_v0 = _m_pfadd( m_v0, v.m_v0 ); m_v1 = _m_pfadd( m_v1, v.m_v1 ); return *this; } Vec4& operator-=( Arg v ) { m_v0 = _m_pfsub( m_v0, v.m_v0 ); m_v1 = _m_pfsub( m_v1, v.m_v1 ); return *this; } Vec4& operator*=( Arg v ) { m_v0 = _m_pfmul( m_v0, v.m_v0 ); m_v1 = _m_pfmul( m_v1, v.m_v1 ); return *this; } friend Vec4 operator+( Vec4::Arg left, Vec4::Arg right ) { return Vec4( _m_pfadd( left.m_v0, right.m_v0 ), _m_pfadd( left.m_v1, right.m_v1 )); } friend Vec4 operator-( Vec4::Arg left, Vec4::Arg right ) { return Vec4( _m_pfsub( left.m_v0, right.m_v0 ), _m_pfsub( left.m_v1, right.m_v1 )); } friend Vec4 operator*( Vec4::Arg left, Vec4::Arg right ) { return Vec4( _m_pfmul( left.m_v0, right.m_v0 ), _m_pfmul( left.m_v1, right.m_v1 )); } //! Returns a*b + c friend Vec4 MultiplyAdd( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) { return Vec4( _m_pfadd( _m_pfmul( a.m_v0, b.m_v0 ), c.m_v0 ), _m_pfadd( _m_pfmul( a.m_v1, b.m_v1 ), c.m_v1 )); } //! Returns -( a*b - c ) friend Vec4 NegativeMultiplySubtract( Vec4::Arg a, Vec4::Arg b, Vec4::Arg c ) { return Vec4( _m_pfsub( c.m_v0, _m_pfmul( a.m_v0, b.m_v0 ) ), _m_pfsub( c.m_v1, _m_pfmul( a.m_v1, b.m_v1 ) )); } friend Vec4 Reciprocal( Vec4::Arg v ) { // get the reciprocal estimate __m64 x0 = _m_pfrcp(v.m_v0); __m64 y1 = _m_pfrcp(v.m_v1); // Newton-Rhaphson refinement __m64 x1 = _m_pfrcpit1(v.m_v0, x0); __m64 y1 = _m_pfrcpit1(v.m_v1, y0); __m64 x2 = _m_pfrcpit2(x1, x0); __m64 y2 = _m_pfrcpit2(y1, y0); return Vec4(x2, y2); } friend Vec4 Min( Vec4::Arg left, Vec4::Arg right ) { return Vec4( _m_pfmin( left.m_v0, right.m_v0 ), _m_pfmin( left.m_v1, right.m_v1 )); } friend Vec4 Max( Vec4::Arg left, Vec4::Arg right ) { return Vec4( _m_pfmax( left.m_v0, right.m_v0 ), _m_pfmax( left.m_v1, right.m_v1 )); } friend Vec4 Truncate( Vec4::Arg v ) { // convert to ints __m64 i0 = _m_pf2id( v.m_v0 ); __m64 i1 = _m_pf2id( v.m_v1 ); // convert to floats __m64 f0 = _m_pi2fd( i0 ); __m64 f1 = _m_pi2fd( i1 ); // clear out the MMX multimedia state to allow FP calls later //_m_femms(); return Vec4( f0, f1 ); } friend Vec4 CompareEqual( Vec4::Arg left, Vec4::Arg right ) { return Vec4( _m_pfcmpeq( left.m_v0, right.m_v0 ), _m_pfcmpeq( left.m_v1, right.m_v1 )); } /* 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: __m64 m_v0; __m64 m_v1; }; } // namespace squish #endif // ndef SQUISH_SIMD_3DNOW_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/simd_sse.h000066400000000000000000000120561173441656100237750ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #if ( SQUISH_USE_SSE > 1 ) #include #endif #include #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( const float * v ) { m_v = _mm_load_ps( v ); } Vec4( float x, float y, float z, float w ) { m_v = _mm_setr_ps( x, y, z, w ); } Vec3 GetVec3() const { SQUISH_ALIGN_16 float c[4]; _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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/simd_ve.h000066400000000000000000000105221173441656100236110ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #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( const float * v ) { union { vector float v; float c[4]; } u; u.c[0] = v[0]; u.c[1] = v[1]; u.c[2] = v[2]; u.c[3] = v[3]; m_v = u.v; } 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/singlechannelfit.cpp000066400000000000000000000102731173441656100260360ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/singlechannelfit.h000066400000000000000000000034611173441656100255040ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/singlecolourfit.cpp000066400000000000000000000104371173441656100257330ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/singlecolourfit.h000066400000000000000000000035611173441656100254000ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/singlecolourlookup.inl000066400000000000000000002013241173441656100264570ustar00rootroot00000000000000 static SingleColourLookup const lookup_5_3[] = { { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } }, { { { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 0 } } }, { { { 0, 0, 2 }, { 0, 0, 2 }, { 0, 0, 2 }, { 0, 0, 0 } } }, { { { 0, 0, 3 }, { 0, 0, 3 }, { 0, 1, 1 }, { 0, 0, 0 } } }, { { { 0, 0, 4 }, { 0, 0, 4 }, { 0, 1, 0 }, { 0, 0, 0 } } }, { { { 1, 0, 3 }, { 0, 1, 3 }, { 0, 1, 1 }, { 0, 0, 0 } } }, { { { 1, 0, 2 }, { 0, 1, 2 }, { 0, 1, 2 }, { 0, 0, 0 } } }, { { { 1, 0, 1 }, { 0, 1, 1 }, { 0, 2, 1 }, { 0, 0, 0 } } }, { { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 2, 0 }, { 0, 0, 0 } } }, { { { 1, 0, 1 }, { 0, 1, 1 }, { 0, 2, 1 }, { 0, 0, 0 } } }, { { { 1, 0, 2 }, { 0, 1, 2 }, { 0, 2, 2 }, { 0, 0, 0 } } }, { { { 1, 0, 3 }, { 0, 1, 3 }, { 0, 3, 1 }, { 0, 0, 0 } } }, { { { 1, 0, 4 }, { 0, 1, 4 }, { 0, 3, 0 }, { 0, 0, 0 } } }, { { { 2, 0, 3 }, { 0, 2, 3 }, { 0, 3, 1 }, { 0, 0, 0 } } }, { { { 2, 0, 2 }, { 0, 2, 2 }, { 0, 3, 2 }, { 0, 0, 0 } } }, { { { 2, 0, 1 }, { 0, 2, 1 }, { 0, 4, 1 }, { 0, 0, 0 } } }, { { { 2, 0, 0 }, { 0, 2, 0 }, { 0, 4, 0 }, { 0, 0, 0 } } }, { { { 2, 0, 1 }, { 0, 2, 1 }, { 0, 4, 1 }, { 0, 0, 0 } } }, { { { 2, 0, 2 }, { 0, 2, 2 }, { 0, 4, 2 }, { 0, 0, 0 } } }, { { { 2, 0, 3 }, { 0, 2, 3 }, { 0, 5, 1 }, { 0, 0, 0 } } }, { { { 2, 0, 4 }, { 0, 2, 4 }, { 0, 5, 0 }, { 0, 0, 0 } } }, { { { 3, 0, 3 }, { 0, 3, 3 }, { 0, 5, 1 }, { 0, 0, 0 } } }, { { { 3, 0, 2 }, { 0, 3, 2 }, { 0, 5, 2 }, { 0, 0, 0 } } }, { { { 3, 0, 1 }, { 0, 3, 1 }, { 0, 6, 1 }, { 0, 0, 0 } } }, { { { 3, 0, 0 }, { 0, 3, 0 }, { 0, 6, 0 }, { 0, 0, 0 } } }, { { { 3, 0, 1 }, { 0, 3, 1 }, { 0, 6, 1 }, { 0, 0, 0 } } }, { { { 3, 0, 2 }, { 0, 3, 2 }, { 0, 6, 2 }, { 0, 0, 0 } } }, { { { 3, 0, 3 }, { 0, 3, 3 }, { 0, 7, 1 }, { 0, 0, 0 } } }, { { { 3, 0, 4 }, { 0, 3, 4 }, { 0, 7, 0 }, { 0, 0, 0 } } }, { { { 4, 0, 4 }, { 0, 4, 4 }, { 0, 7, 1 }, { 0, 0, 0 } } }, { { { 4, 0, 3 }, { 0, 4, 3 }, { 0, 7, 2 }, { 0, 0, 0 } } }, { { { 4, 0, 2 }, { 0, 4, 2 }, { 1, 7, 1 }, { 0, 0, 0 } } }, { { { 4, 0, 1 }, { 0, 4, 1 }, { 1, 7, 0 }, { 0, 0, 0 } } }, { { { 4, 0, 0 }, { 0, 4, 0 }, { 0, 8, 0 }, { 0, 0, 0 } } }, { { { 4, 0, 1 }, { 0, 4, 1 }, { 0, 8, 1 }, { 0, 0, 0 } } }, { { { 4, 0, 2 }, { 0, 4, 2 }, { 2, 7, 1 }, { 0, 0, 0 } } }, { { { 4, 0, 3 }, { 0, 4, 3 }, { 2, 7, 0 }, { 0, 0, 0 } } }, { { { 4, 0, 4 }, { 0, 4, 4 }, { 0, 9, 0 }, { 0, 0, 0 } } }, { { { 5, 0, 3 }, { 0, 5, 3 }, { 0, 9, 1 }, { 0, 0, 0 } } }, { { { 5, 0, 2 }, { 0, 5, 2 }, { 3, 7, 1 }, { 0, 0, 0 } } }, { { { 5, 0, 1 }, { 0, 5, 1 }, { 3, 7, 0 }, { 0, 0, 0 } } }, { { { 5, 0, 0 }, { 0, 5, 0 }, { 0, 10, 0 }, { 0, 0, 0 } } }, { { { 5, 0, 1 }, { 0, 5, 1 }, { 0, 10, 1 }, { 0, 0, 0 } } }, { { { 5, 0, 2 }, { 0, 5, 2 }, { 0, 10, 2 }, { 0, 0, 0 } } }, { { { 5, 0, 3 }, { 0, 5, 3 }, { 0, 11, 1 }, { 0, 0, 0 } } }, { { { 5, 0, 4 }, { 0, 5, 4 }, { 0, 11, 0 }, { 0, 0, 0 } } }, { { { 6, 0, 3 }, { 0, 6, 3 }, { 0, 11, 1 }, { 0, 0, 0 } } }, { { { 6, 0, 2 }, { 0, 6, 2 }, { 0, 11, 2 }, { 0, 0, 0 } } }, { { { 6, 0, 1 }, { 0, 6, 1 }, { 0, 12, 1 }, { 0, 0, 0 } } }, { { { 6, 0, 0 }, { 0, 6, 0 }, { 0, 12, 0 }, { 0, 0, 0 } } }, { { { 6, 0, 1 }, { 0, 6, 1 }, { 0, 12, 1 }, { 0, 0, 0 } } }, { { { 6, 0, 2 }, { 0, 6, 2 }, { 0, 12, 2 }, { 0, 0, 0 } } }, { { { 6, 0, 3 }, { 0, 6, 3 }, { 0, 13, 1 }, { 0, 0, 0 } } }, { { { 6, 0, 4 }, { 0, 6, 4 }, { 0, 13, 0 }, { 0, 0, 0 } } }, { { { 7, 0, 3 }, { 0, 7, 3 }, { 0, 13, 1 }, { 0, 0, 0 } } }, { { { 7, 0, 2 }, { 0, 7, 2 }, { 0, 13, 2 }, { 0, 0, 0 } } }, { { { 7, 0, 1 }, { 0, 7, 1 }, { 0, 14, 1 }, { 0, 0, 0 } } }, { { { 7, 0, 0 }, { 0, 7, 0 }, { 0, 14, 0 }, { 0, 0, 0 } } }, { { { 7, 0, 1 }, { 0, 7, 1 }, { 0, 14, 1 }, { 0, 0, 0 } } }, { { { 7, 0, 2 }, { 0, 7, 2 }, { 0, 14, 2 }, { 0, 0, 0 } } }, { { { 7, 0, 3 }, { 0, 7, 3 }, { 0, 15, 1 }, { 0, 0, 0 } } }, { { { 7, 0, 4 }, { 0, 7, 4 }, { 0, 15, 0 }, { 0, 0, 0 } } }, { { { 8, 0, 4 }, { 0, 8, 4 }, { 0, 15, 1 }, { 0, 0, 0 } } }, { { { 8, 0, 3 }, { 0, 8, 3 }, { 0, 15, 2 }, { 0, 0, 0 } } }, { { { 8, 0, 2 }, { 0, 8, 2 }, { 1, 15, 1 }, { 0, 0, 0 } } }, { { { 8, 0, 1 }, { 0, 8, 1 }, { 1, 15, 0 }, { 0, 0, 0 } } }, { { { 8, 0, 0 }, { 0, 8, 0 }, { 0, 16, 0 }, { 0, 0, 0 } } }, { { { 8, 0, 1 }, { 0, 8, 1 }, { 0, 16, 1 }, { 0, 0, 0 } } }, { { { 8, 0, 2 }, { 0, 8, 2 }, { 2, 15, 1 }, { 0, 0, 0 } } }, { { { 8, 0, 3 }, { 0, 8, 3 }, { 2, 15, 0 }, { 0, 0, 0 } } }, { { { 8, 0, 4 }, { 0, 8, 4 }, { 0, 17, 0 }, { 0, 0, 0 } } }, { { { 9, 0, 3 }, { 0, 9, 3 }, { 0, 17, 1 }, { 0, 0, 0 } } }, { { { 9, 0, 2 }, { 0, 9, 2 }, { 3, 15, 1 }, { 0, 0, 0 } } }, { { { 9, 0, 1 }, { 0, 9, 1 }, { 3, 15, 0 }, { 0, 0, 0 } } }, { { { 9, 0, 0 }, { 0, 9, 0 }, { 0, 18, 0 }, { 0, 0, 0 } } }, { { { 9, 0, 1 }, { 0, 9, 1 }, { 0, 18, 1 }, { 0, 0, 0 } } }, { { { 9, 0, 2 }, { 0, 9, 2 }, { 0, 18, 2 }, { 0, 0, 0 } } }, { { { 9, 0, 3 }, { 0, 9, 3 }, { 0, 19, 1 }, { 0, 0, 0 } } }, { { { 9, 0, 4 }, { 0, 9, 4 }, { 0, 19, 0 }, { 0, 0, 0 } } }, { { { 10, 0, 3 }, { 0, 10, 3 }, { 0, 19, 1 }, { 0, 0, 0 } } }, { { { 10, 0, 2 }, { 0, 10, 2 }, { 0, 19, 2 }, { 0, 0, 0 } } }, { { { 10, 0, 1 }, { 0, 10, 1 }, { 0, 20, 1 }, { 0, 0, 0 } } }, { { { 10, 0, 0 }, { 0, 10, 0 }, { 0, 20, 0 }, { 0, 0, 0 } } }, { { { 10, 0, 1 }, { 0, 10, 1 }, { 0, 20, 1 }, { 0, 0, 0 } } }, { { { 10, 0, 2 }, { 0, 10, 2 }, { 0, 20, 2 }, { 0, 0, 0 } } }, { { { 10, 0, 3 }, { 0, 10, 3 }, { 0, 21, 1 }, { 0, 0, 0 } } }, { { { 10, 0, 4 }, { 0, 10, 4 }, { 0, 21, 0 }, { 0, 0, 0 } } }, { { { 11, 0, 3 }, { 0, 11, 3 }, { 0, 21, 1 }, { 0, 0, 0 } } }, { { { 11, 0, 2 }, { 0, 11, 2 }, { 0, 21, 2 }, { 0, 0, 0 } } }, { { { 11, 0, 1 }, { 0, 11, 1 }, { 0, 22, 1 }, { 0, 0, 0 } } }, { { { 11, 0, 0 }, { 0, 11, 0 }, { 0, 22, 0 }, { 0, 0, 0 } } }, { { { 11, 0, 1 }, { 0, 11, 1 }, { 0, 22, 1 }, { 0, 0, 0 } } }, { { { 11, 0, 2 }, { 0, 11, 2 }, { 0, 22, 2 }, { 0, 0, 0 } } }, { { { 11, 0, 3 }, { 0, 11, 3 }, { 0, 23, 1 }, { 0, 0, 0 } } }, { { { 11, 0, 4 }, { 0, 11, 4 }, { 0, 23, 0 }, { 0, 0, 0 } } }, { { { 12, 0, 4 }, { 0, 12, 4 }, { 0, 23, 1 }, { 0, 0, 0 } } }, { { { 12, 0, 3 }, { 0, 12, 3 }, { 0, 23, 2 }, { 0, 0, 0 } } }, { { { 12, 0, 2 }, { 0, 12, 2 }, { 1, 23, 1 }, { 0, 0, 0 } } }, { { { 12, 0, 1 }, { 0, 12, 1 }, { 1, 23, 0 }, { 0, 0, 0 } } }, { { { 12, 0, 0 }, { 0, 12, 0 }, { 0, 24, 0 }, { 0, 0, 0 } } }, { { { 12, 0, 1 }, { 0, 12, 1 }, { 0, 24, 1 }, { 0, 0, 0 } } }, { { { 12, 0, 2 }, { 0, 12, 2 }, { 2, 23, 1 }, { 0, 0, 0 } } }, { { { 12, 0, 3 }, { 0, 12, 3 }, { 2, 23, 0 }, { 0, 0, 0 } } }, { { { 12, 0, 4 }, { 0, 12, 4 }, { 0, 25, 0 }, { 0, 0, 0 } } }, { { { 13, 0, 3 }, { 0, 13, 3 }, { 0, 25, 1 }, { 0, 0, 0 } } }, { { { 13, 0, 2 }, { 0, 13, 2 }, { 3, 23, 1 }, { 0, 0, 0 } } }, { { { 13, 0, 1 }, { 0, 13, 1 }, { 3, 23, 0 }, { 0, 0, 0 } } }, { { { 13, 0, 0 }, { 0, 13, 0 }, { 0, 26, 0 }, { 0, 0, 0 } } }, { { { 13, 0, 1 }, { 0, 13, 1 }, { 0, 26, 1 }, { 0, 0, 0 } } }, { { { 13, 0, 2 }, { 0, 13, 2 }, { 0, 26, 2 }, { 0, 0, 0 } } }, { { { 13, 0, 3 }, { 0, 13, 3 }, { 0, 27, 1 }, { 0, 0, 0 } } }, { { { 13, 0, 4 }, { 0, 13, 4 }, { 0, 27, 0 }, { 0, 0, 0 } } }, { { { 14, 0, 3 }, { 0, 14, 3 }, { 0, 27, 1 }, { 0, 0, 0 } } }, { { { 14, 0, 2 }, { 0, 14, 2 }, { 0, 27, 2 }, { 0, 0, 0 } } }, { { { 14, 0, 1 }, { 0, 14, 1 }, { 0, 28, 1 }, { 0, 0, 0 } } }, { { { 14, 0, 0 }, { 0, 14, 0 }, { 0, 28, 0 }, { 0, 0, 0 } } }, { { { 14, 0, 1 }, { 0, 14, 1 }, { 0, 28, 1 }, { 0, 0, 0 } } }, { { { 14, 0, 2 }, { 0, 14, 2 }, { 0, 28, 2 }, { 0, 0, 0 } } }, { { { 14, 0, 3 }, { 0, 14, 3 }, { 0, 29, 1 }, { 0, 0, 0 } } }, { { { 14, 0, 4 }, { 0, 14, 4 }, { 0, 29, 0 }, { 0, 0, 0 } } }, { { { 15, 0, 3 }, { 0, 15, 3 }, { 0, 29, 1 }, { 0, 0, 0 } } }, { { { 15, 0, 2 }, { 0, 15, 2 }, { 0, 29, 2 }, { 0, 0, 0 } } }, { { { 15, 0, 1 }, { 0, 15, 1 }, { 0, 30, 1 }, { 0, 0, 0 } } }, { { { 15, 0, 0 }, { 0, 15, 0 }, { 0, 30, 0 }, { 0, 0, 0 } } }, { { { 15, 0, 1 }, { 0, 15, 1 }, { 0, 30, 1 }, { 0, 0, 0 } } }, { { { 15, 0, 2 }, { 0, 15, 2 }, { 0, 30, 2 }, { 0, 0, 0 } } }, { { { 15, 0, 3 }, { 0, 15, 3 }, { 0, 31, 1 }, { 0, 0, 0 } } }, { { { 15, 0, 4 }, { 0, 15, 4 }, { 0, 31, 0 }, { 0, 0, 0 } } }, { { { 16, 0, 4 }, { 0, 16, 4 }, { 0, 31, 1 }, { 0, 0, 0 } } }, { { { 16, 0, 3 }, { 0, 16, 3 }, { 0, 31, 2 }, { 0, 0, 0 } } }, { { { 16, 0, 2 }, { 0, 16, 2 }, { 1, 31, 1 }, { 0, 0, 0 } } }, { { { 16, 0, 1 }, { 0, 16, 1 }, { 1, 31, 0 }, { 0, 0, 0 } } }, { { { 16, 0, 0 }, { 0, 16, 0 }, { 4, 28, 0 }, { 0, 0, 0 } } }, { { { 16, 0, 1 }, { 0, 16, 1 }, { 4, 28, 1 }, { 0, 0, 0 } } }, { { { 16, 0, 2 }, { 0, 16, 2 }, { 2, 31, 1 }, { 0, 0, 0 } } }, { { { 16, 0, 3 }, { 0, 16, 3 }, { 2, 31, 0 }, { 0, 0, 0 } } }, { { { 16, 0, 4 }, { 0, 16, 4 }, { 4, 29, 0 }, { 0, 0, 0 } } }, { { { 17, 0, 3 }, { 0, 17, 3 }, { 4, 29, 1 }, { 0, 0, 0 } } }, { { { 17, 0, 2 }, { 0, 17, 2 }, { 3, 31, 1 }, { 0, 0, 0 } } }, { { { 17, 0, 1 }, { 0, 17, 1 }, { 3, 31, 0 }, { 0, 0, 0 } } }, { { { 17, 0, 0 }, { 0, 17, 0 }, { 4, 30, 0 }, { 0, 0, 0 } } }, { { { 17, 0, 1 }, { 0, 17, 1 }, { 4, 30, 1 }, { 0, 0, 0 } } }, { { { 17, 0, 2 }, { 0, 17, 2 }, { 4, 30, 2 }, { 0, 0, 0 } } }, { { { 17, 0, 3 }, { 0, 17, 3 }, { 4, 31, 1 }, { 0, 0, 0 } } }, { { { 17, 0, 4 }, { 0, 17, 4 }, { 4, 31, 0 }, { 0, 0, 0 } } }, { { { 18, 0, 3 }, { 0, 18, 3 }, { 4, 31, 1 }, { 0, 0, 0 } } }, { { { 18, 0, 2 }, { 0, 18, 2 }, { 4, 31, 2 }, { 0, 0, 0 } } }, { { { 18, 0, 1 }, { 0, 18, 1 }, { 5, 31, 1 }, { 0, 0, 0 } } }, { { { 18, 0, 0 }, { 0, 18, 0 }, { 5, 31, 0 }, { 0, 0, 0 } } }, { { { 18, 0, 1 }, { 0, 18, 1 }, { 5, 31, 1 }, { 0, 0, 0 } } }, { { { 18, 0, 2 }, { 0, 18, 2 }, { 5, 31, 2 }, { 0, 0, 0 } } }, { { { 18, 0, 3 }, { 0, 18, 3 }, { 6, 31, 1 }, { 0, 0, 0 } } }, { { { 18, 0, 4 }, { 0, 18, 4 }, { 6, 31, 0 }, { 0, 0, 0 } } }, { { { 19, 0, 3 }, { 0, 19, 3 }, { 6, 31, 1 }, { 0, 0, 0 } } }, { { { 19, 0, 2 }, { 0, 19, 2 }, { 6, 31, 2 }, { 0, 0, 0 } } }, { { { 19, 0, 1 }, { 0, 19, 1 }, { 7, 31, 1 }, { 0, 0, 0 } } }, { { { 19, 0, 0 }, { 0, 19, 0 }, { 7, 31, 0 }, { 0, 0, 0 } } }, { { { 19, 0, 1 }, { 0, 19, 1 }, { 7, 31, 1 }, { 0, 0, 0 } } }, { { { 19, 0, 2 }, { 0, 19, 2 }, { 7, 31, 2 }, { 0, 0, 0 } } }, { { { 19, 0, 3 }, { 0, 19, 3 }, { 8, 31, 1 }, { 0, 0, 0 } } }, { { { 19, 0, 4 }, { 0, 19, 4 }, { 8, 31, 0 }, { 0, 0, 0 } } }, { { { 20, 0, 4 }, { 0, 20, 4 }, { 8, 31, 1 }, { 0, 0, 0 } } }, { { { 20, 0, 3 }, { 0, 20, 3 }, { 8, 31, 2 }, { 0, 0, 0 } } }, { { { 20, 0, 2 }, { 0, 20, 2 }, { 9, 31, 1 }, { 0, 0, 0 } } }, { { { 20, 0, 1 }, { 0, 20, 1 }, { 9, 31, 0 }, { 0, 0, 0 } } }, { { { 20, 0, 0 }, { 0, 20, 0 }, { 12, 28, 0 }, { 0, 0, 0 } } }, { { { 20, 0, 1 }, { 0, 20, 1 }, { 12, 28, 1 }, { 0, 0, 0 } } }, { { { 20, 0, 2 }, { 0, 20, 2 }, { 10, 31, 1 }, { 0, 0, 0 } } }, { { { 20, 0, 3 }, { 0, 20, 3 }, { 10, 31, 0 }, { 0, 0, 0 } } }, { { { 20, 0, 4 }, { 0, 20, 4 }, { 12, 29, 0 }, { 0, 0, 0 } } }, { { { 21, 0, 3 }, { 0, 21, 3 }, { 12, 29, 1 }, { 0, 0, 0 } } }, { { { 21, 0, 2 }, { 0, 21, 2 }, { 11, 31, 1 }, { 0, 0, 0 } } }, { { { 21, 0, 1 }, { 0, 21, 1 }, { 11, 31, 0 }, { 0, 0, 0 } } }, { { { 21, 0, 0 }, { 0, 21, 0 }, { 12, 30, 0 }, { 0, 0, 0 } } }, { { { 21, 0, 1 }, { 0, 21, 1 }, { 12, 30, 1 }, { 0, 0, 0 } } }, { { { 21, 0, 2 }, { 0, 21, 2 }, { 12, 30, 2 }, { 0, 0, 0 } } }, { { { 21, 0, 3 }, { 0, 21, 3 }, { 12, 31, 1 }, { 0, 0, 0 } } }, { { { 21, 0, 4 }, { 0, 21, 4 }, { 12, 31, 0 }, { 0, 0, 0 } } }, { { { 22, 0, 3 }, { 0, 22, 3 }, { 12, 31, 1 }, { 0, 0, 0 } } }, { { { 22, 0, 2 }, { 0, 22, 2 }, { 12, 31, 2 }, { 0, 0, 0 } } }, { { { 22, 0, 1 }, { 0, 22, 1 }, { 13, 31, 1 }, { 0, 0, 0 } } }, { { { 22, 0, 0 }, { 0, 22, 0 }, { 13, 31, 0 }, { 0, 0, 0 } } }, { { { 22, 0, 1 }, { 0, 22, 1 }, { 13, 31, 1 }, { 0, 0, 0 } } }, { { { 22, 0, 2 }, { 0, 22, 2 }, { 13, 31, 2 }, { 0, 0, 0 } } }, { { { 22, 0, 3 }, { 0, 22, 3 }, { 14, 31, 1 }, { 0, 0, 0 } } }, { { { 22, 0, 4 }, { 0, 22, 4 }, { 14, 31, 0 }, { 0, 0, 0 } } }, { { { 23, 0, 3 }, { 0, 23, 3 }, { 14, 31, 1 }, { 0, 0, 0 } } }, { { { 23, 0, 2 }, { 0, 23, 2 }, { 14, 31, 2 }, { 0, 0, 0 } } }, { { { 23, 0, 1 }, { 0, 23, 1 }, { 15, 31, 1 }, { 0, 0, 0 } } }, { { { 23, 0, 0 }, { 0, 23, 0 }, { 15, 31, 0 }, { 0, 0, 0 } } }, { { { 23, 0, 1 }, { 0, 23, 1 }, { 15, 31, 1 }, { 0, 0, 0 } } }, { { { 23, 0, 2 }, { 0, 23, 2 }, { 15, 31, 2 }, { 0, 0, 0 } } }, { { { 23, 0, 3 }, { 0, 23, 3 }, { 16, 31, 1 }, { 0, 0, 0 } } }, { { { 23, 0, 4 }, { 0, 23, 4 }, { 16, 31, 0 }, { 0, 0, 0 } } }, { { { 24, 0, 4 }, { 0, 24, 4 }, { 16, 31, 1 }, { 0, 0, 0 } } }, { { { 24, 0, 3 }, { 0, 24, 3 }, { 16, 31, 2 }, { 0, 0, 0 } } }, { { { 24, 0, 2 }, { 0, 24, 2 }, { 17, 31, 1 }, { 0, 0, 0 } } }, { { { 24, 0, 1 }, { 0, 24, 1 }, { 17, 31, 0 }, { 0, 0, 0 } } }, { { { 24, 0, 0 }, { 0, 24, 0 }, { 20, 28, 0 }, { 0, 0, 0 } } }, { { { 24, 0, 1 }, { 0, 24, 1 }, { 20, 28, 1 }, { 0, 0, 0 } } }, { { { 24, 0, 2 }, { 0, 24, 2 }, { 18, 31, 1 }, { 0, 0, 0 } } }, { { { 24, 0, 3 }, { 0, 24, 3 }, { 18, 31, 0 }, { 0, 0, 0 } } }, { { { 24, 0, 4 }, { 0, 24, 4 }, { 20, 29, 0 }, { 0, 0, 0 } } }, { { { 25, 0, 3 }, { 0, 25, 3 }, { 20, 29, 1 }, { 0, 0, 0 } } }, { { { 25, 0, 2 }, { 0, 25, 2 }, { 19, 31, 1 }, { 0, 0, 0 } } }, { { { 25, 0, 1 }, { 0, 25, 1 }, { 19, 31, 0 }, { 0, 0, 0 } } }, { { { 25, 0, 0 }, { 0, 25, 0 }, { 20, 30, 0 }, { 0, 0, 0 } } }, { { { 25, 0, 1 }, { 0, 25, 1 }, { 20, 30, 1 }, { 0, 0, 0 } } }, { { { 25, 0, 2 }, { 0, 25, 2 }, { 20, 30, 2 }, { 0, 0, 0 } } }, { { { 25, 0, 3 }, { 0, 25, 3 }, { 20, 31, 1 }, { 0, 0, 0 } } }, { { { 25, 0, 4 }, { 0, 25, 4 }, { 20, 31, 0 }, { 0, 0, 0 } } }, { { { 26, 0, 3 }, { 0, 26, 3 }, { 20, 31, 1 }, { 0, 0, 0 } } }, { { { 26, 0, 2 }, { 0, 26, 2 }, { 20, 31, 2 }, { 0, 0, 0 } } }, { { { 26, 0, 1 }, { 0, 26, 1 }, { 21, 31, 1 }, { 0, 0, 0 } } }, { { { 26, 0, 0 }, { 0, 26, 0 }, { 21, 31, 0 }, { 0, 0, 0 } } }, { { { 26, 0, 1 }, { 0, 26, 1 }, { 21, 31, 1 }, { 0, 0, 0 } } }, { { { 26, 0, 2 }, { 0, 26, 2 }, { 21, 31, 2 }, { 0, 0, 0 } } }, { { { 26, 0, 3 }, { 0, 26, 3 }, { 22, 31, 1 }, { 0, 0, 0 } } }, { { { 26, 0, 4 }, { 0, 26, 4 }, { 22, 31, 0 }, { 0, 0, 0 } } }, { { { 27, 0, 3 }, { 0, 27, 3 }, { 22, 31, 1 }, { 0, 0, 0 } } }, { { { 27, 0, 2 }, { 0, 27, 2 }, { 22, 31, 2 }, { 0, 0, 0 } } }, { { { 27, 0, 1 }, { 0, 27, 1 }, { 23, 31, 1 }, { 0, 0, 0 } } }, { { { 27, 0, 0 }, { 0, 27, 0 }, { 23, 31, 0 }, { 0, 0, 0 } } }, { { { 27, 0, 1 }, { 0, 27, 1 }, { 23, 31, 1 }, { 0, 0, 0 } } }, { { { 27, 0, 2 }, { 0, 27, 2 }, { 23, 31, 2 }, { 0, 0, 0 } } }, { { { 27, 0, 3 }, { 0, 27, 3 }, { 24, 31, 1 }, { 0, 0, 0 } } }, { { { 27, 0, 4 }, { 0, 27, 4 }, { 24, 31, 0 }, { 0, 0, 0 } } }, { { { 28, 0, 4 }, { 0, 28, 4 }, { 24, 31, 1 }, { 0, 0, 0 } } }, { { { 28, 0, 3 }, { 0, 28, 3 }, { 24, 31, 2 }, { 0, 0, 0 } } }, { { { 28, 0, 2 }, { 0, 28, 2 }, { 25, 31, 1 }, { 0, 0, 0 } } }, { { { 28, 0, 1 }, { 0, 28, 1 }, { 25, 31, 0 }, { 0, 0, 0 } } }, { { { 28, 0, 0 }, { 0, 28, 0 }, { 28, 28, 0 }, { 0, 0, 0 } } }, { { { 28, 0, 1 }, { 0, 28, 1 }, { 28, 28, 1 }, { 0, 0, 0 } } }, { { { 28, 0, 2 }, { 0, 28, 2 }, { 26, 31, 1 }, { 0, 0, 0 } } }, { { { 28, 0, 3 }, { 0, 28, 3 }, { 26, 31, 0 }, { 0, 0, 0 } } }, { { { 28, 0, 4 }, { 0, 28, 4 }, { 28, 29, 0 }, { 0, 0, 0 } } }, { { { 29, 0, 3 }, { 0, 29, 3 }, { 28, 29, 1 }, { 0, 0, 0 } } }, { { { 29, 0, 2 }, { 0, 29, 2 }, { 27, 31, 1 }, { 0, 0, 0 } } }, { { { 29, 0, 1 }, { 0, 29, 1 }, { 27, 31, 0 }, { 0, 0, 0 } } }, { { { 29, 0, 0 }, { 0, 29, 0 }, { 28, 30, 0 }, { 0, 0, 0 } } }, { { { 29, 0, 1 }, { 0, 29, 1 }, { 28, 30, 1 }, { 0, 0, 0 } } }, { { { 29, 0, 2 }, { 0, 29, 2 }, { 28, 30, 2 }, { 0, 0, 0 } } }, { { { 29, 0, 3 }, { 0, 29, 3 }, { 28, 31, 1 }, { 0, 0, 0 } } }, { { { 29, 0, 4 }, { 0, 29, 4 }, { 28, 31, 0 }, { 0, 0, 0 } } }, { { { 30, 0, 3 }, { 0, 30, 3 }, { 28, 31, 1 }, { 0, 0, 0 } } }, { { { 30, 0, 2 }, { 0, 30, 2 }, { 28, 31, 2 }, { 0, 0, 0 } } }, { { { 30, 0, 1 }, { 0, 30, 1 }, { 29, 31, 1 }, { 0, 0, 0 } } }, { { { 30, 0, 0 }, { 0, 30, 0 }, { 29, 31, 0 }, { 0, 0, 0 } } }, { { { 30, 0, 1 }, { 0, 30, 1 }, { 29, 31, 1 }, { 0, 0, 0 } } }, { { { 30, 0, 2 }, { 0, 30, 2 }, { 29, 31, 2 }, { 0, 0, 0 } } }, { { { 30, 0, 3 }, { 0, 30, 3 }, { 30, 31, 1 }, { 0, 0, 0 } } }, { { { 30, 0, 4 }, { 0, 30, 4 }, { 30, 31, 0 }, { 0, 0, 0 } } }, { { { 31, 0, 3 }, { 0, 31, 3 }, { 30, 31, 1 }, { 0, 0, 0 } } }, { { { 31, 0, 2 }, { 0, 31, 2 }, { 30, 31, 2 }, { 0, 0, 0 } } }, { { { 31, 0, 1 }, { 0, 31, 1 }, { 31, 31, 1 }, { 0, 0, 0 } } }, { { { 31, 0, 0 }, { 0, 31, 0 }, { 31, 31, 0 }, { 0, 0, 0 } } } }; static SingleColourLookup const lookup_6_3[] = { { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } }, { { { 0, 0, 1 }, { 0, 0, 1 }, { 0, 1, 1 }, { 0, 0, 0 } } }, { { { 0, 0, 2 }, { 0, 0, 2 }, { 0, 1, 0 }, { 0, 0, 0 } } }, { { { 1, 0, 1 }, { 0, 1, 1 }, { 0, 2, 1 }, { 0, 0, 0 } } }, { { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 2, 0 }, { 0, 0, 0 } } }, { { { 1, 0, 1 }, { 0, 1, 1 }, { 0, 3, 1 }, { 0, 0, 0 } } }, { { { 1, 0, 2 }, { 0, 1, 2 }, { 0, 3, 0 }, { 0, 0, 0 } } }, { { { 2, 0, 1 }, { 0, 2, 1 }, { 0, 4, 1 }, { 0, 0, 0 } } }, { { { 2, 0, 0 }, { 0, 2, 0 }, { 0, 4, 0 }, { 0, 0, 0 } } }, { { { 2, 0, 1 }, { 0, 2, 1 }, { 0, 5, 1 }, { 0, 0, 0 } } }, { { { 2, 0, 2 }, { 0, 2, 2 }, { 0, 5, 0 }, { 0, 0, 0 } } }, { { { 3, 0, 1 }, { 0, 3, 1 }, { 0, 6, 1 }, { 0, 0, 0 } } }, { { { 3, 0, 0 }, { 0, 3, 0 }, { 0, 6, 0 }, { 0, 0, 0 } } }, { { { 3, 0, 1 }, { 0, 3, 1 }, { 0, 7, 1 }, { 0, 0, 0 } } }, { { { 3, 0, 2 }, { 0, 3, 2 }, { 0, 7, 0 }, { 0, 0, 0 } } }, { { { 4, 0, 1 }, { 0, 4, 1 }, { 0, 8, 1 }, { 0, 0, 0 } } }, { { { 4, 0, 0 }, { 0, 4, 0 }, { 0, 8, 0 }, { 0, 0, 0 } } }, { { { 4, 0, 1 }, { 0, 4, 1 }, { 0, 9, 1 }, { 0, 0, 0 } } }, { { { 4, 0, 2 }, { 0, 4, 2 }, { 0, 9, 0 }, { 0, 0, 0 } } }, { { { 5, 0, 1 }, { 0, 5, 1 }, { 0, 10, 1 }, { 0, 0, 0 } } }, { { { 5, 0, 0 }, { 0, 5, 0 }, { 0, 10, 0 }, { 0, 0, 0 } } }, { { { 5, 0, 1 }, { 0, 5, 1 }, { 0, 11, 1 }, { 0, 0, 0 } } }, { { { 5, 0, 2 }, { 0, 5, 2 }, { 0, 11, 0 }, { 0, 0, 0 } } }, { { { 6, 0, 1 }, { 0, 6, 1 }, { 0, 12, 1 }, { 0, 0, 0 } } }, { { { 6, 0, 0 }, { 0, 6, 0 }, { 0, 12, 0 }, { 0, 0, 0 } } }, { { { 6, 0, 1 }, { 0, 6, 1 }, { 0, 13, 1 }, { 0, 0, 0 } } }, { { { 6, 0, 2 }, { 0, 6, 2 }, { 0, 13, 0 }, { 0, 0, 0 } } }, { { { 7, 0, 1 }, { 0, 7, 1 }, { 0, 14, 1 }, { 0, 0, 0 } } }, { { { 7, 0, 0 }, { 0, 7, 0 }, { 0, 14, 0 }, { 0, 0, 0 } } }, { { { 7, 0, 1 }, { 0, 7, 1 }, { 0, 15, 1 }, { 0, 0, 0 } } }, { { { 7, 0, 2 }, { 0, 7, 2 }, { 0, 15, 0 }, { 0, 0, 0 } } }, { { { 8, 0, 1 }, { 0, 8, 1 }, { 0, 16, 1 }, { 0, 0, 0 } } }, { { { 8, 0, 0 }, { 0, 8, 0 }, { 0, 16, 0 }, { 0, 0, 0 } } }, { { { 8, 0, 1 }, { 0, 8, 1 }, { 0, 17, 1 }, { 0, 0, 0 } } }, { { { 8, 0, 2 }, { 0, 8, 2 }, { 0, 17, 0 }, { 0, 0, 0 } } }, { { { 9, 0, 1 }, { 0, 9, 1 }, { 0, 18, 1 }, { 0, 0, 0 } } }, { { { 9, 0, 0 }, { 0, 9, 0 }, { 0, 18, 0 }, { 0, 0, 0 } } }, { { { 9, 0, 1 }, { 0, 9, 1 }, { 0, 19, 1 }, { 0, 0, 0 } } }, { { { 9, 0, 2 }, { 0, 9, 2 }, { 0, 19, 0 }, { 0, 0, 0 } } }, { { { 10, 0, 1 }, { 0, 10, 1 }, { 0, 20, 1 }, { 0, 0, 0 } } }, { { { 10, 0, 0 }, { 0, 10, 0 }, { 0, 20, 0 }, { 0, 0, 0 } } }, { { { 10, 0, 1 }, { 0, 10, 1 }, { 0, 21, 1 }, { 0, 0, 0 } } }, { { { 10, 0, 2 }, { 0, 10, 2 }, { 0, 21, 0 }, { 0, 0, 0 } } }, { { { 11, 0, 1 }, { 0, 11, 1 }, { 0, 22, 1 }, { 0, 0, 0 } } }, { { { 11, 0, 0 }, { 0, 11, 0 }, { 0, 22, 0 }, { 0, 0, 0 } } }, { { { 11, 0, 1 }, { 0, 11, 1 }, { 0, 23, 1 }, { 0, 0, 0 } } }, { { { 11, 0, 2 }, { 0, 11, 2 }, { 0, 23, 0 }, { 0, 0, 0 } } }, { { { 12, 0, 1 }, { 0, 12, 1 }, { 0, 24, 1 }, { 0, 0, 0 } } }, { { { 12, 0, 0 }, { 0, 12, 0 }, { 0, 24, 0 }, { 0, 0, 0 } } }, { { { 12, 0, 1 }, { 0, 12, 1 }, { 0, 25, 1 }, { 0, 0, 0 } } }, { { { 12, 0, 2 }, { 0, 12, 2 }, { 0, 25, 0 }, { 0, 0, 0 } } }, { { { 13, 0, 1 }, { 0, 13, 1 }, { 0, 26, 1 }, { 0, 0, 0 } } }, { { { 13, 0, 0 }, { 0, 13, 0 }, { 0, 26, 0 }, { 0, 0, 0 } } }, { { { 13, 0, 1 }, { 0, 13, 1 }, { 0, 27, 1 }, { 0, 0, 0 } } }, { { { 13, 0, 2 }, { 0, 13, 2 }, { 0, 27, 0 }, { 0, 0, 0 } } }, { { { 14, 0, 1 }, { 0, 14, 1 }, { 0, 28, 1 }, { 0, 0, 0 } } }, { { { 14, 0, 0 }, { 0, 14, 0 }, { 0, 28, 0 }, { 0, 0, 0 } } }, { { { 14, 0, 1 }, { 0, 14, 1 }, { 0, 29, 1 }, { 0, 0, 0 } } }, { { { 14, 0, 2 }, { 0, 14, 2 }, { 0, 29, 0 }, { 0, 0, 0 } } }, { { { 15, 0, 1 }, { 0, 15, 1 }, { 0, 30, 1 }, { 0, 0, 0 } } }, { { { 15, 0, 0 }, { 0, 15, 0 }, { 0, 30, 0 }, { 0, 0, 0 } } }, { { { 15, 0, 1 }, { 0, 15, 1 }, { 0, 31, 1 }, { 0, 0, 0 } } }, { { { 15, 0, 2 }, { 0, 15, 2 }, { 0, 31, 0 }, { 0, 0, 0 } } }, { { { 16, 0, 2 }, { 0, 16, 2 }, { 1, 31, 1 }, { 0, 0, 0 } } }, { { { 16, 0, 1 }, { 0, 16, 1 }, { 1, 31, 0 }, { 0, 0, 0 } } }, { { { 16, 0, 0 }, { 0, 16, 0 }, { 0, 32, 0 }, { 0, 0, 0 } } }, { { { 16, 0, 1 }, { 0, 16, 1 }, { 2, 31, 0 }, { 0, 0, 0 } } }, { { { 16, 0, 2 }, { 0, 16, 2 }, { 0, 33, 0 }, { 0, 0, 0 } } }, { { { 17, 0, 1 }, { 0, 17, 1 }, { 3, 31, 0 }, { 0, 0, 0 } } }, { { { 17, 0, 0 }, { 0, 17, 0 }, { 0, 34, 0 }, { 0, 0, 0 } } }, { { { 17, 0, 1 }, { 0, 17, 1 }, { 4, 31, 0 }, { 0, 0, 0 } } }, { { { 17, 0, 2 }, { 0, 17, 2 }, { 0, 35, 0 }, { 0, 0, 0 } } }, { { { 18, 0, 1 }, { 0, 18, 1 }, { 5, 31, 0 }, { 0, 0, 0 } } }, { { { 18, 0, 0 }, { 0, 18, 0 }, { 0, 36, 0 }, { 0, 0, 0 } } }, { { { 18, 0, 1 }, { 0, 18, 1 }, { 6, 31, 0 }, { 0, 0, 0 } } }, { { { 18, 0, 2 }, { 0, 18, 2 }, { 0, 37, 0 }, { 0, 0, 0 } } }, { { { 19, 0, 1 }, { 0, 19, 1 }, { 7, 31, 0 }, { 0, 0, 0 } } }, { { { 19, 0, 0 }, { 0, 19, 0 }, { 0, 38, 0 }, { 0, 0, 0 } } }, { { { 19, 0, 1 }, { 0, 19, 1 }, { 8, 31, 0 }, { 0, 0, 0 } } }, { { { 19, 0, 2 }, { 0, 19, 2 }, { 0, 39, 0 }, { 0, 0, 0 } } }, { { { 20, 0, 1 }, { 0, 20, 1 }, { 9, 31, 0 }, { 0, 0, 0 } } }, { { { 20, 0, 0 }, { 0, 20, 0 }, { 0, 40, 0 }, { 0, 0, 0 } } }, { { { 20, 0, 1 }, { 0, 20, 1 }, { 10, 31, 0 }, { 0, 0, 0 } } }, { { { 20, 0, 2 }, { 0, 20, 2 }, { 0, 41, 0 }, { 0, 0, 0 } } }, { { { 21, 0, 1 }, { 0, 21, 1 }, { 11, 31, 0 }, { 0, 0, 0 } } }, { { { 21, 0, 0 }, { 0, 21, 0 }, { 0, 42, 0 }, { 0, 0, 0 } } }, { { { 21, 0, 1 }, { 0, 21, 1 }, { 12, 31, 0 }, { 0, 0, 0 } } }, { { { 21, 0, 2 }, { 0, 21, 2 }, { 0, 43, 0 }, { 0, 0, 0 } } }, { { { 22, 0, 1 }, { 0, 22, 1 }, { 13, 31, 0 }, { 0, 0, 0 } } }, { { { 22, 0, 0 }, { 0, 22, 0 }, { 0, 44, 0 }, { 0, 0, 0 } } }, { { { 22, 0, 1 }, { 0, 22, 1 }, { 14, 31, 0 }, { 0, 0, 0 } } }, { { { 22, 0, 2 }, { 0, 22, 2 }, { 0, 45, 0 }, { 0, 0, 0 } } }, { { { 23, 0, 1 }, { 0, 23, 1 }, { 15, 31, 0 }, { 0, 0, 0 } } }, { { { 23, 0, 0 }, { 0, 23, 0 }, { 0, 46, 0 }, { 0, 0, 0 } } }, { { { 23, 0, 1 }, { 0, 23, 1 }, { 0, 47, 1 }, { 0, 0, 0 } } }, { { { 23, 0, 2 }, { 0, 23, 2 }, { 0, 47, 0 }, { 0, 0, 0 } } }, { { { 24, 0, 1 }, { 0, 24, 1 }, { 0, 48, 1 }, { 0, 0, 0 } } }, { { { 24, 0, 0 }, { 0, 24, 0 }, { 0, 48, 0 }, { 0, 0, 0 } } }, { { { 24, 0, 1 }, { 0, 24, 1 }, { 0, 49, 1 }, { 0, 0, 0 } } }, { { { 24, 0, 2 }, { 0, 24, 2 }, { 0, 49, 0 }, { 0, 0, 0 } } }, { { { 25, 0, 1 }, { 0, 25, 1 }, { 0, 50, 1 }, { 0, 0, 0 } } }, { { { 25, 0, 0 }, { 0, 25, 0 }, { 0, 50, 0 }, { 0, 0, 0 } } }, { { { 25, 0, 1 }, { 0, 25, 1 }, { 0, 51, 1 }, { 0, 0, 0 } } }, { { { 25, 0, 2 }, { 0, 25, 2 }, { 0, 51, 0 }, { 0, 0, 0 } } }, { { { 26, 0, 1 }, { 0, 26, 1 }, { 0, 52, 1 }, { 0, 0, 0 } } }, { { { 26, 0, 0 }, { 0, 26, 0 }, { 0, 52, 0 }, { 0, 0, 0 } } }, { { { 26, 0, 1 }, { 0, 26, 1 }, { 0, 53, 1 }, { 0, 0, 0 } } }, { { { 26, 0, 2 }, { 0, 26, 2 }, { 0, 53, 0 }, { 0, 0, 0 } } }, { { { 27, 0, 1 }, { 0, 27, 1 }, { 0, 54, 1 }, { 0, 0, 0 } } }, { { { 27, 0, 0 }, { 0, 27, 0 }, { 0, 54, 0 }, { 0, 0, 0 } } }, { { { 27, 0, 1 }, { 0, 27, 1 }, { 0, 55, 1 }, { 0, 0, 0 } } }, { { { 27, 0, 2 }, { 0, 27, 2 }, { 0, 55, 0 }, { 0, 0, 0 } } }, { { { 28, 0, 1 }, { 0, 28, 1 }, { 0, 56, 1 }, { 0, 0, 0 } } }, { { { 28, 0, 0 }, { 0, 28, 0 }, { 0, 56, 0 }, { 0, 0, 0 } } }, { { { 28, 0, 1 }, { 0, 28, 1 }, { 0, 57, 1 }, { 0, 0, 0 } } }, { { { 28, 0, 2 }, { 0, 28, 2 }, { 0, 57, 0 }, { 0, 0, 0 } } }, { { { 29, 0, 1 }, { 0, 29, 1 }, { 0, 58, 1 }, { 0, 0, 0 } } }, { { { 29, 0, 0 }, { 0, 29, 0 }, { 0, 58, 0 }, { 0, 0, 0 } } }, { { { 29, 0, 1 }, { 0, 29, 1 }, { 0, 59, 1 }, { 0, 0, 0 } } }, { { { 29, 0, 2 }, { 0, 29, 2 }, { 0, 59, 0 }, { 0, 0, 0 } } }, { { { 30, 0, 1 }, { 0, 30, 1 }, { 0, 60, 1 }, { 0, 0, 0 } } }, { { { 30, 0, 0 }, { 0, 30, 0 }, { 0, 60, 0 }, { 0, 0, 0 } } }, { { { 30, 0, 1 }, { 0, 30, 1 }, { 0, 61, 1 }, { 0, 0, 0 } } }, { { { 30, 0, 2 }, { 0, 30, 2 }, { 0, 61, 0 }, { 0, 0, 0 } } }, { { { 31, 0, 1 }, { 0, 31, 1 }, { 0, 62, 1 }, { 0, 0, 0 } } }, { { { 31, 0, 0 }, { 0, 31, 0 }, { 0, 62, 0 }, { 0, 0, 0 } } }, { { { 31, 0, 1 }, { 0, 31, 1 }, { 0, 63, 1 }, { 0, 0, 0 } } }, { { { 31, 0, 2 }, { 0, 31, 2 }, { 0, 63, 0 }, { 0, 0, 0 } } }, { { { 32, 0, 2 }, { 0, 32, 2 }, { 1, 63, 1 }, { 0, 0, 0 } } }, { { { 32, 0, 1 }, { 0, 32, 1 }, { 1, 63, 0 }, { 0, 0, 0 } } }, { { { 32, 0, 0 }, { 0, 32, 0 }, { 16, 48, 0 }, { 0, 0, 0 } } }, { { { 32, 0, 1 }, { 0, 32, 1 }, { 2, 63, 0 }, { 0, 0, 0 } } }, { { { 32, 0, 2 }, { 0, 32, 2 }, { 16, 49, 0 }, { 0, 0, 0 } } }, { { { 33, 0, 1 }, { 0, 33, 1 }, { 3, 63, 0 }, { 0, 0, 0 } } }, { { { 33, 0, 0 }, { 0, 33, 0 }, { 16, 50, 0 }, { 0, 0, 0 } } }, { { { 33, 0, 1 }, { 0, 33, 1 }, { 4, 63, 0 }, { 0, 0, 0 } } }, { { { 33, 0, 2 }, { 0, 33, 2 }, { 16, 51, 0 }, { 0, 0, 0 } } }, { { { 34, 0, 1 }, { 0, 34, 1 }, { 5, 63, 0 }, { 0, 0, 0 } } }, { { { 34, 0, 0 }, { 0, 34, 0 }, { 16, 52, 0 }, { 0, 0, 0 } } }, { { { 34, 0, 1 }, { 0, 34, 1 }, { 6, 63, 0 }, { 0, 0, 0 } } }, { { { 34, 0, 2 }, { 0, 34, 2 }, { 16, 53, 0 }, { 0, 0, 0 } } }, { { { 35, 0, 1 }, { 0, 35, 1 }, { 7, 63, 0 }, { 0, 0, 0 } } }, { { { 35, 0, 0 }, { 0, 35, 0 }, { 16, 54, 0 }, { 0, 0, 0 } } }, { { { 35, 0, 1 }, { 0, 35, 1 }, { 8, 63, 0 }, { 0, 0, 0 } } }, { { { 35, 0, 2 }, { 0, 35, 2 }, { 16, 55, 0 }, { 0, 0, 0 } } }, { { { 36, 0, 1 }, { 0, 36, 1 }, { 9, 63, 0 }, { 0, 0, 0 } } }, { { { 36, 0, 0 }, { 0, 36, 0 }, { 16, 56, 0 }, { 0, 0, 0 } } }, { { { 36, 0, 1 }, { 0, 36, 1 }, { 10, 63, 0 }, { 0, 0, 0 } } }, { { { 36, 0, 2 }, { 0, 36, 2 }, { 16, 57, 0 }, { 0, 0, 0 } } }, { { { 37, 0, 1 }, { 0, 37, 1 }, { 11, 63, 0 }, { 0, 0, 0 } } }, { { { 37, 0, 0 }, { 0, 37, 0 }, { 16, 58, 0 }, { 0, 0, 0 } } }, { { { 37, 0, 1 }, { 0, 37, 1 }, { 12, 63, 0 }, { 0, 0, 0 } } }, { { { 37, 0, 2 }, { 0, 37, 2 }, { 16, 59, 0 }, { 0, 0, 0 } } }, { { { 38, 0, 1 }, { 0, 38, 1 }, { 13, 63, 0 }, { 0, 0, 0 } } }, { { { 38, 0, 0 }, { 0, 38, 0 }, { 16, 60, 0 }, { 0, 0, 0 } } }, { { { 38, 0, 1 }, { 0, 38, 1 }, { 14, 63, 0 }, { 0, 0, 0 } } }, { { { 38, 0, 2 }, { 0, 38, 2 }, { 16, 61, 0 }, { 0, 0, 0 } } }, { { { 39, 0, 1 }, { 0, 39, 1 }, { 15, 63, 0 }, { 0, 0, 0 } } }, { { { 39, 0, 0 }, { 0, 39, 0 }, { 16, 62, 0 }, { 0, 0, 0 } } }, { { { 39, 0, 1 }, { 0, 39, 1 }, { 16, 63, 1 }, { 0, 0, 0 } } }, { { { 39, 0, 2 }, { 0, 39, 2 }, { 16, 63, 0 }, { 0, 0, 0 } } }, { { { 40, 0, 1 }, { 0, 40, 1 }, { 17, 63, 1 }, { 0, 0, 0 } } }, { { { 40, 0, 0 }, { 0, 40, 0 }, { 17, 63, 0 }, { 0, 0, 0 } } }, { { { 40, 0, 1 }, { 0, 40, 1 }, { 18, 63, 1 }, { 0, 0, 0 } } }, { { { 40, 0, 2 }, { 0, 40, 2 }, { 18, 63, 0 }, { 0, 0, 0 } } }, { { { 41, 0, 1 }, { 0, 41, 1 }, { 19, 63, 1 }, { 0, 0, 0 } } }, { { { 41, 0, 0 }, { 0, 41, 0 }, { 19, 63, 0 }, { 0, 0, 0 } } }, { { { 41, 0, 1 }, { 0, 41, 1 }, { 20, 63, 1 }, { 0, 0, 0 } } }, { { { 41, 0, 2 }, { 0, 41, 2 }, { 20, 63, 0 }, { 0, 0, 0 } } }, { { { 42, 0, 1 }, { 0, 42, 1 }, { 21, 63, 1 }, { 0, 0, 0 } } }, { { { 42, 0, 0 }, { 0, 42, 0 }, { 21, 63, 0 }, { 0, 0, 0 } } }, { { { 42, 0, 1 }, { 0, 42, 1 }, { 22, 63, 1 }, { 0, 0, 0 } } }, { { { 42, 0, 2 }, { 0, 42, 2 }, { 22, 63, 0 }, { 0, 0, 0 } } }, { { { 43, 0, 1 }, { 0, 43, 1 }, { 23, 63, 1 }, { 0, 0, 0 } } }, { { { 43, 0, 0 }, { 0, 43, 0 }, { 23, 63, 0 }, { 0, 0, 0 } } }, { { { 43, 0, 1 }, { 0, 43, 1 }, { 24, 63, 1 }, { 0, 0, 0 } } }, { { { 43, 0, 2 }, { 0, 43, 2 }, { 24, 63, 0 }, { 0, 0, 0 } } }, { { { 44, 0, 1 }, { 0, 44, 1 }, { 25, 63, 1 }, { 0, 0, 0 } } }, { { { 44, 0, 0 }, { 0, 44, 0 }, { 25, 63, 0 }, { 0, 0, 0 } } }, { { { 44, 0, 1 }, { 0, 44, 1 }, { 26, 63, 1 }, { 0, 0, 0 } } }, { { { 44, 0, 2 }, { 0, 44, 2 }, { 26, 63, 0 }, { 0, 0, 0 } } }, { { { 45, 0, 1 }, { 0, 45, 1 }, { 27, 63, 1 }, { 0, 0, 0 } } }, { { { 45, 0, 0 }, { 0, 45, 0 }, { 27, 63, 0 }, { 0, 0, 0 } } }, { { { 45, 0, 1 }, { 0, 45, 1 }, { 28, 63, 1 }, { 0, 0, 0 } } }, { { { 45, 0, 2 }, { 0, 45, 2 }, { 28, 63, 0 }, { 0, 0, 0 } } }, { { { 46, 0, 1 }, { 0, 46, 1 }, { 29, 63, 1 }, { 0, 0, 0 } } }, { { { 46, 0, 0 }, { 0, 46, 0 }, { 29, 63, 0 }, { 0, 0, 0 } } }, { { { 46, 0, 1 }, { 0, 46, 1 }, { 30, 63, 1 }, { 0, 0, 0 } } }, { { { 46, 0, 2 }, { 0, 46, 2 }, { 30, 63, 0 }, { 0, 0, 0 } } }, { { { 47, 0, 1 }, { 0, 47, 1 }, { 31, 63, 1 }, { 0, 0, 0 } } }, { { { 47, 0, 0 }, { 0, 47, 0 }, { 31, 63, 0 }, { 0, 0, 0 } } }, { { { 47, 0, 1 }, { 0, 47, 1 }, { 32, 63, 1 }, { 0, 0, 0 } } }, { { { 47, 0, 2 }, { 0, 47, 2 }, { 32, 63, 0 }, { 0, 0, 0 } } }, { { { 48, 0, 2 }, { 0, 48, 2 }, { 33, 63, 1 }, { 0, 0, 0 } } }, { { { 48, 0, 1 }, { 0, 48, 1 }, { 33, 63, 0 }, { 0, 0, 0 } } }, { { { 48, 0, 0 }, { 0, 48, 0 }, { 48, 48, 0 }, { 0, 0, 0 } } }, { { { 48, 0, 1 }, { 0, 48, 1 }, { 34, 63, 0 }, { 0, 0, 0 } } }, { { { 48, 0, 2 }, { 0, 48, 2 }, { 48, 49, 0 }, { 0, 0, 0 } } }, { { { 49, 0, 1 }, { 0, 49, 1 }, { 35, 63, 0 }, { 0, 0, 0 } } }, { { { 49, 0, 0 }, { 0, 49, 0 }, { 48, 50, 0 }, { 0, 0, 0 } } }, { { { 49, 0, 1 }, { 0, 49, 1 }, { 36, 63, 0 }, { 0, 0, 0 } } }, { { { 49, 0, 2 }, { 0, 49, 2 }, { 48, 51, 0 }, { 0, 0, 0 } } }, { { { 50, 0, 1 }, { 0, 50, 1 }, { 37, 63, 0 }, { 0, 0, 0 } } }, { { { 50, 0, 0 }, { 0, 50, 0 }, { 48, 52, 0 }, { 0, 0, 0 } } }, { { { 50, 0, 1 }, { 0, 50, 1 }, { 38, 63, 0 }, { 0, 0, 0 } } }, { { { 50, 0, 2 }, { 0, 50, 2 }, { 48, 53, 0 }, { 0, 0, 0 } } }, { { { 51, 0, 1 }, { 0, 51, 1 }, { 39, 63, 0 }, { 0, 0, 0 } } }, { { { 51, 0, 0 }, { 0, 51, 0 }, { 48, 54, 0 }, { 0, 0, 0 } } }, { { { 51, 0, 1 }, { 0, 51, 1 }, { 40, 63, 0 }, { 0, 0, 0 } } }, { { { 51, 0, 2 }, { 0, 51, 2 }, { 48, 55, 0 }, { 0, 0, 0 } } }, { { { 52, 0, 1 }, { 0, 52, 1 }, { 41, 63, 0 }, { 0, 0, 0 } } }, { { { 52, 0, 0 }, { 0, 52, 0 }, { 48, 56, 0 }, { 0, 0, 0 } } }, { { { 52, 0, 1 }, { 0, 52, 1 }, { 42, 63, 0 }, { 0, 0, 0 } } }, { { { 52, 0, 2 }, { 0, 52, 2 }, { 48, 57, 0 }, { 0, 0, 0 } } }, { { { 53, 0, 1 }, { 0, 53, 1 }, { 43, 63, 0 }, { 0, 0, 0 } } }, { { { 53, 0, 0 }, { 0, 53, 0 }, { 48, 58, 0 }, { 0, 0, 0 } } }, { { { 53, 0, 1 }, { 0, 53, 1 }, { 44, 63, 0 }, { 0, 0, 0 } } }, { { { 53, 0, 2 }, { 0, 53, 2 }, { 48, 59, 0 }, { 0, 0, 0 } } }, { { { 54, 0, 1 }, { 0, 54, 1 }, { 45, 63, 0 }, { 0, 0, 0 } } }, { { { 54, 0, 0 }, { 0, 54, 0 }, { 48, 60, 0 }, { 0, 0, 0 } } }, { { { 54, 0, 1 }, { 0, 54, 1 }, { 46, 63, 0 }, { 0, 0, 0 } } }, { { { 54, 0, 2 }, { 0, 54, 2 }, { 48, 61, 0 }, { 0, 0, 0 } } }, { { { 55, 0, 1 }, { 0, 55, 1 }, { 47, 63, 0 }, { 0, 0, 0 } } }, { { { 55, 0, 0 }, { 0, 55, 0 }, { 48, 62, 0 }, { 0, 0, 0 } } }, { { { 55, 0, 1 }, { 0, 55, 1 }, { 48, 63, 1 }, { 0, 0, 0 } } }, { { { 55, 0, 2 }, { 0, 55, 2 }, { 48, 63, 0 }, { 0, 0, 0 } } }, { { { 56, 0, 1 }, { 0, 56, 1 }, { 49, 63, 1 }, { 0, 0, 0 } } }, { { { 56, 0, 0 }, { 0, 56, 0 }, { 49, 63, 0 }, { 0, 0, 0 } } }, { { { 56, 0, 1 }, { 0, 56, 1 }, { 50, 63, 1 }, { 0, 0, 0 } } }, { { { 56, 0, 2 }, { 0, 56, 2 }, { 50, 63, 0 }, { 0, 0, 0 } } }, { { { 57, 0, 1 }, { 0, 57, 1 }, { 51, 63, 1 }, { 0, 0, 0 } } }, { { { 57, 0, 0 }, { 0, 57, 0 }, { 51, 63, 0 }, { 0, 0, 0 } } }, { { { 57, 0, 1 }, { 0, 57, 1 }, { 52, 63, 1 }, { 0, 0, 0 } } }, { { { 57, 0, 2 }, { 0, 57, 2 }, { 52, 63, 0 }, { 0, 0, 0 } } }, { { { 58, 0, 1 }, { 0, 58, 1 }, { 53, 63, 1 }, { 0, 0, 0 } } }, { { { 58, 0, 0 }, { 0, 58, 0 }, { 53, 63, 0 }, { 0, 0, 0 } } }, { { { 58, 0, 1 }, { 0, 58, 1 }, { 54, 63, 1 }, { 0, 0, 0 } } }, { { { 58, 0, 2 }, { 0, 58, 2 }, { 54, 63, 0 }, { 0, 0, 0 } } }, { { { 59, 0, 1 }, { 0, 59, 1 }, { 55, 63, 1 }, { 0, 0, 0 } } }, { { { 59, 0, 0 }, { 0, 59, 0 }, { 55, 63, 0 }, { 0, 0, 0 } } }, { { { 59, 0, 1 }, { 0, 59, 1 }, { 56, 63, 1 }, { 0, 0, 0 } } }, { { { 59, 0, 2 }, { 0, 59, 2 }, { 56, 63, 0 }, { 0, 0, 0 } } }, { { { 60, 0, 1 }, { 0, 60, 1 }, { 57, 63, 1 }, { 0, 0, 0 } } }, { { { 60, 0, 0 }, { 0, 60, 0 }, { 57, 63, 0 }, { 0, 0, 0 } } }, { { { 60, 0, 1 }, { 0, 60, 1 }, { 58, 63, 1 }, { 0, 0, 0 } } }, { { { 60, 0, 2 }, { 0, 60, 2 }, { 58, 63, 0 }, { 0, 0, 0 } } }, { { { 61, 0, 1 }, { 0, 61, 1 }, { 59, 63, 1 }, { 0, 0, 0 } } }, { { { 61, 0, 0 }, { 0, 61, 0 }, { 59, 63, 0 }, { 0, 0, 0 } } }, { { { 61, 0, 1 }, { 0, 61, 1 }, { 60, 63, 1 }, { 0, 0, 0 } } }, { { { 61, 0, 2 }, { 0, 61, 2 }, { 60, 63, 0 }, { 0, 0, 0 } } }, { { { 62, 0, 1 }, { 0, 62, 1 }, { 61, 63, 1 }, { 0, 0, 0 } } }, { { { 62, 0, 0 }, { 0, 62, 0 }, { 61, 63, 0 }, { 0, 0, 0 } } }, { { { 62, 0, 1 }, { 0, 62, 1 }, { 62, 63, 1 }, { 0, 0, 0 } } }, { { { 62, 0, 2 }, { 0, 62, 2 }, { 62, 63, 0 }, { 0, 0, 0 } } }, { { { 63, 0, 1 }, { 0, 63, 1 }, { 63, 63, 1 }, { 0, 0, 0 } } }, { { { 63, 0, 0 }, { 0, 63, 0 }, { 63, 63, 0 }, { 0, 0, 0 } } } }; static SingleColourLookup const lookup_5_4[] = { { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } }, { { { 0, 0, 1 }, { 0, 0, 1 }, { 0, 1, 1 }, { 1, 0, 1 } } }, { { { 0, 0, 2 }, { 0, 0, 2 }, { 0, 1, 0 }, { 1, 0, 0 } } }, { { { 0, 0, 3 }, { 0, 0, 3 }, { 0, 1, 1 }, { 1, 0, 1 } } }, { { { 0, 0, 4 }, { 0, 0, 4 }, { 0, 2, 1 }, { 0, 1, 1 } } }, { { { 1, 0, 3 }, { 0, 1, 3 }, { 0, 2, 0 }, { 0, 1, 0 } } }, { { { 1, 0, 2 }, { 0, 1, 2 }, { 0, 2, 1 }, { 0, 1, 1 } } }, { { { 1, 0, 1 }, { 0, 1, 1 }, { 0, 3, 1 }, { 1, 1, 1 } } }, { { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 3, 0 }, { 1, 1, 0 } } }, { { { 1, 0, 1 }, { 0, 1, 1 }, { 1, 2, 1 }, { 0, 2, 1 } } }, { { { 1, 0, 2 }, { 0, 1, 2 }, { 1, 2, 0 }, { 0, 2, 0 } } }, { { { 1, 0, 3 }, { 0, 1, 3 }, { 0, 4, 0 }, { 4, 0, 0 } } }, { { { 1, 0, 4 }, { 0, 1, 4 }, { 0, 5, 1 }, { 1, 2, 1 } } }, { { { 2, 0, 3 }, { 0, 2, 3 }, { 0, 5, 0 }, { 1, 2, 0 } } }, { { { 2, 0, 2 }, { 0, 2, 2 }, { 0, 5, 1 }, { 1, 2, 1 } } }, { { { 2, 0, 1 }, { 0, 2, 1 }, { 0, 6, 1 }, { 0, 3, 1 } } }, { { { 2, 0, 0 }, { 0, 2, 0 }, { 0, 6, 0 }, { 0, 3, 0 } } }, { { { 2, 0, 1 }, { 0, 2, 1 }, { 2, 3, 1 }, { 1, 3, 1 } } }, { { { 2, 0, 2 }, { 0, 2, 2 }, { 2, 3, 0 }, { 1, 3, 0 } } }, { { { 2, 0, 3 }, { 0, 2, 3 }, { 0, 7, 0 }, { 5, 1, 0 } } }, { { { 2, 0, 4 }, { 0, 2, 4 }, { 1, 6, 1 }, { 2, 3, 1 } } }, { { { 3, 0, 3 }, { 0, 3, 3 }, { 1, 6, 0 }, { 2, 3, 0 } } }, { { { 3, 0, 2 }, { 0, 3, 2 }, { 0, 8, 0 }, { 0, 4, 0 } } }, { { { 3, 0, 1 }, { 0, 3, 1 }, { 0, 9, 1 }, { 1, 4, 1 } } }, { { { 3, 0, 0 }, { 0, 3, 0 }, { 0, 9, 0 }, { 1, 4, 0 } } }, { { { 3, 0, 1 }, { 0, 3, 1 }, { 0, 9, 1 }, { 1, 4, 1 } } }, { { { 3, 0, 2 }, { 0, 3, 2 }, { 0, 10, 1 }, { 0, 5, 1 } } }, { { { 3, 0, 3 }, { 0, 3, 3 }, { 0, 10, 0 }, { 0, 5, 0 } } }, { { { 3, 0, 4 }, { 0, 3, 4 }, { 2, 7, 1 }, { 5, 3, 1 } } }, { { { 4, 0, 4 }, { 0, 4, 4 }, { 2, 7, 0 }, { 5, 3, 0 } } }, { { { 4, 0, 3 }, { 0, 4, 3 }, { 0, 11, 0 }, { 1, 5, 0 } } }, { { { 4, 0, 2 }, { 0, 4, 2 }, { 1, 10, 1 }, { 0, 6, 1 } } }, { { { 4, 0, 1 }, { 0, 4, 1 }, { 1, 10, 0 }, { 0, 6, 0 } } }, { { { 4, 0, 0 }, { 0, 4, 0 }, { 0, 12, 0 }, { 4, 4, 0 } } }, { { { 4, 0, 1 }, { 0, 4, 1 }, { 0, 13, 1 }, { 1, 6, 1 } } }, { { { 4, 0, 2 }, { 0, 4, 2 }, { 0, 13, 0 }, { 1, 6, 0 } } }, { { { 4, 0, 3 }, { 0, 4, 3 }, { 0, 13, 1 }, { 1, 6, 1 } } }, { { { 4, 0, 4 }, { 0, 4, 4 }, { 0, 14, 1 }, { 0, 7, 1 } } }, { { { 5, 0, 3 }, { 0, 5, 3 }, { 0, 14, 0 }, { 0, 7, 0 } } }, { { { 5, 0, 2 }, { 0, 5, 2 }, { 2, 11, 1 }, { 1, 7, 1 } } }, { { { 5, 0, 1 }, { 0, 5, 1 }, { 2, 11, 0 }, { 1, 7, 0 } } }, { { { 5, 0, 0 }, { 0, 5, 0 }, { 0, 15, 0 }, { 5, 5, 0 } } }, { { { 5, 0, 1 }, { 0, 5, 1 }, { 1, 14, 1 }, { 2, 7, 1 } } }, { { { 5, 0, 2 }, { 0, 5, 2 }, { 1, 14, 0 }, { 2, 7, 0 } } }, { { { 5, 0, 3 }, { 0, 5, 3 }, { 0, 16, 0 }, { 0, 8, 0 } } }, { { { 5, 0, 4 }, { 0, 5, 4 }, { 0, 17, 1 }, { 1, 8, 1 } } }, { { { 6, 0, 3 }, { 0, 6, 3 }, { 0, 17, 0 }, { 1, 8, 0 } } }, { { { 6, 0, 2 }, { 0, 6, 2 }, { 0, 17, 1 }, { 1, 8, 1 } } }, { { { 6, 0, 1 }, { 0, 6, 1 }, { 0, 18, 1 }, { 0, 9, 1 } } }, { { { 6, 0, 0 }, { 0, 6, 0 }, { 0, 18, 0 }, { 0, 9, 0 } } }, { { { 6, 0, 1 }, { 0, 6, 1 }, { 2, 15, 1 }, { 5, 7, 1 } } }, { { { 6, 0, 2 }, { 0, 6, 2 }, { 2, 15, 0 }, { 5, 7, 0 } } }, { { { 6, 0, 3 }, { 0, 6, 3 }, { 0, 19, 0 }, { 1, 9, 0 } } }, { { { 6, 0, 4 }, { 0, 6, 4 }, { 1, 18, 1 }, { 0, 10, 1 } } }, { { { 7, 0, 3 }, { 0, 7, 3 }, { 1, 18, 0 }, { 0, 10, 0 } } }, { { { 7, 0, 2 }, { 0, 7, 2 }, { 0, 20, 0 }, { 4, 8, 0 } } }, { { { 7, 0, 1 }, { 0, 7, 1 }, { 0, 21, 1 }, { 1, 10, 1 } } }, { { { 7, 0, 0 }, { 0, 7, 0 }, { 0, 21, 0 }, { 1, 10, 0 } } }, { { { 7, 0, 1 }, { 0, 7, 1 }, { 0, 21, 1 }, { 1, 10, 1 } } }, { { { 7, 0, 2 }, { 0, 7, 2 }, { 0, 22, 1 }, { 0, 11, 1 } } }, { { { 7, 0, 3 }, { 0, 7, 3 }, { 0, 22, 0 }, { 0, 11, 0 } } }, { { { 7, 0, 4 }, { 0, 7, 4 }, { 2, 19, 1 }, { 1, 11, 1 } } }, { { { 8, 0, 4 }, { 0, 8, 4 }, { 2, 19, 0 }, { 1, 11, 0 } } }, { { { 8, 0, 3 }, { 0, 8, 3 }, { 0, 23, 0 }, { 5, 9, 0 } } }, { { { 8, 0, 2 }, { 0, 8, 2 }, { 1, 22, 1 }, { 2, 11, 1 } } }, { { { 8, 0, 1 }, { 0, 8, 1 }, { 1, 22, 0 }, { 2, 11, 0 } } }, { { { 8, 0, 0 }, { 0, 8, 0 }, { 0, 24, 0 }, { 0, 12, 0 } } }, { { { 8, 0, 1 }, { 0, 8, 1 }, { 0, 25, 1 }, { 1, 12, 1 } } }, { { { 8, 0, 2 }, { 0, 8, 2 }, { 0, 25, 0 }, { 1, 12, 0 } } }, { { { 8, 0, 3 }, { 0, 8, 3 }, { 0, 25, 1 }, { 1, 12, 1 } } }, { { { 8, 0, 4 }, { 0, 8, 4 }, { 0, 26, 1 }, { 0, 13, 1 } } }, { { { 9, 0, 3 }, { 0, 9, 3 }, { 0, 26, 0 }, { 0, 13, 0 } } }, { { { 9, 0, 2 }, { 0, 9, 2 }, { 2, 23, 1 }, { 5, 11, 1 } } }, { { { 9, 0, 1 }, { 0, 9, 1 }, { 2, 23, 0 }, { 5, 11, 0 } } }, { { { 9, 0, 0 }, { 0, 9, 0 }, { 0, 27, 0 }, { 1, 13, 0 } } }, { { { 9, 0, 1 }, { 0, 9, 1 }, { 1, 26, 1 }, { 0, 14, 1 } } }, { { { 9, 0, 2 }, { 0, 9, 2 }, { 1, 26, 0 }, { 0, 14, 0 } } }, { { { 9, 0, 3 }, { 0, 9, 3 }, { 0, 28, 0 }, { 4, 12, 0 } } }, { { { 9, 0, 4 }, { 0, 9, 4 }, { 0, 29, 1 }, { 1, 14, 1 } } }, { { { 10, 0, 3 }, { 0, 10, 3 }, { 0, 29, 0 }, { 1, 14, 0 } } }, { { { 10, 0, 2 }, { 0, 10, 2 }, { 0, 29, 1 }, { 1, 14, 1 } } }, { { { 10, 0, 1 }, { 0, 10, 1 }, { 0, 30, 1 }, { 0, 15, 1 } } }, { { { 10, 0, 0 }, { 0, 10, 0 }, { 0, 30, 0 }, { 0, 15, 0 } } }, { { { 10, 0, 1 }, { 0, 10, 1 }, { 2, 27, 1 }, { 1, 15, 1 } } }, { { { 10, 0, 2 }, { 0, 10, 2 }, { 2, 27, 0 }, { 1, 15, 0 } } }, { { { 10, 0, 3 }, { 0, 10, 3 }, { 0, 31, 0 }, { 5, 13, 0 } } }, { { { 10, 0, 4 }, { 0, 10, 4 }, { 1, 30, 1 }, { 2, 15, 1 } } }, { { { 11, 0, 3 }, { 0, 11, 3 }, { 1, 30, 0 }, { 2, 15, 0 } } }, { { { 11, 0, 2 }, { 0, 11, 2 }, { 4, 24, 0 }, { 0, 16, 0 } } }, { { { 11, 0, 1 }, { 0, 11, 1 }, { 1, 31, 1 }, { 1, 16, 1 } } }, { { { 11, 0, 0 }, { 0, 11, 0 }, { 1, 31, 0 }, { 1, 16, 0 } } }, { { { 11, 0, 1 }, { 0, 11, 1 }, { 1, 31, 1 }, { 1, 16, 1 } } }, { { { 11, 0, 2 }, { 0, 11, 2 }, { 2, 30, 1 }, { 0, 17, 1 } } }, { { { 11, 0, 3 }, { 0, 11, 3 }, { 2, 30, 0 }, { 0, 17, 0 } } }, { { { 11, 0, 4 }, { 0, 11, 4 }, { 2, 31, 1 }, { 5, 15, 1 } } }, { { { 12, 0, 4 }, { 0, 12, 4 }, { 2, 31, 0 }, { 5, 15, 0 } } }, { { { 12, 0, 3 }, { 0, 12, 3 }, { 4, 27, 0 }, { 1, 17, 0 } } }, { { { 12, 0, 2 }, { 0, 12, 2 }, { 3, 30, 1 }, { 0, 18, 1 } } }, { { { 12, 0, 1 }, { 0, 12, 1 }, { 3, 30, 0 }, { 0, 18, 0 } } }, { { { 12, 0, 0 }, { 0, 12, 0 }, { 4, 28, 0 }, { 4, 16, 0 } } }, { { { 12, 0, 1 }, { 0, 12, 1 }, { 3, 31, 1 }, { 1, 18, 1 } } }, { { { 12, 0, 2 }, { 0, 12, 2 }, { 3, 31, 0 }, { 1, 18, 0 } } }, { { { 12, 0, 3 }, { 0, 12, 3 }, { 3, 31, 1 }, { 1, 18, 1 } } }, { { { 12, 0, 4 }, { 0, 12, 4 }, { 4, 30, 1 }, { 0, 19, 1 } } }, { { { 13, 0, 3 }, { 0, 13, 3 }, { 4, 30, 0 }, { 0, 19, 0 } } }, { { { 13, 0, 2 }, { 0, 13, 2 }, { 6, 27, 1 }, { 1, 19, 1 } } }, { { { 13, 0, 1 }, { 0, 13, 1 }, { 6, 27, 0 }, { 1, 19, 0 } } }, { { { 13, 0, 0 }, { 0, 13, 0 }, { 4, 31, 0 }, { 5, 17, 0 } } }, { { { 13, 0, 1 }, { 0, 13, 1 }, { 5, 30, 1 }, { 2, 19, 1 } } }, { { { 13, 0, 2 }, { 0, 13, 2 }, { 5, 30, 0 }, { 2, 19, 0 } } }, { { { 13, 0, 3 }, { 0, 13, 3 }, { 8, 24, 0 }, { 0, 20, 0 } } }, { { { 13, 0, 4 }, { 0, 13, 4 }, { 5, 31, 1 }, { 1, 20, 1 } } }, { { { 14, 0, 3 }, { 0, 14, 3 }, { 5, 31, 0 }, { 1, 20, 0 } } }, { { { 14, 0, 2 }, { 0, 14, 2 }, { 5, 31, 1 }, { 1, 20, 1 } } }, { { { 14, 0, 1 }, { 0, 14, 1 }, { 6, 30, 1 }, { 0, 21, 1 } } }, { { { 14, 0, 0 }, { 0, 14, 0 }, { 6, 30, 0 }, { 0, 21, 0 } } }, { { { 14, 0, 1 }, { 0, 14, 1 }, { 6, 31, 1 }, { 5, 19, 1 } } }, { { { 14, 0, 2 }, { 0, 14, 2 }, { 6, 31, 0 }, { 5, 19, 0 } } }, { { { 14, 0, 3 }, { 0, 14, 3 }, { 8, 27, 0 }, { 1, 21, 0 } } }, { { { 14, 0, 4 }, { 0, 14, 4 }, { 7, 30, 1 }, { 0, 22, 1 } } }, { { { 15, 0, 3 }, { 0, 15, 3 }, { 7, 30, 0 }, { 0, 22, 0 } } }, { { { 15, 0, 2 }, { 0, 15, 2 }, { 8, 28, 0 }, { 4, 20, 0 } } }, { { { 15, 0, 1 }, { 0, 15, 1 }, { 7, 31, 1 }, { 1, 22, 1 } } }, { { { 15, 0, 0 }, { 0, 15, 0 }, { 7, 31, 0 }, { 1, 22, 0 } } }, { { { 15, 0, 1 }, { 0, 15, 1 }, { 7, 31, 1 }, { 1, 22, 1 } } }, { { { 15, 0, 2 }, { 0, 15, 2 }, { 8, 30, 1 }, { 0, 23, 1 } } }, { { { 15, 0, 3 }, { 0, 15, 3 }, { 8, 30, 0 }, { 0, 23, 0 } } }, { { { 15, 0, 4 }, { 0, 15, 4 }, { 10, 27, 1 }, { 1, 23, 1 } } }, { { { 16, 0, 4 }, { 0, 16, 4 }, { 10, 27, 0 }, { 1, 23, 0 } } }, { { { 16, 0, 3 }, { 0, 16, 3 }, { 8, 31, 0 }, { 5, 21, 0 } } }, { { { 16, 0, 2 }, { 0, 16, 2 }, { 9, 30, 1 }, { 2, 23, 1 } } }, { { { 16, 0, 1 }, { 0, 16, 1 }, { 9, 30, 0 }, { 2, 23, 0 } } }, { { { 16, 0, 0 }, { 0, 16, 0 }, { 12, 24, 0 }, { 0, 24, 0 } } }, { { { 16, 0, 1 }, { 0, 16, 1 }, { 9, 31, 1 }, { 1, 24, 1 } } }, { { { 16, 0, 2 }, { 0, 16, 2 }, { 9, 31, 0 }, { 1, 24, 0 } } }, { { { 16, 0, 3 }, { 0, 16, 3 }, { 9, 31, 1 }, { 1, 24, 1 } } }, { { { 16, 0, 4 }, { 0, 16, 4 }, { 10, 30, 1 }, { 0, 25, 1 } } }, { { { 17, 0, 3 }, { 0, 17, 3 }, { 10, 30, 0 }, { 0, 25, 0 } } }, { { { 17, 0, 2 }, { 0, 17, 2 }, { 10, 31, 1 }, { 5, 23, 1 } } }, { { { 17, 0, 1 }, { 0, 17, 1 }, { 10, 31, 0 }, { 5, 23, 0 } } }, { { { 17, 0, 0 }, { 0, 17, 0 }, { 12, 27, 0 }, { 1, 25, 0 } } }, { { { 17, 0, 1 }, { 0, 17, 1 }, { 11, 30, 1 }, { 0, 26, 1 } } }, { { { 17, 0, 2 }, { 0, 17, 2 }, { 11, 30, 0 }, { 0, 26, 0 } } }, { { { 17, 0, 3 }, { 0, 17, 3 }, { 12, 28, 0 }, { 4, 24, 0 } } }, { { { 17, 0, 4 }, { 0, 17, 4 }, { 11, 31, 1 }, { 1, 26, 1 } } }, { { { 18, 0, 3 }, { 0, 18, 3 }, { 11, 31, 0 }, { 1, 26, 0 } } }, { { { 18, 0, 2 }, { 0, 18, 2 }, { 11, 31, 1 }, { 1, 26, 1 } } }, { { { 18, 0, 1 }, { 0, 18, 1 }, { 12, 30, 1 }, { 0, 27, 1 } } }, { { { 18, 0, 0 }, { 0, 18, 0 }, { 12, 30, 0 }, { 0, 27, 0 } } }, { { { 18, 0, 1 }, { 0, 18, 1 }, { 14, 27, 1 }, { 1, 27, 1 } } }, { { { 18, 0, 2 }, { 0, 18, 2 }, { 14, 27, 0 }, { 1, 27, 0 } } }, { { { 18, 0, 3 }, { 0, 18, 3 }, { 12, 31, 0 }, { 5, 25, 0 } } }, { { { 18, 0, 4 }, { 0, 18, 4 }, { 13, 30, 1 }, { 2, 27, 1 } } }, { { { 19, 0, 3 }, { 0, 19, 3 }, { 13, 30, 0 }, { 2, 27, 0 } } }, { { { 19, 0, 2 }, { 0, 19, 2 }, { 16, 24, 0 }, { 0, 28, 0 } } }, { { { 19, 0, 1 }, { 0, 19, 1 }, { 13, 31, 1 }, { 1, 28, 1 } } }, { { { 19, 0, 0 }, { 0, 19, 0 }, { 13, 31, 0 }, { 1, 28, 0 } } }, { { { 19, 0, 1 }, { 0, 19, 1 }, { 13, 31, 1 }, { 1, 28, 1 } } }, { { { 19, 0, 2 }, { 0, 19, 2 }, { 14, 30, 1 }, { 0, 29, 1 } } }, { { { 19, 0, 3 }, { 0, 19, 3 }, { 14, 30, 0 }, { 0, 29, 0 } } }, { { { 19, 0, 4 }, { 0, 19, 4 }, { 14, 31, 1 }, { 5, 27, 1 } } }, { { { 20, 0, 4 }, { 0, 20, 4 }, { 14, 31, 0 }, { 5, 27, 0 } } }, { { { 20, 0, 3 }, { 0, 20, 3 }, { 16, 27, 0 }, { 1, 29, 0 } } }, { { { 20, 0, 2 }, { 0, 20, 2 }, { 15, 30, 1 }, { 0, 30, 1 } } }, { { { 20, 0, 1 }, { 0, 20, 1 }, { 15, 30, 0 }, { 0, 30, 0 } } }, { { { 20, 0, 0 }, { 0, 20, 0 }, { 16, 28, 0 }, { 4, 28, 0 } } }, { { { 20, 0, 1 }, { 0, 20, 1 }, { 15, 31, 1 }, { 1, 30, 1 } } }, { { { 20, 0, 2 }, { 0, 20, 2 }, { 15, 31, 0 }, { 1, 30, 0 } } }, { { { 20, 0, 3 }, { 0, 20, 3 }, { 15, 31, 1 }, { 1, 30, 1 } } }, { { { 20, 0, 4 }, { 0, 20, 4 }, { 16, 30, 1 }, { 0, 31, 1 } } }, { { { 21, 0, 3 }, { 0, 21, 3 }, { 16, 30, 0 }, { 0, 31, 0 } } }, { { { 21, 0, 2 }, { 0, 21, 2 }, { 18, 27, 1 }, { 1, 31, 1 } } }, { { { 21, 0, 1 }, { 0, 21, 1 }, { 18, 27, 0 }, { 1, 31, 0 } } }, { { { 21, 0, 0 }, { 0, 21, 0 }, { 16, 31, 0 }, { 5, 29, 0 } } }, { { { 21, 0, 1 }, { 0, 21, 1 }, { 17, 30, 1 }, { 2, 31, 1 } } }, { { { 21, 0, 2 }, { 0, 21, 2 }, { 17, 30, 0 }, { 2, 31, 0 } } }, { { { 21, 0, 3 }, { 0, 21, 3 }, { 20, 24, 0 }, { 8, 28, 0 } } }, { { { 21, 0, 4 }, { 0, 21, 4 }, { 17, 31, 1 }, { 3, 31, 1 } } }, { { { 22, 0, 3 }, { 0, 22, 3 }, { 17, 31, 0 }, { 3, 31, 0 } } }, { { { 22, 0, 2 }, { 0, 22, 2 }, { 17, 31, 1 }, { 3, 31, 1 } } }, { { { 22, 0, 1 }, { 0, 22, 1 }, { 18, 30, 1 }, { 4, 31, 1 } } }, { { { 22, 0, 0 }, { 0, 22, 0 }, { 18, 30, 0 }, { 4, 31, 0 } } }, { { { 22, 0, 1 }, { 0, 22, 1 }, { 18, 31, 1 }, { 5, 31, 1 } } }, { { { 22, 0, 2 }, { 0, 22, 2 }, { 18, 31, 0 }, { 5, 31, 0 } } }, { { { 22, 0, 3 }, { 0, 22, 3 }, { 20, 27, 0 }, { 9, 29, 0 } } }, { { { 22, 0, 4 }, { 0, 22, 4 }, { 19, 30, 1 }, { 6, 31, 1 } } }, { { { 23, 0, 3 }, { 0, 23, 3 }, { 19, 30, 0 }, { 6, 31, 0 } } }, { { { 23, 0, 2 }, { 0, 23, 2 }, { 20, 28, 0 }, { 12, 28, 0 } } }, { { { 23, 0, 1 }, { 0, 23, 1 }, { 19, 31, 1 }, { 7, 31, 1 } } }, { { { 23, 0, 0 }, { 0, 23, 0 }, { 19, 31, 0 }, { 7, 31, 0 } } }, { { { 23, 0, 1 }, { 0, 23, 1 }, { 19, 31, 1 }, { 7, 31, 1 } } }, { { { 23, 0, 2 }, { 0, 23, 2 }, { 20, 30, 1 }, { 8, 31, 1 } } }, { { { 23, 0, 3 }, { 0, 23, 3 }, { 20, 30, 0 }, { 8, 31, 0 } } }, { { { 23, 0, 4 }, { 0, 23, 4 }, { 22, 27, 1 }, { 9, 31, 1 } } }, { { { 24, 0, 4 }, { 0, 24, 4 }, { 22, 27, 0 }, { 9, 31, 0 } } }, { { { 24, 0, 3 }, { 0, 24, 3 }, { 20, 31, 0 }, { 13, 29, 0 } } }, { { { 24, 0, 2 }, { 0, 24, 2 }, { 21, 30, 1 }, { 10, 31, 1 } } }, { { { 24, 0, 1 }, { 0, 24, 1 }, { 21, 30, 0 }, { 10, 31, 0 } } }, { { { 24, 0, 0 }, { 0, 24, 0 }, { 24, 24, 0 }, { 16, 28, 0 } } }, { { { 24, 0, 1 }, { 0, 24, 1 }, { 21, 31, 1 }, { 11, 31, 1 } } }, { { { 24, 0, 2 }, { 0, 24, 2 }, { 21, 31, 0 }, { 11, 31, 0 } } }, { { { 24, 0, 3 }, { 0, 24, 3 }, { 21, 31, 1 }, { 11, 31, 1 } } }, { { { 24, 0, 4 }, { 0, 24, 4 }, { 22, 30, 1 }, { 12, 31, 1 } } }, { { { 25, 0, 3 }, { 0, 25, 3 }, { 22, 30, 0 }, { 12, 31, 0 } } }, { { { 25, 0, 2 }, { 0, 25, 2 }, { 22, 31, 1 }, { 13, 31, 1 } } }, { { { 25, 0, 1 }, { 0, 25, 1 }, { 22, 31, 0 }, { 13, 31, 0 } } }, { { { 25, 0, 0 }, { 0, 25, 0 }, { 24, 27, 0 }, { 17, 29, 0 } } }, { { { 25, 0, 1 }, { 0, 25, 1 }, { 23, 30, 1 }, { 14, 31, 1 } } }, { { { 25, 0, 2 }, { 0, 25, 2 }, { 23, 30, 0 }, { 14, 31, 0 } } }, { { { 25, 0, 3 }, { 0, 25, 3 }, { 24, 28, 0 }, { 20, 28, 0 } } }, { { { 25, 0, 4 }, { 0, 25, 4 }, { 23, 31, 1 }, { 15, 31, 1 } } }, { { { 26, 0, 3 }, { 0, 26, 3 }, { 23, 31, 0 }, { 15, 31, 0 } } }, { { { 26, 0, 2 }, { 0, 26, 2 }, { 23, 31, 1 }, { 15, 31, 1 } } }, { { { 26, 0, 1 }, { 0, 26, 1 }, { 24, 30, 1 }, { 16, 31, 1 } } }, { { { 26, 0, 0 }, { 0, 26, 0 }, { 24, 30, 0 }, { 16, 31, 0 } } }, { { { 26, 0, 1 }, { 0, 26, 1 }, { 26, 27, 1 }, { 17, 31, 1 } } }, { { { 26, 0, 2 }, { 0, 26, 2 }, { 26, 27, 0 }, { 17, 31, 0 } } }, { { { 26, 0, 3 }, { 0, 26, 3 }, { 24, 31, 0 }, { 21, 29, 0 } } }, { { { 26, 0, 4 }, { 0, 26, 4 }, { 25, 30, 1 }, { 18, 31, 1 } } }, { { { 27, 0, 3 }, { 0, 27, 3 }, { 25, 30, 0 }, { 18, 31, 0 } } }, { { { 27, 0, 2 }, { 0, 27, 2 }, { 28, 24, 0 }, { 24, 28, 0 } } }, { { { 27, 0, 1 }, { 0, 27, 1 }, { 25, 31, 1 }, { 19, 31, 1 } } }, { { { 27, 0, 0 }, { 0, 27, 0 }, { 25, 31, 0 }, { 19, 31, 0 } } }, { { { 27, 0, 1 }, { 0, 27, 1 }, { 25, 31, 1 }, { 19, 31, 1 } } }, { { { 27, 0, 2 }, { 0, 27, 2 }, { 26, 30, 1 }, { 20, 31, 1 } } }, { { { 27, 0, 3 }, { 0, 27, 3 }, { 26, 30, 0 }, { 20, 31, 0 } } }, { { { 27, 0, 4 }, { 0, 27, 4 }, { 26, 31, 1 }, { 21, 31, 1 } } }, { { { 28, 0, 4 }, { 0, 28, 4 }, { 26, 31, 0 }, { 21, 31, 0 } } }, { { { 28, 0, 3 }, { 0, 28, 3 }, { 28, 27, 0 }, { 25, 29, 0 } } }, { { { 28, 0, 2 }, { 0, 28, 2 }, { 27, 30, 1 }, { 22, 31, 1 } } }, { { { 28, 0, 1 }, { 0, 28, 1 }, { 27, 30, 0 }, { 22, 31, 0 } } }, { { { 28, 0, 0 }, { 0, 28, 0 }, { 28, 28, 0 }, { 28, 28, 0 } } }, { { { 28, 0, 1 }, { 0, 28, 1 }, { 27, 31, 1 }, { 23, 31, 1 } } }, { { { 28, 0, 2 }, { 0, 28, 2 }, { 27, 31, 0 }, { 23, 31, 0 } } }, { { { 28, 0, 3 }, { 0, 28, 3 }, { 27, 31, 1 }, { 23, 31, 1 } } }, { { { 28, 0, 4 }, { 0, 28, 4 }, { 28, 30, 1 }, { 24, 31, 1 } } }, { { { 29, 0, 3 }, { 0, 29, 3 }, { 28, 30, 0 }, { 24, 31, 0 } } }, { { { 29, 0, 2 }, { 0, 29, 2 }, { 30, 27, 1 }, { 25, 31, 1 } } }, { { { 29, 0, 1 }, { 0, 29, 1 }, { 30, 27, 0 }, { 25, 31, 0 } } }, { { { 29, 0, 0 }, { 0, 29, 0 }, { 28, 31, 0 }, { 29, 29, 0 } } }, { { { 29, 0, 1 }, { 0, 29, 1 }, { 29, 30, 1 }, { 26, 31, 1 } } }, { { { 29, 0, 2 }, { 0, 29, 2 }, { 29, 30, 0 }, { 26, 31, 0 } } }, { { { 29, 0, 3 }, { 0, 29, 3 }, { 29, 30, 1 }, { 26, 31, 1 } } }, { { { 29, 0, 4 }, { 0, 29, 4 }, { 29, 31, 1 }, { 27, 31, 1 } } }, { { { 30, 0, 3 }, { 0, 30, 3 }, { 29, 31, 0 }, { 27, 31, 0 } } }, { { { 30, 0, 2 }, { 0, 30, 2 }, { 29, 31, 1 }, { 27, 31, 1 } } }, { { { 30, 0, 1 }, { 0, 30, 1 }, { 30, 30, 1 }, { 28, 31, 1 } } }, { { { 30, 0, 0 }, { 0, 30, 0 }, { 30, 30, 0 }, { 28, 31, 0 } } }, { { { 30, 0, 1 }, { 0, 30, 1 }, { 30, 31, 1 }, { 29, 31, 1 } } }, { { { 30, 0, 2 }, { 0, 30, 2 }, { 30, 31, 0 }, { 29, 31, 0 } } }, { { { 30, 0, 3 }, { 0, 30, 3 }, { 30, 31, 1 }, { 29, 31, 1 } } }, { { { 30, 0, 4 }, { 0, 30, 4 }, { 31, 30, 1 }, { 30, 31, 1 } } }, { { { 31, 0, 3 }, { 0, 31, 3 }, { 31, 30, 0 }, { 30, 31, 0 } } }, { { { 31, 0, 2 }, { 0, 31, 2 }, { 31, 30, 1 }, { 30, 31, 1 } } }, { { { 31, 0, 1 }, { 0, 31, 1 }, { 31, 31, 1 }, { 31, 31, 1 } } }, { { { 31, 0, 0 }, { 0, 31, 0 }, { 31, 31, 0 }, { 31, 31, 0 } } } }; static SingleColourLookup const lookup_6_4[] = { { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } } }, { { { 0, 0, 1 }, { 0, 0, 1 }, { 0, 1, 0 }, { 1, 0, 0 } } }, { { { 0, 0, 2 }, { 0, 0, 2 }, { 0, 2, 0 }, { 0, 1, 0 } } }, { { { 1, 0, 1 }, { 0, 1, 1 }, { 0, 3, 1 }, { 1, 1, 1 } } }, { { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 3, 0 }, { 1, 1, 0 } } }, { { { 1, 0, 1 }, { 0, 1, 1 }, { 0, 4, 0 }, { 0, 2, 0 } } }, { { { 1, 0, 2 }, { 0, 1, 2 }, { 0, 5, 0 }, { 1, 2, 0 } } }, { { { 2, 0, 1 }, { 0, 2, 1 }, { 0, 6, 1 }, { 0, 3, 1 } } }, { { { 2, 0, 0 }, { 0, 2, 0 }, { 0, 6, 0 }, { 0, 3, 0 } } }, { { { 2, 0, 1 }, { 0, 2, 1 }, { 0, 7, 0 }, { 1, 3, 0 } } }, { { { 2, 0, 2 }, { 0, 2, 2 }, { 0, 8, 0 }, { 0, 4, 0 } } }, { { { 3, 0, 1 }, { 0, 3, 1 }, { 0, 9, 1 }, { 1, 4, 1 } } }, { { { 3, 0, 0 }, { 0, 3, 0 }, { 0, 9, 0 }, { 1, 4, 0 } } }, { { { 3, 0, 1 }, { 0, 3, 1 }, { 0, 10, 0 }, { 0, 5, 0 } } }, { { { 3, 0, 2 }, { 0, 3, 2 }, { 0, 11, 0 }, { 1, 5, 0 } } }, { { { 4, 0, 1 }, { 0, 4, 1 }, { 0, 12, 1 }, { 0, 6, 1 } } }, { { { 4, 0, 0 }, { 0, 4, 0 }, { 0, 12, 0 }, { 0, 6, 0 } } }, { { { 4, 0, 1 }, { 0, 4, 1 }, { 0, 13, 0 }, { 1, 6, 0 } } }, { { { 4, 0, 2 }, { 0, 4, 2 }, { 0, 14, 0 }, { 0, 7, 0 } } }, { { { 5, 0, 1 }, { 0, 5, 1 }, { 0, 15, 1 }, { 1, 7, 1 } } }, { { { 5, 0, 0 }, { 0, 5, 0 }, { 0, 15, 0 }, { 1, 7, 0 } } }, { { { 5, 0, 1 }, { 0, 5, 1 }, { 0, 16, 0 }, { 0, 8, 0 } } }, { { { 5, 0, 2 }, { 0, 5, 2 }, { 1, 15, 0 }, { 1, 8, 0 } } }, { { { 6, 0, 1 }, { 0, 6, 1 }, { 0, 17, 0 }, { 17, 0, 0 } } }, { { { 6, 0, 0 }, { 0, 6, 0 }, { 0, 18, 0 }, { 0, 9, 0 } } }, { { { 6, 0, 1 }, { 0, 6, 1 }, { 0, 19, 0 }, { 1, 9, 0 } } }, { { { 6, 0, 2 }, { 0, 6, 2 }, { 3, 14, 0 }, { 0, 10, 0 } } }, { { { 7, 0, 1 }, { 0, 7, 1 }, { 0, 20, 0 }, { 16, 2, 0 } } }, { { { 7, 0, 0 }, { 0, 7, 0 }, { 0, 21, 0 }, { 1, 10, 0 } } }, { { { 7, 0, 1 }, { 0, 7, 1 }, { 0, 22, 0 }, { 0, 11, 0 } } }, { { { 7, 0, 2 }, { 0, 7, 2 }, { 4, 15, 0 }, { 1, 11, 0 } } }, { { { 8, 0, 1 }, { 0, 8, 1 }, { 0, 23, 0 }, { 17, 3, 0 } } }, { { { 8, 0, 0 }, { 0, 8, 0 }, { 0, 24, 0 }, { 0, 12, 0 } } }, { { { 8, 0, 1 }, { 0, 8, 1 }, { 0, 25, 0 }, { 1, 12, 0 } } }, { { { 8, 0, 2 }, { 0, 8, 2 }, { 6, 14, 0 }, { 0, 13, 0 } } }, { { { 9, 0, 1 }, { 0, 9, 1 }, { 0, 26, 0 }, { 16, 5, 0 } } }, { { { 9, 0, 0 }, { 0, 9, 0 }, { 0, 27, 0 }, { 1, 13, 0 } } }, { { { 9, 0, 1 }, { 0, 9, 1 }, { 0, 28, 0 }, { 0, 14, 0 } } }, { { { 9, 0, 2 }, { 0, 9, 2 }, { 7, 15, 0 }, { 1, 14, 0 } } }, { { { 10, 0, 1 }, { 0, 10, 1 }, { 0, 29, 0 }, { 17, 6, 0 } } }, { { { 10, 0, 0 }, { 0, 10, 0 }, { 0, 30, 0 }, { 0, 15, 0 } } }, { { { 10, 0, 1 }, { 0, 10, 1 }, { 0, 31, 0 }, { 1, 15, 0 } } }, { { { 10, 0, 2 }, { 0, 10, 2 }, { 9, 14, 0 }, { 2, 15, 0 } } }, { { { 11, 0, 1 }, { 0, 11, 1 }, { 0, 32, 0 }, { 0, 16, 0 } } }, { { { 11, 0, 0 }, { 0, 11, 0 }, { 0, 33, 0 }, { 1, 16, 0 } } }, { { { 11, 0, 1 }, { 0, 11, 1 }, { 2, 30, 0 }, { 4, 15, 0 } } }, { { { 11, 0, 2 }, { 0, 11, 2 }, { 0, 34, 0 }, { 0, 17, 0 } } }, { { { 12, 0, 1 }, { 0, 12, 1 }, { 0, 35, 0 }, { 1, 17, 0 } } }, { { { 12, 0, 0 }, { 0, 12, 0 }, { 0, 36, 0 }, { 0, 18, 0 } } }, { { { 12, 0, 1 }, { 0, 12, 1 }, { 3, 31, 0 }, { 7, 15, 0 } } }, { { { 12, 0, 2 }, { 0, 12, 2 }, { 0, 37, 0 }, { 1, 18, 0 } } }, { { { 13, 0, 1 }, { 0, 13, 1 }, { 0, 38, 0 }, { 0, 19, 0 } } }, { { { 13, 0, 0 }, { 0, 13, 0 }, { 0, 39, 0 }, { 1, 19, 0 } } }, { { { 13, 0, 1 }, { 0, 13, 1 }, { 5, 30, 0 }, { 10, 15, 0 } } }, { { { 13, 0, 2 }, { 0, 13, 2 }, { 0, 40, 0 }, { 0, 20, 0 } } }, { { { 14, 0, 1 }, { 0, 14, 1 }, { 0, 41, 0 }, { 1, 20, 0 } } }, { { { 14, 0, 0 }, { 0, 14, 0 }, { 0, 42, 0 }, { 0, 21, 0 } } }, { { { 14, 0, 1 }, { 0, 14, 1 }, { 6, 31, 0 }, { 13, 15, 0 } } }, { { { 14, 0, 2 }, { 0, 14, 2 }, { 0, 43, 0 }, { 1, 21, 0 } } }, { { { 15, 0, 1 }, { 0, 15, 1 }, { 0, 44, 0 }, { 0, 22, 0 } } }, { { { 15, 0, 0 }, { 0, 15, 0 }, { 0, 45, 0 }, { 1, 22, 0 } } }, { { { 15, 0, 1 }, { 0, 15, 1 }, { 8, 30, 0 }, { 16, 15, 0 } } }, { { { 15, 0, 2 }, { 0, 15, 2 }, { 0, 46, 0 }, { 0, 23, 0 } } }, { { { 16, 0, 2 }, { 0, 16, 2 }, { 0, 47, 0 }, { 1, 23, 0 } } }, { { { 16, 0, 1 }, { 0, 16, 1 }, { 1, 46, 0 }, { 0, 24, 0 } } }, { { { 16, 0, 0 }, { 0, 16, 0 }, { 0, 48, 0 }, { 16, 16, 0 } } }, { { { 16, 0, 1 }, { 0, 16, 1 }, { 0, 49, 0 }, { 1, 24, 0 } } }, { { { 16, 0, 2 }, { 0, 16, 2 }, { 0, 50, 0 }, { 0, 25, 0 } } }, { { { 17, 0, 1 }, { 0, 17, 1 }, { 2, 47, 0 }, { 1, 25, 0 } } }, { { { 17, 0, 0 }, { 0, 17, 0 }, { 0, 51, 0 }, { 17, 17, 0 } } }, { { { 17, 0, 1 }, { 0, 17, 1 }, { 0, 52, 0 }, { 0, 26, 0 } } }, { { { 17, 0, 2 }, { 0, 17, 2 }, { 0, 53, 0 }, { 1, 26, 0 } } }, { { { 18, 0, 1 }, { 0, 18, 1 }, { 4, 46, 0 }, { 0, 27, 0 } } }, { { { 18, 0, 0 }, { 0, 18, 0 }, { 0, 54, 0 }, { 16, 19, 0 } } }, { { { 18, 0, 1 }, { 0, 18, 1 }, { 0, 55, 0 }, { 1, 27, 0 } } }, { { { 18, 0, 2 }, { 0, 18, 2 }, { 0, 56, 0 }, { 0, 28, 0 } } }, { { { 19, 0, 1 }, { 0, 19, 1 }, { 5, 47, 0 }, { 1, 28, 0 } } }, { { { 19, 0, 0 }, { 0, 19, 0 }, { 0, 57, 0 }, { 17, 20, 0 } } }, { { { 19, 0, 1 }, { 0, 19, 1 }, { 0, 58, 0 }, { 0, 29, 0 } } }, { { { 19, 0, 2 }, { 0, 19, 2 }, { 0, 59, 0 }, { 1, 29, 0 } } }, { { { 20, 0, 1 }, { 0, 20, 1 }, { 7, 46, 0 }, { 0, 30, 0 } } }, { { { 20, 0, 0 }, { 0, 20, 0 }, { 0, 60, 0 }, { 16, 22, 0 } } }, { { { 20, 0, 1 }, { 0, 20, 1 }, { 0, 61, 0 }, { 1, 30, 0 } } }, { { { 20, 0, 2 }, { 0, 20, 2 }, { 0, 62, 0 }, { 0, 31, 0 } } }, { { { 21, 0, 1 }, { 0, 21, 1 }, { 8, 47, 0 }, { 1, 31, 0 } } }, { { { 21, 0, 0 }, { 0, 21, 0 }, { 0, 63, 0 }, { 17, 23, 0 } } }, { { { 21, 0, 1 }, { 0, 21, 1 }, { 1, 62, 0 }, { 0, 32, 0 } } }, { { { 21, 0, 2 }, { 0, 21, 2 }, { 1, 63, 0 }, { 3, 31, 0 } } }, { { { 22, 0, 1 }, { 0, 22, 1 }, { 10, 46, 0 }, { 1, 32, 0 } } }, { { { 22, 0, 0 }, { 0, 22, 0 }, { 2, 62, 0 }, { 0, 33, 0 } } }, { { { 22, 0, 1 }, { 0, 22, 1 }, { 2, 63, 0 }, { 1, 33, 0 } } }, { { { 22, 0, 2 }, { 0, 22, 2 }, { 3, 62, 0 }, { 6, 31, 0 } } }, { { { 23, 0, 1 }, { 0, 23, 1 }, { 11, 47, 0 }, { 0, 34, 0 } } }, { { { 23, 0, 0 }, { 0, 23, 0 }, { 3, 63, 0 }, { 1, 34, 0 } } }, { { { 23, 0, 1 }, { 0, 23, 1 }, { 4, 62, 0 }, { 0, 35, 0 } } }, { { { 23, 0, 2 }, { 0, 23, 2 }, { 4, 63, 0 }, { 9, 31, 0 } } }, { { { 24, 0, 1 }, { 0, 24, 1 }, { 13, 46, 0 }, { 1, 35, 0 } } }, { { { 24, 0, 0 }, { 0, 24, 0 }, { 5, 62, 0 }, { 0, 36, 0 } } }, { { { 24, 0, 1 }, { 0, 24, 1 }, { 5, 63, 0 }, { 1, 36, 0 } } }, { { { 24, 0, 2 }, { 0, 24, 2 }, { 6, 62, 0 }, { 12, 31, 0 } } }, { { { 25, 0, 1 }, { 0, 25, 1 }, { 14, 47, 0 }, { 0, 37, 0 } } }, { { { 25, 0, 0 }, { 0, 25, 0 }, { 6, 63, 0 }, { 1, 37, 0 } } }, { { { 25, 0, 1 }, { 0, 25, 1 }, { 7, 62, 0 }, { 0, 38, 0 } } }, { { { 25, 0, 2 }, { 0, 25, 2 }, { 7, 63, 0 }, { 15, 31, 0 } } }, { { { 26, 0, 1 }, { 0, 26, 1 }, { 16, 45, 0 }, { 1, 38, 0 } } }, { { { 26, 0, 0 }, { 0, 26, 0 }, { 8, 62, 0 }, { 0, 39, 0 } } }, { { { 26, 0, 1 }, { 0, 26, 1 }, { 8, 63, 0 }, { 1, 39, 0 } } }, { { { 26, 0, 2 }, { 0, 26, 2 }, { 9, 62, 0 }, { 18, 31, 0 } } }, { { { 27, 0, 1 }, { 0, 27, 1 }, { 16, 48, 0 }, { 0, 40, 0 } } }, { { { 27, 0, 0 }, { 0, 27, 0 }, { 9, 63, 0 }, { 1, 40, 0 } } }, { { { 27, 0, 1 }, { 0, 27, 1 }, { 10, 62, 0 }, { 0, 41, 0 } } }, { { { 27, 0, 2 }, { 0, 27, 2 }, { 10, 63, 0 }, { 16, 33, 0 } } }, { { { 28, 0, 1 }, { 0, 28, 1 }, { 16, 51, 0 }, { 1, 41, 0 } } }, { { { 28, 0, 0 }, { 0, 28, 0 }, { 11, 62, 0 }, { 0, 42, 0 } } }, { { { 28, 0, 1 }, { 0, 28, 1 }, { 11, 63, 0 }, { 1, 42, 0 } } }, { { { 28, 0, 2 }, { 0, 28, 2 }, { 12, 62, 0 }, { 17, 34, 0 } } }, { { { 29, 0, 1 }, { 0, 29, 1 }, { 16, 54, 0 }, { 0, 43, 0 } } }, { { { 29, 0, 0 }, { 0, 29, 0 }, { 12, 63, 0 }, { 1, 43, 0 } } }, { { { 29, 0, 1 }, { 0, 29, 1 }, { 13, 62, 0 }, { 0, 44, 0 } } }, { { { 29, 0, 2 }, { 0, 29, 2 }, { 13, 63, 0 }, { 16, 36, 0 } } }, { { { 30, 0, 1 }, { 0, 30, 1 }, { 16, 57, 0 }, { 1, 44, 0 } } }, { { { 30, 0, 0 }, { 0, 30, 0 }, { 14, 62, 0 }, { 0, 45, 0 } } }, { { { 30, 0, 1 }, { 0, 30, 1 }, { 14, 63, 0 }, { 1, 45, 0 } } }, { { { 30, 0, 2 }, { 0, 30, 2 }, { 15, 62, 0 }, { 17, 37, 0 } } }, { { { 31, 0, 1 }, { 0, 31, 1 }, { 16, 60, 0 }, { 0, 46, 0 } } }, { { { 31, 0, 0 }, { 0, 31, 0 }, { 15, 63, 0 }, { 1, 46, 0 } } }, { { { 31, 0, 1 }, { 0, 31, 1 }, { 24, 46, 0 }, { 0, 47, 0 } } }, { { { 31, 0, 2 }, { 0, 31, 2 }, { 16, 62, 0 }, { 16, 39, 0 } } }, { { { 32, 0, 2 }, { 0, 32, 2 }, { 16, 63, 0 }, { 1, 47, 0 } } }, { { { 32, 0, 1 }, { 0, 32, 1 }, { 17, 62, 0 }, { 2, 47, 0 } } }, { { { 32, 0, 0 }, { 0, 32, 0 }, { 25, 47, 0 }, { 0, 48, 0 } } }, { { { 32, 0, 1 }, { 0, 32, 1 }, { 17, 63, 0 }, { 1, 48, 0 } } }, { { { 32, 0, 2 }, { 0, 32, 2 }, { 18, 62, 0 }, { 0, 49, 0 } } }, { { { 33, 0, 1 }, { 0, 33, 1 }, { 18, 63, 0 }, { 5, 47, 0 } } }, { { { 33, 0, 0 }, { 0, 33, 0 }, { 27, 46, 0 }, { 1, 49, 0 } } }, { { { 33, 0, 1 }, { 0, 33, 1 }, { 19, 62, 0 }, { 0, 50, 0 } } }, { { { 33, 0, 2 }, { 0, 33, 2 }, { 19, 63, 0 }, { 1, 50, 0 } } }, { { { 34, 0, 1 }, { 0, 34, 1 }, { 20, 62, 0 }, { 8, 47, 0 } } }, { { { 34, 0, 0 }, { 0, 34, 0 }, { 28, 47, 0 }, { 0, 51, 0 } } }, { { { 34, 0, 1 }, { 0, 34, 1 }, { 20, 63, 0 }, { 1, 51, 0 } } }, { { { 34, 0, 2 }, { 0, 34, 2 }, { 21, 62, 0 }, { 0, 52, 0 } } }, { { { 35, 0, 1 }, { 0, 35, 1 }, { 21, 63, 0 }, { 11, 47, 0 } } }, { { { 35, 0, 0 }, { 0, 35, 0 }, { 30, 46, 0 }, { 1, 52, 0 } } }, { { { 35, 0, 1 }, { 0, 35, 1 }, { 22, 62, 0 }, { 0, 53, 0 } } }, { { { 35, 0, 2 }, { 0, 35, 2 }, { 22, 63, 0 }, { 1, 53, 0 } } }, { { { 36, 0, 1 }, { 0, 36, 1 }, { 23, 62, 0 }, { 14, 47, 0 } } }, { { { 36, 0, 0 }, { 0, 36, 0 }, { 31, 47, 0 }, { 0, 54, 0 } } }, { { { 36, 0, 1 }, { 0, 36, 1 }, { 23, 63, 0 }, { 1, 54, 0 } } }, { { { 36, 0, 2 }, { 0, 36, 2 }, { 24, 62, 0 }, { 0, 55, 0 } } }, { { { 37, 0, 1 }, { 0, 37, 1 }, { 24, 63, 0 }, { 17, 47, 0 } } }, { { { 37, 0, 0 }, { 0, 37, 0 }, { 32, 47, 0 }, { 1, 55, 0 } } }, { { { 37, 0, 1 }, { 0, 37, 1 }, { 25, 62, 0 }, { 0, 56, 0 } } }, { { { 37, 0, 2 }, { 0, 37, 2 }, { 25, 63, 0 }, { 1, 56, 0 } } }, { { { 38, 0, 1 }, { 0, 38, 1 }, { 26, 62, 0 }, { 17, 48, 0 } } }, { { { 38, 0, 0 }, { 0, 38, 0 }, { 32, 50, 0 }, { 0, 57, 0 } } }, { { { 38, 0, 1 }, { 0, 38, 1 }, { 26, 63, 0 }, { 1, 57, 0 } } }, { { { 38, 0, 2 }, { 0, 38, 2 }, { 27, 62, 0 }, { 0, 58, 0 } } }, { { { 39, 0, 1 }, { 0, 39, 1 }, { 27, 63, 0 }, { 16, 50, 0 } } }, { { { 39, 0, 0 }, { 0, 39, 0 }, { 32, 53, 0 }, { 1, 58, 0 } } }, { { { 39, 0, 1 }, { 0, 39, 1 }, { 28, 62, 0 }, { 0, 59, 0 } } }, { { { 39, 0, 2 }, { 0, 39, 2 }, { 28, 63, 0 }, { 1, 59, 0 } } }, { { { 40, 0, 1 }, { 0, 40, 1 }, { 29, 62, 0 }, { 17, 51, 0 } } }, { { { 40, 0, 0 }, { 0, 40, 0 }, { 32, 56, 0 }, { 0, 60, 0 } } }, { { { 40, 0, 1 }, { 0, 40, 1 }, { 29, 63, 0 }, { 1, 60, 0 } } }, { { { 40, 0, 2 }, { 0, 40, 2 }, { 30, 62, 0 }, { 0, 61, 0 } } }, { { { 41, 0, 1 }, { 0, 41, 1 }, { 30, 63, 0 }, { 16, 53, 0 } } }, { { { 41, 0, 0 }, { 0, 41, 0 }, { 32, 59, 0 }, { 1, 61, 0 } } }, { { { 41, 0, 1 }, { 0, 41, 1 }, { 31, 62, 0 }, { 0, 62, 0 } } }, { { { 41, 0, 2 }, { 0, 41, 2 }, { 31, 63, 0 }, { 1, 62, 0 } } }, { { { 42, 0, 1 }, { 0, 42, 1 }, { 32, 61, 0 }, { 17, 54, 0 } } }, { { { 42, 0, 0 }, { 0, 42, 0 }, { 32, 62, 0 }, { 0, 63, 0 } } }, { { { 42, 0, 1 }, { 0, 42, 1 }, { 32, 63, 0 }, { 1, 63, 0 } } }, { { { 42, 0, 2 }, { 0, 42, 2 }, { 41, 46, 0 }, { 2, 63, 0 } } }, { { { 43, 0, 1 }, { 0, 43, 1 }, { 33, 62, 0 }, { 16, 56, 0 } } }, { { { 43, 0, 0 }, { 0, 43, 0 }, { 33, 63, 0 }, { 3, 63, 0 } } }, { { { 43, 0, 1 }, { 0, 43, 1 }, { 34, 62, 0 }, { 4, 63, 0 } } }, { { { 43, 0, 2 }, { 0, 43, 2 }, { 42, 47, 0 }, { 5, 63, 0 } } }, { { { 44, 0, 1 }, { 0, 44, 1 }, { 34, 63, 0 }, { 17, 57, 0 } } }, { { { 44, 0, 0 }, { 0, 44, 0 }, { 35, 62, 0 }, { 6, 63, 0 } } }, { { { 44, 0, 1 }, { 0, 44, 1 }, { 35, 63, 0 }, { 7, 63, 0 } } }, { { { 44, 0, 2 }, { 0, 44, 2 }, { 44, 46, 0 }, { 8, 63, 0 } } }, { { { 45, 0, 1 }, { 0, 45, 1 }, { 36, 62, 0 }, { 16, 59, 0 } } }, { { { 45, 0, 0 }, { 0, 45, 0 }, { 36, 63, 0 }, { 9, 63, 0 } } }, { { { 45, 0, 1 }, { 0, 45, 1 }, { 37, 62, 0 }, { 10, 63, 0 } } }, { { { 45, 0, 2 }, { 0, 45, 2 }, { 45, 47, 0 }, { 11, 63, 0 } } }, { { { 46, 0, 1 }, { 0, 46, 1 }, { 37, 63, 0 }, { 17, 60, 0 } } }, { { { 46, 0, 0 }, { 0, 46, 0 }, { 38, 62, 0 }, { 12, 63, 0 } } }, { { { 46, 0, 1 }, { 0, 46, 1 }, { 38, 63, 0 }, { 13, 63, 0 } } }, { { { 46, 0, 2 }, { 0, 46, 2 }, { 47, 46, 0 }, { 14, 63, 0 } } }, { { { 47, 0, 1 }, { 0, 47, 1 }, { 39, 62, 0 }, { 16, 62, 0 } } }, { { { 47, 0, 0 }, { 0, 47, 0 }, { 39, 63, 0 }, { 15, 63, 0 } } }, { { { 47, 0, 1 }, { 0, 47, 1 }, { 40, 62, 0 }, { 16, 63, 0 } } }, { { { 47, 0, 2 }, { 0, 47, 2 }, { 48, 46, 0 }, { 32, 55, 0 } } }, { { { 48, 0, 2 }, { 0, 48, 2 }, { 40, 63, 0 }, { 17, 63, 0 } } }, { { { 48, 0, 1 }, { 0, 48, 1 }, { 41, 62, 0 }, { 18, 63, 0 } } }, { { { 48, 0, 0 }, { 0, 48, 0 }, { 41, 63, 0 }, { 19, 63, 0 } } }, { { { 48, 0, 1 }, { 0, 48, 1 }, { 48, 49, 0 }, { 33, 56, 0 } } }, { { { 48, 0, 2 }, { 0, 48, 2 }, { 42, 62, 0 }, { 20, 63, 0 } } }, { { { 49, 0, 1 }, { 0, 49, 1 }, { 42, 63, 0 }, { 21, 63, 0 } } }, { { { 49, 0, 0 }, { 0, 49, 0 }, { 43, 62, 0 }, { 22, 63, 0 } } }, { { { 49, 0, 1 }, { 0, 49, 1 }, { 48, 52, 0 }, { 32, 58, 0 } } }, { { { 49, 0, 2 }, { 0, 49, 2 }, { 43, 63, 0 }, { 23, 63, 0 } } }, { { { 50, 0, 1 }, { 0, 50, 1 }, { 44, 62, 0 }, { 24, 63, 0 } } }, { { { 50, 0, 0 }, { 0, 50, 0 }, { 44, 63, 0 }, { 25, 63, 0 } } }, { { { 50, 0, 1 }, { 0, 50, 1 }, { 48, 55, 0 }, { 33, 59, 0 } } }, { { { 50, 0, 2 }, { 0, 50, 2 }, { 45, 62, 0 }, { 26, 63, 0 } } }, { { { 51, 0, 1 }, { 0, 51, 1 }, { 45, 63, 0 }, { 27, 63, 0 } } }, { { { 51, 0, 0 }, { 0, 51, 0 }, { 46, 62, 0 }, { 28, 63, 0 } } }, { { { 51, 0, 1 }, { 0, 51, 1 }, { 48, 58, 0 }, { 32, 61, 0 } } }, { { { 51, 0, 2 }, { 0, 51, 2 }, { 46, 63, 0 }, { 29, 63, 0 } } }, { { { 52, 0, 1 }, { 0, 52, 1 }, { 47, 62, 0 }, { 30, 63, 0 } } }, { { { 52, 0, 0 }, { 0, 52, 0 }, { 47, 63, 0 }, { 31, 63, 0 } } }, { { { 52, 0, 1 }, { 0, 52, 1 }, { 48, 61, 0 }, { 33, 62, 0 } } }, { { { 52, 0, 2 }, { 0, 52, 2 }, { 48, 62, 0 }, { 32, 63, 0 } } }, { { { 53, 0, 1 }, { 0, 53, 1 }, { 56, 47, 0 }, { 33, 63, 0 } } }, { { { 53, 0, 0 }, { 0, 53, 0 }, { 48, 63, 0 }, { 49, 55, 0 } } }, { { { 53, 0, 1 }, { 0, 53, 1 }, { 49, 62, 0 }, { 34, 63, 0 } } }, { { { 53, 0, 2 }, { 0, 53, 2 }, { 49, 63, 0 }, { 35, 63, 0 } } }, { { { 54, 0, 1 }, { 0, 54, 1 }, { 58, 46, 0 }, { 36, 63, 0 } } }, { { { 54, 0, 0 }, { 0, 54, 0 }, { 50, 62, 0 }, { 48, 57, 0 } } }, { { { 54, 0, 1 }, { 0, 54, 1 }, { 50, 63, 0 }, { 37, 63, 0 } } }, { { { 54, 0, 2 }, { 0, 54, 2 }, { 51, 62, 0 }, { 38, 63, 0 } } }, { { { 55, 0, 1 }, { 0, 55, 1 }, { 59, 47, 0 }, { 39, 63, 0 } } }, { { { 55, 0, 0 }, { 0, 55, 0 }, { 51, 63, 0 }, { 49, 58, 0 } } }, { { { 55, 0, 1 }, { 0, 55, 1 }, { 52, 62, 0 }, { 40, 63, 0 } } }, { { { 55, 0, 2 }, { 0, 55, 2 }, { 52, 63, 0 }, { 41, 63, 0 } } }, { { { 56, 0, 1 }, { 0, 56, 1 }, { 61, 46, 0 }, { 42, 63, 0 } } }, { { { 56, 0, 0 }, { 0, 56, 0 }, { 53, 62, 0 }, { 48, 60, 0 } } }, { { { 56, 0, 1 }, { 0, 56, 1 }, { 53, 63, 0 }, { 43, 63, 0 } } }, { { { 56, 0, 2 }, { 0, 56, 2 }, { 54, 62, 0 }, { 44, 63, 0 } } }, { { { 57, 0, 1 }, { 0, 57, 1 }, { 62, 47, 0 }, { 45, 63, 0 } } }, { { { 57, 0, 0 }, { 0, 57, 0 }, { 54, 63, 0 }, { 49, 61, 0 } } }, { { { 57, 0, 1 }, { 0, 57, 1 }, { 55, 62, 0 }, { 46, 63, 0 } } }, { { { 57, 0, 2 }, { 0, 57, 2 }, { 55, 63, 0 }, { 47, 63, 0 } } }, { { { 58, 0, 1 }, { 0, 58, 1 }, { 56, 62, 1 }, { 48, 63, 1 } } }, { { { 58, 0, 0 }, { 0, 58, 0 }, { 56, 62, 0 }, { 48, 63, 0 } } }, { { { 58, 0, 1 }, { 0, 58, 1 }, { 56, 63, 0 }, { 49, 63, 0 } } }, { { { 58, 0, 2 }, { 0, 58, 2 }, { 57, 62, 0 }, { 50, 63, 0 } } }, { { { 59, 0, 1 }, { 0, 59, 1 }, { 57, 63, 1 }, { 51, 63, 1 } } }, { { { 59, 0, 0 }, { 0, 59, 0 }, { 57, 63, 0 }, { 51, 63, 0 } } }, { { { 59, 0, 1 }, { 0, 59, 1 }, { 58, 62, 0 }, { 52, 63, 0 } } }, { { { 59, 0, 2 }, { 0, 59, 2 }, { 58, 63, 0 }, { 53, 63, 0 } } }, { { { 60, 0, 1 }, { 0, 60, 1 }, { 59, 62, 1 }, { 54, 63, 1 } } }, { { { 60, 0, 0 }, { 0, 60, 0 }, { 59, 62, 0 }, { 54, 63, 0 } } }, { { { 60, 0, 1 }, { 0, 60, 1 }, { 59, 63, 0 }, { 55, 63, 0 } } }, { { { 60, 0, 2 }, { 0, 60, 2 }, { 60, 62, 0 }, { 56, 63, 0 } } }, { { { 61, 0, 1 }, { 0, 61, 1 }, { 60, 63, 1 }, { 57, 63, 1 } } }, { { { 61, 0, 0 }, { 0, 61, 0 }, { 60, 63, 0 }, { 57, 63, 0 } } }, { { { 61, 0, 1 }, { 0, 61, 1 }, { 61, 62, 0 }, { 58, 63, 0 } } }, { { { 61, 0, 2 }, { 0, 61, 2 }, { 61, 63, 0 }, { 59, 63, 0 } } }, { { { 62, 0, 1 }, { 0, 62, 1 }, { 62, 62, 1 }, { 60, 63, 1 } } }, { { { 62, 0, 0 }, { 0, 62, 0 }, { 62, 62, 0 }, { 60, 63, 0 } } }, { { { 62, 0, 1 }, { 0, 62, 1 }, { 62, 63, 0 }, { 61, 63, 0 } } }, { { { 62, 0, 2 }, { 0, 62, 2 }, { 63, 62, 0 }, { 62, 63, 0 } } }, { { { 63, 0, 1 }, { 0, 63, 1 }, { 63, 63, 1 }, { 63, 63, 1 } } }, { { { 63, 0, 0 }, { 0, 63, 0 }, { 63, 63, 0 }, { 63, 63, 0 } } } }; nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/squish.cpp000066400000000000000000000140101173441656100240260ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 #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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/squish.h000066400000000000000000000233731173441656100235070ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/squish.xcodeproj/000077500000000000000000000000001173441656100253225ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/squish.xcodeproj/project.pbxproj000066400000000000000000000576461173441656100304200ustar00rootroot00000000000000// !$*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 = ""; }; 133FA0DB096A7B8E0050752E /* alpha.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = alpha.cpp; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; 1350D70B092AA857005EE038 /* clusterfit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = clusterfit.cpp; sourceTree = ""; }; 1350D70C092AA858005EE038 /* clusterfit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clusterfit.h; sourceTree = ""; }; 1350D70F092AA858005EE038 /* colourblock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = colourblock.cpp; sourceTree = ""; }; 1350D710092AA858005EE038 /* colourblock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = colourblock.h; sourceTree = ""; }; 1350D711092AA858005EE038 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; 1350D712092AA858005EE038 /* maths.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = maths.cpp; sourceTree = ""; }; 1350D713092AA858005EE038 /* maths.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = maths.h; sourceTree = ""; }; 1350D716092AA858005EE038 /* rangefit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = rangefit.cpp; sourceTree = ""; }; 1350D717092AA858005EE038 /* rangefit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rangefit.h; sourceTree = ""; }; 1350D718092AA858005EE038 /* squish.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = squish.cpp; sourceTree = ""; }; 1350D719092AA858005EE038 /* squish.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = squish.h; sourceTree = ""; }; 13906CE3096938880000A6A7 /* texture_compression_s3tc.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = texture_compression_s3tc.txt; sourceTree = ""; }; 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 = ""; }; 139C234D09B0602700A2500D /* singlecolourfit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = singlecolourfit.h; sourceTree = ""; }; 139C234E09B0602700A2500D /* singlecolourfit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = singlecolourfit.cpp; sourceTree = ""; }; 139C236D09B060A900A2500D /* singlecolourlookup.inl */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = singlecolourlookup.inl; sourceTree = ""; }; 13A7CCA20952BE63001C963A /* colourfit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colourfit.h; sourceTree = ""; }; 13A7CCA30952BE63001C963A /* colourfit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colourfit.cpp; sourceTree = ""; }; 13C4C7AB0941C18000AC5B89 /* colourset.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = colourset.cpp; sourceTree = ""; }; 13C4C7AC0941C18000AC5B89 /* colourset.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = colourset.h; sourceTree = ""; }; 13CD64C0092BCF8A00488C97 /* simd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simd.h; sourceTree = ""; }; 13D0DC900931F93A00909807 /* simd_ve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simd_ve.h; sourceTree = ""; }; 13D0DC960931F9D600909807 /* simd_sse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simd_sse.h; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( D2AAC046055464E500DB518D /* libsquish.a */, 1342B4110999DE7F00152915 /* squishpng */, 1342B4370999E07C00152915 /* squishtest */, 139C21C409ADAA7000A2500D /* squishgen */, ); name = Products; sourceTree = ""; }; C6A0FF2B0290797F04C91782 /* Documentation */ = { isa = PBXGroup; children = ( ); name = Documentation; sourceTree = ""; }; /* 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 */; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/texture_compression_s3tc.txt000066400000000000000000000524061173441656100276370ustar00rootroot00000000000000Name 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 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 parameter of TexImage2D, CopyTexImage2D, and CompressedTexImage2DARB and the 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: * is not a multiple of four or equal to TEXTURE_WIDTH, unless and are both zero. * is not a multiple of four or equal to TEXTURE_HEIGHT, unless and are both zero. * or 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 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 is an S3TC format. CompressedTexImage2DARB will produce an INVALID_OPERATION error if 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 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: * is not a multiple of four or equal to TEXTURE_WIDTH. * is not a multiple of four or equal to TEXTURE_HEIGHT. * or 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 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 is COMPRESSED_RGB_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT1_EXT, COMPRESSED_RGBA_S3TC_DXT3_EXT, or COMPRESSED_RGBA_S3TC_DXT5_EXT and is not equal to zero. INVALID_ENUM is generated by CompressedTexSubImage1DARB or CompressedTexSubImage3DARB if 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: is not a multiple of four or equal to TEXTURE_WIDTH; is not a multiple of four or equal to TEXTURE_HEIGHT; or 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 , , or 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 , DELETE: , or is greater than -b, + is DELETE: less than w+b, + is less than h+b, or DELETE: + 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 , height of , and block size of (8 or 16 bytes) is decoded, the corresponding image size (in bytes) is: ceil(/4) * ceil(/4) * blocksize. When decoding an S3TC image, the block containing the texel at offset (, ) begins at an offset (in bytes) relative to the base of the image of: blocksize * (ceil(/4) * floor(/4) + floor(/4)). The data corresponding to a specific texel (, ) are extracted from a 4x4 texel block using a relative (x,y) value of ( modulo 4, 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 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. nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/vs7/000077500000000000000000000000001173441656100225315ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/vs7/squish.sln000066400000000000000000000040201173441656100245570ustar00rootroot00000000000000Microsoft 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 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/vs7/squish/000077500000000000000000000000001173441656100240455ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/vs7/squish/squish.vcproj000066400000000000000000000110641173441656100266100ustar00rootroot00000000000000 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/vs7/squishpng/000077500000000000000000000000001173441656100245525ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/vs7/squishpng/squishpng.vcproj000066400000000000000000000067571173441656100300370ustar00rootroot00000000000000 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/vs7/squishtest/000077500000000000000000000000001173441656100247455ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/vs7/squishtest/squishtest.vcproj000066400000000000000000000066371173441656100304220ustar00rootroot00000000000000 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/weightedclusterfit.cpp000066400000000000000000000376731173441656100264430ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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 namespace squish { WeightedClusterFit::WeightedClusterFit() { } void WeightedClusterFit::SetColourSet( ColourSet const* colours, int flags ) { ColourFit::SetColourSet( colours, flags ); // initialise the best error #if SQUISH_USE_SIMD m_besterror = VEC4_CONST( FLT_MAX ); Vec3 metric = m_metric.GetVec3(); #else m_besterror = FLT_MAX; Vec3 metric = m_metric; #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(), metric ); // 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 m_metricSqr = m_metric * m_metric; } float WeightedClusterFit::GetBestError() const { #if SQUISH_USE_SIMD Vec4 x = m_xxsum * m_metricSqr; Vec4 error = m_besterror + x.SplatX() + x.SplatY() + x.SplatZ(); return error.GetVec3().X(); #else return m_besterror + Dot(m_xxsum, m_metricSqr); #endif } #if SQUISH_USE_SIMD void WeightedClusterFit::Compress3( void* block ) { int const count = m_colours->GetCount(); 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); 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 ); // 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 <= count; c0++) { Vec4 x1 = zero; for( int c1 = 0; c1 <= count-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 to the grid a = Min( one, Max( zero, a ) ); b = Min( one, Max( zero, b ) ); a = Truncate( MultiplyAdd( grid, a, half ) ) * gridrcp; b = Truncate( MultiplyAdd( grid, b, half ) ) * gridrcp; // compute the error (we skip the constant xxsum) Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum ); Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum ); Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 ); Vec4 e4 = MultiplyAdd( two, e3, e1 ); // apply the metric to the error term Vec4 e5 = e4 * m_metricSqr; Vec4 error = e5.SplatX() + e5.SplatY() + e5.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 < count; i++) { bestindices[i] = 1; } } // remap the indices u8 ordered[16]; for( int i = 0; i < count; ++i ) ordered[m_order[i]] = bestindices[i]; m_colours->RemapIndices( ordered, bestindices ); // save the block WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block ); // save the error m_besterror = besterror; } } void WeightedClusterFit::Compress4( void* block ) { int const count = m_colours->GetCount(); 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 ); Vec4 const twonineths = VEC4_CONST( 2.0f/9.0f ); Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f ); Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f ); // 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 <= count; c0++) { Vec4 x1 = zero; for( int c1 = 0; c1 <= count-c0; c1++) { Vec4 x2 = zero; for( int c2 = 0; c2 <= count-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 = MultiplyAdd(x2, onethird, MultiplyAdd(x1, twothirds, x0)); // 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 = MultiplyAdd(x2, twothirds, MultiplyAdd(x1, onethird, x3)); // betax_sum, beta2_sum Vec4 const beta2_sum = betax_sum.SplatW(); //float const alphabeta_sum = (w1 + w2) * (2.0f/9.0f); Vec4 const alphabeta_sum = twonineths*( x1 + x2 ).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 to the grid a = Min( one, Max( zero, a ) ); b = Min( one, Max( zero, b ) ); a = Truncate( MultiplyAdd( grid, a, half ) ) * gridrcp; b = Truncate( MultiplyAdd( grid, b, half ) ) * gridrcp; // compute the error (we skip the constant xxsum) Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum ); Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum ); Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 ); Vec4 e4 = MultiplyAdd( two, e3, e1 ); // apply the metric to the error term Vec4 e5 = e4 * m_metricSqr; Vec4 error = e5.SplatX() + e5.SplatY() + e5.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 < count; i++) { bestindices[i] = 1; } } // remap the indices u8 ordered[16]; for( int i = 0; i < count; ++i ) ordered[m_order[i]] = bestindices[i]; m_colours->RemapIndices( ordered, bestindices ); // save the block WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block ); // save the error m_besterror = besterror; } } #else void WeightedClusterFit::Compress3( void* block ) { int const count = m_colours->GetCount(); Vec3 const one( 1.0f ); Vec3 const zero( 0.0f ); Vec3 const half( 0.5f ); Vec3 const grid( 31.0f, 63.0f, 31.0f ); Vec3 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f ); // 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 <= count; c0++) { Vec3 x1(0.0f); float w1 = 0.0f; for( int c1 = 0; c1 <= count-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 to the grid a = Min( one, Max( zero, a ) ); b = Min( one, Max( zero, b ) ); 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_metricSqr ); // 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 < count; i++) { bestindices[i] = 1; } } // remap the indices u8 ordered[16]; for( int i = 0; i < count; ++i ) ordered[m_order[i]] = bestindices[i]; m_colours->RemapIndices( ordered, bestindices ); // save the block WriteColourBlock3( beststart, bestend, bestindices, block ); // save the error m_besterror = besterror; } } void WeightedClusterFit::Compress4( void* block ) { int const count = m_colours->GetCount(); Vec3 const one( 1.0f ); Vec3 const zero( 0.0f ); Vec3 const half( 0.5f ); Vec3 const grid( 31.0f, 63.0f, 31.0f ); Vec3 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f ); // 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; // check all possible clusters for this total order for( int c0 = 0; c0 <= count; c0++) { Vec3 x1(0.0f); float w1 = 0.0f; for( int c1 = 0; c1 <= count-c0; c1++) { Vec3 x2(0.0f); float w2 = 0.0f; for( int c2 = 0; c2 <= count-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 to the grid a = Min( one, Max( zero, a ) ); b = Min( one, Max( zero, b ) ); 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_metricSqr ); // 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 < count; i++) { bestindices[i] = 1; } } // remap the indices u8 ordered[16]; for( int i = 0; i < count; ++i ) ordered[m_order[i]] = bestindices[i]; m_colours->RemapIndices( ordered, bestindices ); // save the block WriteColourBlock4( beststart, bestend, bestindices, block ); // save the error m_besterror = besterror; } } #endif } // namespace squish nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/squish/weightedclusterfit.h000066400000000000000000000043211173441656100260700ustar00rootroot00000000000000/* ----------------------------------------------------------------------------- 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(); void SetColourSet( ColourSet const* colours, int flags ); void SetMetric(float r, float g, float b); float GetBestError() const; // 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_metricSqr; Vec4 m_xxsum; Vec4 m_xsum; Vec4 m_besterror; #else Vec3 m_weighted[16]; float m_weights[16]; Vec3 m_metric; Vec3 m_metricSqr; Vec3 m_xxsum; Vec3 m_xsum; float m_wsum; float m_besterror; #endif int m_order[16]; }; } // namespace squish #endif // ndef SQUISH_WEIGHTEDCLUSTERFIT_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tests/000077500000000000000000000000001173441656100216405ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tests/ctest.c000066400000000000000000000016231173441656100231300ustar00rootroot00000000000000 #include #include int main(void) { NvttInputOptions inputOptions = 0; NvttOutputOptions outputOptions = 0; NvttCompressionOptions compressionOptions = 0; const unsigned int img[16*16]; memset(img, 0, sizeof(unsigned int) * 16 * 16); inputOptions = nvttCreateInputOptions(); nvttSetInputOptionsTextureLayout(inputOptions, NVTT_TextureType_2D, 16, 16, 1); nvttSetInputOptionsMipmapData(inputOptions, img, 16, 16, 1, 0, 0); outputOptions = nvttCreateOutputOptions(); nvttSetOutputOptionsFileName(outputOptions, "output.dds"); compressionOptions = nvttCreateCompressionOptions(); nvttSetCompressionOptionsFormat(compressionOptions, NVTT_Format_BC1); nvttCompress(inputOptions, outputOptions, compressionOptions); nvttDestroyCompressionOptions(compressionOptions); nvttDestroyOutputOptions(outputOptions); nvttDestroyInputOptions(inputOptions); return 0; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tests/filtertest.cpp000066400000000000000000000030221173441656100245260ustar00rootroot00000000000000 #include #include "../tools/cmdline.h" #include using namespace nv; int main(void) { // MyAssertHandler assertHandler; MyMessageHandler messageHandler; BoxFilter box1(0.5); Kernel1 k1(box1, 2); k1.debugPrint(); nvDebug("\n"); BoxFilter box2(1); Kernel1 k2(box2, 2); k2.debugPrint(); nvDebug("\n"); BoxFilter boxr3(1); Kernel1 k3(boxr3, 2); k3.debugPrint(); nvDebug("\n"); KaiserFilter kai4(5); kai4.setParameters(4, 2); Kernel1 k4(kai4, 2); k4.debugPrint(); nvDebug("\n"); /* Kernel1 k3(3); Kernel1 k4(9); Kernel1 k5(10); // k3.initFilter(Filter::Box); // k4.initFilter(Filter::Box); // k5.initFilter(Filter::Box); // nvDebug("Box Filter:\n"); // k3.debugPrint(); nvDebug("\n"); // k4.debugPrint(); nvDebug("\n"); // k5.debugPrint(); nvDebug("\n"); k3.initSinc(0.75); k4.initSinc(0.75); k5.initSinc(0.75); nvDebug("Sinc Filter:\n"); k3.debugPrint(); nvDebug("\n"); k4.debugPrint(); nvDebug("\n"); k5.debugPrint(); nvDebug("\n"); k3.initKaiser(4, 1, 100); k4.initKaiser(4, 1, 100); k5.initKaiser(4, 1, 100); nvDebug("Kaiser Filter:\n"); k3.debugPrint(); nvDebug("\n"); k4.debugPrint(); nvDebug("\n"); k5.debugPrint(); nvDebug("\n"); k3.initKaiser(4, 1, 10); k4.initKaiser(4, 1, 10); k5.initKaiser(4, 1, 10); nvDebug("Kaiser Filter 2:\n"); k3.debugPrint(); nvDebug("\n"); k4.debugPrint(); nvDebug("\n"); k5.debugPrint(); nvDebug("\n"); */ int l_start = 4; int l_end = 2; BoxFilter filter; PolyphaseKernel kp(kai4, l_start, l_end); kp.debugPrint(); return 0; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/000077500000000000000000000000001173441656100216365ustar00rootroot00000000000000nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/assemble.cpp000066400000000000000000000110241173441656100241330ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include #include "cmdline.h" // @@ Add decent error messages. // @@ Add option to resize images. // @@ Add support for reading DDS files with 2D images and possibly mipmaps. int main(int argc, char *argv[]) { MyAssertHandler assertHandler; MyMessageHandler messageHandler; bool assembleCubeMap = true; bool assembleVolume = false; bool assembleTextureArray = false; nv::Array files; nv::Path output = "output.dds"; // Parse arguments. for (int i = 1; i < argc; i++) { // Input options. if (strcmp("-cube", argv[i]) == 0) { assembleCubeMap = true; assembleVolume = false; assembleTextureArray = false; } /*if (strcmp("-volume", argv[i]) == 0) { assembleCubeMap = false; assembleVolume = true; assembleTextureArray = false; } if (strcmp("-array", argv[i]) == 0) { assembleCubeMap = false; assembleVolume = false; assembleTextureArray = true; }*/ else if (strcmp("-o", argv[i]) == 0) { i++; if (i < argc && argv[i][0] != '-') { output = argv[i]; } } else if (argv[i][0] != '-') { files.append(argv[i]); } } if (files.count() == 0) { printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n"); printf("usage: nvassemble [-cube|-volume|-array] 'file0' 'file1' ...\n\n"); return 1; } if (nv::strCaseCmp(output.extension(), ".dds") != 0) { //output.stripExtension(); output.append(".dds"); } if (assembleCubeMap && files.count() != 6) { printf("*** error, 6 files expected, but got %d\n", files.count()); return 1; } // Load all files. nv::Array images; uint w = 0, h = 0; bool hasAlpha = false; const uint imageCount = files.count(); images.resize(imageCount); for (uint i = 0; i < imageCount; i++) { if (!images[i].load(files[i])) { printf("*** error loading file\n"); return 1; } if (i == 0) { w = images[i].width(); h = images[i].height(); } else if (images[i].width() != w || images[i].height() != h) { printf("*** error, size of image '%s' does not match\n", files[i].str()); return 1; } if (images[i].format() == nv::Image::Format_ARGB) { hasAlpha = true; } } nv::StdOutputStream stream(output); if (stream.isError()) { printf("Error opening '%s' for writting\n", output.str()); return 1; } // Output DDS header. nv::DDSHeader header; header.setWidth(w); header.setHeight(h); if (assembleCubeMap) { header.setTextureCube(); } else if (assembleVolume) { header.setTexture3D(); header.setDepth(imageCount); } else if (assembleTextureArray) { //header.setTextureArray(imageCount); } // @@ It always outputs 32 bpp. header.setPitch(4 * w); header.setPixelFormat(32, 0xFF0000, 0xFF00, 0xFF, hasAlpha ? 0xFF000000 : 0); stream << header; // Output images. for (uint i = 0; i < imageCount; i++) { const uint pixelCount = w * h; for (uint p = 0; p < pixelCount; p++) { nv::Color32 c = images[i].pixel(p); uint8 r = c.r; uint8 g = c.g; uint8 b = c.b; uint8 a = c.a; stream << b << g << r << a; } } return 0; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/benchmark.cpp000066400000000000000000000220771173441656100243040ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include "cmdline.h" #include // clock struct MyErrorHandler : public nvtt::ErrorHandler { virtual void error(nvtt::Error e) { nvDebugBreak(); } }; // Set color to normal map conversion options. void setColorToNormalMap(nvtt::InputOptions & inputOptions) { inputOptions.setNormalMap(false); inputOptions.setConvertToNormalMap(true); inputOptions.setHeightEvaluation(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 0.0f); //inputOptions.setNormalFilter(1.0f, 0, 0, 0); //inputOptions.setNormalFilter(0.0f, 0, 0, 1); inputOptions.setGamma(1.0f, 1.0f); inputOptions.setNormalizeMipmaps(true); } // Set options for normal maps. void setNormalMap(nvtt::InputOptions & inputOptions) { inputOptions.setNormalMap(true); inputOptions.setConvertToNormalMap(false); inputOptions.setGamma(1.0f, 1.0f); inputOptions.setNormalizeMipmaps(true); } // Set options for color maps. void setColorMap(nvtt::InputOptions & inputOptions) { inputOptions.setNormalMap(false); inputOptions.setConvertToNormalMap(false); inputOptions.setGamma(2.2f, 2.2f); inputOptions.setNormalizeMipmaps(false); } int main(int argc, char *argv[]) { MyAssertHandler assertHandler; MyMessageHandler messageHandler; bool normal = false; bool color2normal = false; bool wrapRepeat = false; bool noMipmaps = false; bool fast = false; bool nocuda = false; bool silent = false; nvtt::Format format = nvtt::Format_BC1; const char * externalCompressor = NULL; nv::Path input; nv::Path output; // Parse arguments. for (int i = 1; i < argc; i++) { // Input options. if (strcmp("-color", argv[i]) == 0) { } else if (strcmp("-normal", argv[i]) == 0) { normal = true; } else if (strcmp("-tonormal", argv[i]) == 0) { color2normal = true; } else if (strcmp("-clamp", argv[i]) == 0) { } else if (strcmp("-repeat", argv[i]) == 0) { wrapRepeat = true; } else if (strcmp("-nomips", argv[i]) == 0) { noMipmaps = true; } // Compression options. else if (strcmp("-fast", argv[i]) == 0) { fast = true; } else if (strcmp("-nocuda", argv[i]) == 0) { nocuda = true; } else if (strcmp("-rgb", argv[i]) == 0) { format = nvtt::Format_RGB; } else if (strcmp("-bc1", argv[i]) == 0) { format = nvtt::Format_BC1; } else if (strcmp("-bc1a", argv[i]) == 0) { format = nvtt::Format_BC1a; } else if (strcmp("-bc2", argv[i]) == 0) { format = nvtt::Format_BC2; } else if (strcmp("-bc3", argv[i]) == 0) { format = nvtt::Format_BC3; } else if (strcmp("-bc3n", argv[i]) == 0) { format = nvtt::Format_BC3n; } else if (strcmp("-bc4", argv[i]) == 0) { format = nvtt::Format_BC4; } else if (strcmp("-bc5", argv[i]) == 0) { format = nvtt::Format_BC5; } // Undocumented option. Mainly used for testing. else if (strcmp("-ext", argv[i]) == 0) { if (i+1 < argc && argv[i+1][0] != '-') { externalCompressor = argv[i+1]; i++; } } // Misc options else if (strcmp("-silent", argv[i]) == 0) { silent = true; } else if (argv[i][0] != '-') { input = argv[i]; if (i+1 < argc && argv[i+1][0] != '-') { output = argv[i+1]; } else { output.copy(input.str()); output.stripExtension(); output.append(".dds"); } break; } } printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n"); if (input.isNull()) { printf("usage: nvttbenchmark [options] infile [outfile]\n\n"); printf("Input options:\n"); printf(" -color \tThe input image is a color map (default).\n"); printf(" -normal \tThe input image is a normal map.\n"); printf(" -tonormal\tConvert input to normal map.\n"); printf(" -clamp \tClamp wrapping mode (default).\n"); printf(" -repeat \tRepeat wrapping mode.\n"); printf(" -nomips \tDisable mipmap generation.\n\n"); printf("Compression options:\n"); printf(" -fast \tFast compression.\n"); printf(" -nocuda \tDo not use cuda compressor.\n"); printf(" -rgb \tRGBA format\n"); printf(" -bc1 \tBC1 format (DXT1)\n"); printf(" -bc1a \tBC1 format with binary alpha (DXT1a)\n"); printf(" -bc2 \tBC2 format (DXT3)\n"); printf(" -bc3 \tBC3 format (DXT5)\n"); printf(" -bc3n \tBC3 normal map format (DXT5nm)\n"); printf(" -bc4 \tBC4 format (ATI1)\n"); printf(" -bc5 \tBC5 format (3Dc/ATI2)\n\n"); return 1; } // @@ Make sure input file exists. // Set input options. nvtt::InputOptions inputOptions; if (nv::strCaseCmp(input.extension(), ".dds") == 0) { // Load surface. nv::DirectDrawSurface dds(input); if (!dds.isValid()) { fprintf(stderr, "The file '%s' is not a valid DDS file.\n", input.str()); return 1; } if (!dds.isSupported() || dds.isTexture3D()) { fprintf(stderr, "The file '%s' is not a supported DDS file.\n", input.str()); return 1; } uint faceCount; if (dds.isTexture2D()) { inputOptions.setTextureLayout(nvtt::TextureType_2D, dds.width(), dds.height()); faceCount = 1; } else { nvDebugCheck(dds.isTextureCube()); inputOptions.setTextureLayout(nvtt::TextureType_Cube, dds.width(), dds.height()); faceCount = 6; } uint mipmapCount = dds.mipmapCount(); nv::Image mipmap; for (uint f = 0; f < faceCount; f++) { for (uint m = 0; m <= mipmapCount; m++) { dds.mipmap(&mipmap, f, m); inputOptions.setMipmapData(mipmap.pixels(), mipmap.width(), mipmap.height(), 1, f, m); } } } else { // Regular image. nv::Image image; if (!image.load(input)) { fprintf(stderr, "The file '%s' is not a supported image type.\n", input.str()); return 1; } inputOptions.setTextureLayout(nvtt::TextureType_2D, image.width(), image.height()); inputOptions.setMipmapData(image.pixels(), image.width(), image.height()); } if (fast) { inputOptions.setMipmapping(true, nvtt::MipmapFilter_Box); } else { inputOptions.setMipmapping(true, nvtt::MipmapFilter_Box); //inputOptions.setMipmapping(true, nvtt::MipmapFilter_Kaiser); } if (wrapRepeat) { inputOptions.setWrapMode(nvtt::WrapMode_Repeat); } else { inputOptions.setWrapMode(nvtt::WrapMode_Clamp); } if (normal) { setNormalMap(inputOptions); } else if (color2normal) { setColorToNormalMap(inputOptions); } else { setColorMap(inputOptions); } if (noMipmaps) { inputOptions.setMipmapping(false); } nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat(format); if (fast) { compressionOptions.setQuality(nvtt::Quality_Fastest); } else { compressionOptions.setQuality(nvtt::Quality_Normal); //compressionOptions.setQuality(nvtt::Quality_Production, 0.5f); //compressionOptions.setQuality(nvtt::Quality_Highest); } compressionOptions.enableHardwareCompression(!nocuda); compressionOptions.setColorWeights(1, 1, 1); if (externalCompressor != NULL) { compressionOptions.setExternalCompressor(externalCompressor); } MyErrorHandler errorHandler; nvtt::OutputOptions outputOptions(NULL, &errorHandler); // printf("Press ENTER.\n"); // fflush(stdout); // getchar(); clock_t start = clock(); const int iterationCount = 20; for (int i = 0; i < iterationCount; i++) { nvtt::compress(inputOptions, outputOptions, compressionOptions); } clock_t end = clock(); float seconds = float(end-start) / CLOCKS_PER_SEC printf("total time taken: %.3f seconds\n", seconds); printf("time taken per texture: %.3f seconds\n", seconds / iterationCount); printf("textures per second: %.3f T/s\n", iterationCount / seconds); return 0; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/cmdline.h000066400000000000000000000040601173441656100234220ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 CMDLINE_H #define CMDLINE_H #include #include // stderr #include // exit #include // va_list struct MyMessageHandler : public nv::MessageHandler { MyMessageHandler() { nv::debug::setMessageHandler( this ); } ~MyMessageHandler() { nv::debug::resetMessageHandler(); } virtual void log( const char * str, va_list arg ) { va_list val; va_copy(val, arg); vfprintf(stderr, str, arg); va_end(val); } }; struct MyAssertHandler : public nv::AssertHandler { MyAssertHandler() { nv::debug::setAssertHandler( this ); } ~MyAssertHandler() { nv::debug::resetAssertHandler(); } // Handler method, note that func might be NULL! virtual int assert( const char *exp, const char *file, int line, const char *func ) { fprintf(stderr, "Assertion failed: %s\nIn %s:%d\n", exp, file, line); nv::debug::dumpInfo(); exit(1); } }; #endif // CMDLINE_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/compress.cpp000066400000000000000000000260001173441656100241730ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include "cmdline.h" #include // clock //#define WINDOWS_LEAN_AND_MEAN //#include // TIMER struct MyOutputHandler : public nvtt::OutputHandler { MyOutputHandler(const char * name) : total(0), progress(0), percentage(0), stream(new nv::StdOutputStream(name)) {} virtual ~MyOutputHandler() { delete stream; } void setTotal(int64 t) { total = t + 128; } void setDisplayProgress(bool b) { verbose = b; } virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel) { // ignore. } // Output data. virtual bool writeData(const void * data, int size) { nvDebugCheck(stream != NULL); stream->serialize(const_cast(data), size); progress += size; int p = int((100 * progress) / total); if (verbose && p != percentage) { nvCheck(p >= 0); percentage = p; printf("\r%d%%", percentage); fflush(stdout); } return true; } int64 total; int64 progress; int percentage; bool verbose; nv::StdOutputStream * stream; }; struct MyErrorHandler : public nvtt::ErrorHandler { virtual void error(nvtt::Error e) { #if _DEBUG nvDebugBreak(); #endif printf("Error: '%s'\n", nvtt::errorString(e)); } }; // Set color to normal map conversion options. void setColorToNormalMap(nvtt::InputOptions & inputOptions) { inputOptions.setNormalMap(false); inputOptions.setConvertToNormalMap(true); inputOptions.setHeightEvaluation(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 0.0f); //inputOptions.setNormalFilter(1.0f, 0, 0, 0); //inputOptions.setNormalFilter(0.0f, 0, 0, 1); inputOptions.setGamma(1.0f, 1.0f); inputOptions.setNormalizeMipmaps(true); } // Set options for normal maps. void setNormalMap(nvtt::InputOptions & inputOptions) { inputOptions.setNormalMap(true); inputOptions.setConvertToNormalMap(false); inputOptions.setGamma(1.0f, 1.0f); inputOptions.setNormalizeMipmaps(true); } // Set options for color maps. void setColorMap(nvtt::InputOptions & inputOptions) { inputOptions.setNormalMap(false); inputOptions.setConvertToNormalMap(false); inputOptions.setGamma(2.2f, 2.2f); inputOptions.setNormalizeMipmaps(false); } int main(int argc, char *argv[]) { MyAssertHandler assertHandler; MyMessageHandler messageHandler; bool alpha = false; bool normal = false; bool color2normal = false; bool wrapRepeat = false; bool noMipmaps = false; bool fast = false; bool nocuda = false; bool silent = false; bool bc1n = false; nvtt::Format format = nvtt::Format_BC1; const char * externalCompressor = NULL; nv::Path input; nv::Path output; // Parse arguments. for (int i = 1; i < argc; i++) { // Input options. if (strcmp("-color", argv[i]) == 0) { } else if (strcmp("-alpha", argv[i]) == 0) { alpha = true; } else if (strcmp("-normal", argv[i]) == 0) { normal = true; } else if (strcmp("-tonormal", argv[i]) == 0) { color2normal = true; } else if (strcmp("-clamp", argv[i]) == 0) { } else if (strcmp("-repeat", argv[i]) == 0) { wrapRepeat = true; } else if (strcmp("-nomips", argv[i]) == 0) { noMipmaps = true; } // Compression options. else if (strcmp("-fast", argv[i]) == 0) { fast = true; } else if (strcmp("-nocuda", argv[i]) == 0) { nocuda = true; } else if (strcmp("-rgb", argv[i]) == 0) { format = nvtt::Format_RGB; } else if (strcmp("-bc1", argv[i]) == 0) { format = nvtt::Format_BC1; } else if (strcmp("-bc1n", argv[i]) == 0) { format = nvtt::Format_BC1; bc1n = true; } else if (strcmp("-bc1a", argv[i]) == 0) { format = nvtt::Format_BC1a; } else if (strcmp("-bc2", argv[i]) == 0) { format = nvtt::Format_BC2; } else if (strcmp("-bc3", argv[i]) == 0) { format = nvtt::Format_BC3; } else if (strcmp("-bc3n", argv[i]) == 0) { format = nvtt::Format_BC3n; } else if (strcmp("-bc4", argv[i]) == 0) { format = nvtt::Format_BC4; } else if (strcmp("-bc5", argv[i]) == 0) { format = nvtt::Format_BC5; } // Undocumented option. Mainly used for testing. else if (strcmp("-ext", argv[i]) == 0) { if (i+1 < argc && argv[i+1][0] != '-') { externalCompressor = argv[i+1]; i++; } } // Misc options else if (strcmp("-silent", argv[i]) == 0) { silent = true; } else if (argv[i][0] != '-') { input = argv[i]; if (i+1 < argc && argv[i+1][0] != '-') { output = argv[i+1]; } else { output.copy(input.str()); output.stripExtension(); output.append(".dds"); } break; } } const uint version = nvtt::version(); const uint major = version / 100; const uint minor = version % 100; printf("NVIDIA Texture Tools %u.%u - Copyright NVIDIA Corporation 2007\n\n", major, minor); if (input.isNull()) { printf("usage: nvcompress [options] infile [outfile]\n\n"); printf("Input options:\n"); printf(" -color \tThe input image is a color map (default).\n"); printf(" -alpha \tThe input image has an alpha channel used for transparency.\n"); printf(" -normal \tThe input image is a normal map.\n"); printf(" -tonormal\tConvert input to normal map.\n"); printf(" -clamp \tClamp wrapping mode (default).\n"); printf(" -repeat \tRepeat wrapping mode.\n"); printf(" -nomips \tDisable mipmap generation.\n\n"); printf("Compression options:\n"); printf(" -fast \tFast compression.\n"); printf(" -nocuda \tDo not use cuda compressor.\n"); printf(" -rgb \tRGBA format\n"); printf(" -bc1 \tBC1 format (DXT1)\n"); printf(" -bc1n \tBC1 normal map format (DXT1nm)\n"); printf(" -bc1a \tBC1 format with binary alpha (DXT1a)\n"); printf(" -bc2 \tBC2 format (DXT3)\n"); printf(" -bc3 \tBC3 format (DXT5)\n"); printf(" -bc3n \tBC3 normal map format (DXT5nm)\n"); printf(" -bc4 \tBC4 format (ATI1)\n"); printf(" -bc5 \tBC5 format (3Dc/ATI2)\n\n"); return EXIT_FAILURE; } // @@ Make sure input file exists. // Set input options. nvtt::InputOptions inputOptions; if (nv::strCaseCmp(input.extension(), ".dds") == 0) { // Load surface. nv::DirectDrawSurface dds(input); if (!dds.isValid()) { fprintf(stderr, "The file '%s' is not a valid DDS file.\n", input.str()); return EXIT_FAILURE; } if (!dds.isSupported() || dds.isTexture3D()) { fprintf(stderr, "The file '%s' is not a supported DDS file.\n", input.str()); return EXIT_FAILURE; } uint faceCount; if (dds.isTexture2D()) { inputOptions.setTextureLayout(nvtt::TextureType_2D, dds.width(), dds.height()); faceCount = 1; } else { nvDebugCheck(dds.isTextureCube()); inputOptions.setTextureLayout(nvtt::TextureType_Cube, dds.width(), dds.height()); faceCount = 6; } uint mipmapCount = dds.mipmapCount(); nv::Image mipmap; for (uint f = 0; f < faceCount; f++) { for (uint m = 0; m < mipmapCount; m++) { dds.mipmap(&mipmap, f, m); inputOptions.setMipmapData(mipmap.pixels(), mipmap.width(), mipmap.height(), 1, f, m); } } } else { // Regular image. nv::Image image; if (!image.load(input)) { fprintf(stderr, "The file '%s' is not a supported image type.\n", input.str()); return EXIT_FAILURE; } inputOptions.setTextureLayout(nvtt::TextureType_2D, image.width(), image.height()); inputOptions.setMipmapData(image.pixels(), image.width(), image.height()); } if (wrapRepeat) { inputOptions.setWrapMode(nvtt::WrapMode_Repeat); } else { inputOptions.setWrapMode(nvtt::WrapMode_Clamp); } if (alpha) { inputOptions.setAlphaMode(nvtt::AlphaMode_Transparency); } else { inputOptions.setAlphaMode(nvtt::AlphaMode_None); } if (normal) { setNormalMap(inputOptions); } else if (color2normal) { setColorToNormalMap(inputOptions); } else { setColorMap(inputOptions); } if (noMipmaps) { inputOptions.setMipmapGeneration(false); } nvtt::CompressionOptions compressionOptions; compressionOptions.setFormat(format); if (fast) { compressionOptions.setQuality(nvtt::Quality_Fastest); } else { compressionOptions.setQuality(nvtt::Quality_Normal); //compressionOptions.setQuality(nvtt::Quality_Production); //compressionOptions.setQuality(nvtt::Quality_Highest); } if (bc1n) { compressionOptions.setColorWeights(1, 1, 0); } if (externalCompressor != NULL) { compressionOptions.setExternalCompressor(externalCompressor); } MyErrorHandler errorHandler; MyOutputHandler outputHandler(output); if (outputHandler.stream->isError()) { fprintf(stderr, "Error opening '%s' for writting\n", output.str()); return EXIT_FAILURE; } nvtt::Compressor compressor; compressor.enableCudaAcceleration(!nocuda); printf("CUDA acceleration "); if (compressor.isCudaAccelerationEnabled()) { printf("ENABLED\n\n"); } else { printf("DISABLED\n\n"); } outputHandler.setTotal(compressor.estimateSize(inputOptions, compressionOptions)); outputHandler.setDisplayProgress(!silent); nvtt::OutputOptions outputOptions; //outputOptions.setFileName(output); outputOptions.setOutputHandler(&outputHandler); outputOptions.setErrorHandler(&errorHandler); // printf("Press ENTER.\n"); // fflush(stdout); // getchar(); clock_t start = clock(); if (!compressor.process(inputOptions, compressionOptions, outputOptions)) { return EXIT_FAILURE; } clock_t end = clock(); printf("\rtime taken: %.3f seconds\n", float(end-start) / CLOCKS_PER_SEC); return EXIT_SUCCESS; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/configdialog.cpp000066400000000000000000000115661173441656100250000ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 "configdialog.h" #include #include ConfigDialog::ConfigDialog(QWidget *parent/*=0*/) : QDialog(parent) { init(); } ConfigDialog::ConfigDialog(const char * fileName, QWidget *parent/*=0*/) : QDialog(parent) { init(); open(fileName); } void ConfigDialog::init() { ui.setupUi(this); connect(ui.openButton, SIGNAL(clicked()), this, SLOT(openClicked())); connect(ui.generateMipmapsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(generateMipmapsChanged(int))); connect(ui.mipmapFilterComboBox, SIGNAL(activated(QString)), this, SLOT(mipmapFilterChanged(QString))); //connect(ui.mipmapFilterSettings, SIGNAL(clicked()), this, SLOT(mipmapFilterSettingsShow())); connect(ui.redSpinBox, SIGNAL(valueChanged(double)), this, SLOT(colorWeightChanged())); connect(ui.greenSpinBox, SIGNAL(valueChanged(double)), this, SLOT(colorWeightChanged())); connect(ui.blueSpinBox, SIGNAL(valueChanged(double)), this, SLOT(colorWeightChanged())); connect(ui.uniformButton, SIGNAL(toggled(bool)), this, SLOT(uniformWeightToggled(bool))); connect(ui.luminanceButton, SIGNAL(toggled(bool)), this, SLOT(luminanceWeightToggled(bool))); //connect(ui.rgbMapRadioButton, SIGNAL(toggled(bool)), this, SLOT(colorModeChanged())); connect(ui.normalMapRadioButton, SIGNAL(toggled(bool)), this, SLOT(normalMapModeChanged(bool))); } void ConfigDialog::openClicked() { // @@ Open file dialog. QString fileName; open(fileName); } void ConfigDialog::generateMipmapsChanged(int state) { Q_UNUSED(state); bool generateMipmapEnabled = ui.generateMipmapsCheckBox->isChecked(); ui.mipmapFilterLabel->setEnabled(generateMipmapEnabled); ui.mipmapFilterComboBox->setEnabled(generateMipmapEnabled); ui.limitMipmapsCheckBox->setEnabled(generateMipmapEnabled); bool enableFilterSettings = (ui.mipmapFilterComboBox->currentText() == "Kaiser"); ui.mipmapFilterSettings->setEnabled(generateMipmapEnabled && enableFilterSettings); bool enableMaxLevel = ui.limitMipmapsCheckBox->isChecked(); ui.maxLevelLabel->setEnabled(generateMipmapEnabled && enableMaxLevel); ui.maxLevelSpinBox->setEnabled(generateMipmapEnabled && enableMaxLevel); } void ConfigDialog::mipmapFilterChanged(QString name) { bool enableFilterSettings = (name == "Kaiser"); ui.mipmapFilterSettings->setEnabled(enableFilterSettings); } void ConfigDialog::colorWeightChanged() { double r = ui.redSpinBox->value(); double g = ui.greenSpinBox->value(); double b = ui.blueSpinBox->value(); bool uniform = (r == 1.0 && g == 1.0 && b == 1.0); bool luminance = (r == 0.3 && g == 0.59 && b == 0.11); ui.uniformButton->setChecked(uniform); ui.luminanceButton->setChecked(luminance); } void ConfigDialog::uniformWeightToggled(bool checked) { if (checked) { ui.redSpinBox->setValue(1.0); ui.greenSpinBox->setValue(1.0); ui.blueSpinBox->setValue(1.0); } } void ConfigDialog::luminanceWeightToggled(bool checked) { if (checked) { ui.redSpinBox->setValue(0.3); ui.greenSpinBox->setValue(0.59); ui.blueSpinBox->setValue(0.11); } } void ConfigDialog::normalMapModeChanged(bool checked) { ui.alphaModeGroupBox->setEnabled(!checked); ui.inputGammaSpinBox->setEnabled(!checked); ui.inputGammaLabel->setEnabled(!checked); ui.outputGammaSpinBox->setEnabled(!checked); ui.outputGammaLabel->setEnabled(!checked); } bool ConfigDialog::open(QString fileName) { // @@ Load image. QImage image; // @@ If success. { ui.imagePathLineEdit->setText(fileName); // @@ Set image in graphics view. // @@ Set image description. // @@ Provide image to nvtt. int w = image.width(); int h = image.height(); void * data = NULL; inputOptions.setTextureLayout(nvtt::TextureType_2D, w, h); inputOptions.setMipmapData(data, w, h); return true; } return false; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/configdialog.h000066400000000000000000000036631173441656100244440ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 CONFIGDIALOG_H #define CONFIGDIALOG_H #include #include "ui_configdialog.h" #include class ConfigDialog : public QDialog { Q_OBJECT public: ConfigDialog(QWidget *parent = 0); ConfigDialog(const char * fileName, QWidget *parent = 0); protected slots: void openClicked(); void generateMipmapsChanged(int state); void mipmapFilterChanged(QString name); void colorWeightChanged(); void uniformWeightToggled(bool checked); void luminanceWeightToggled(bool checked); void normalMapModeChanged(bool checked); bool open(QString fileName); private: void init(); private: Ui::ConfigDialog ui; nvtt::InputOptions inputOptions; nvtt::CompressionOptions compressionOptions; nvtt::OutputOptions outputOptions; }; #endif // CONFIGDIALOG_H nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/configdialog.ui000066400000000000000000001037651173441656100246360ustar00rootroot00000000000000 ConfigDialog 0 0 674 475 NVIDIA Texture Tools true 64 0 128 16777215 Qt::ScrollBarAlwaysOff QListView::Static QListView::TopToBottom false QListView::Adjust QListView::ListMode Input Options Compression Options Output Options Preview ../../../../../../castano-stuff/qshaderedit/src/images/colorpicker.png 0 0 3 -1 0 0 0 0 0 Qt::ElideNone false File Path 0 0 Open Image Settings 0 0 Color Mode Qt::AlignHCenter 0 RGB true Normal Map 0 0 Alpha Mode Qt::AlignHCenter 0 None false Transparency true Premultiplied 0 0 0 Wrap Mode: mipmapFilterComboBox 16777215 26 Mirror Repeat Clamp 0 0 Input Gamma: inputGammaSpinBox 0 0 QAbstractSpinBox::UpDownArrows 0.050000000000000 4.000000000000000 0.050000000000000 2.200000000000000 0 0 Output Gamma: inputGammaSpinBox 0 0 QAbstractSpinBox::UpDownArrows 0.050000000000000 4.000000000000000 0.050000000000000 2.200000000000000 Qt::Vertical 433 16 Mipmaps Generate mipmaps true 1 0 0 Mipmap filter: mipmapFilterComboBox 16777215 26 Box Triangle Kaiser false 0 0 16777215 24 false ... Qt::ToolButtonTextOnly 0 0 Limit Mipmaps false 0 0 Max Level: false 0 0 80 16777215 Qt::Vertical 204 71 Normal Map 0 0 0 0 0 0 Format: Qt::PlainText Qt::NoTextInteraction formatComboBox Uncompressed BC1 (DXT1) BC1a (DXT1a) BC2 (DXT3) BC3 (DXT5) BC4 BC5 0 0 Quality: Qt::PlainText Qt::NoTextInteraction formatComboBox 1 Fastest Normal Production Highest Qt::Horizontal 40 20 0 0 Color Weights Qt::AlignHCenter Red redSpinBox 1.000000000000000 0.050000000000000 1.000000000000000 Green greenSpinBox 1.000000000000000 0.050000000000000 1.000000000000000 Blue blueSpinBox 1.000000000000000 0.050000000000000 1.000000000000000 16777215 22 Uniform Weights true true 16777215 22 Luminance Weights true Qt::Horizontal 40 20 Qt::Vertical 484 31 0 0 0 0 Bilinear Filter true View difference Qt::Horizontal Default true 0 true Qt::Horizontal false Quit listWidget currentRowChanged(int) stackedWidget setCurrentIndex(int) 118 193 154 220 pushButton clicked() ConfigDialog accept() 565 491 582 506 limitMipmapsCheckBox clicked(bool) maxLevelSpinBox setEnabled(bool) 451 120 524 120 limitMipmapsCheckBox clicked(bool) maxLevelLabel setEnabled(bool) 337 120 482 124 nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/ddsinfo.cpp000066400000000000000000000034301173441656100237700ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include "cmdline.h" int main(int argc, char *argv[]) { MyAssertHandler assertHandler; MyMessageHandler messageHandler; if (argc != 2) { printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n"); printf("usage: nvddsinfo ddsfile\n\n"); return 1; } // Load surface. nv::DirectDrawSurface dds(argv[1]); if (!dds.isValid()) { printf("The file '%s' is not a valid DDS file.\n", argv[1]); return 1; } dds.printInfo(); return 0; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/decompress.cpp000066400000000000000000000042731173441656100245140ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include "cmdline.h" int main(int argc, char *argv[]) { MyAssertHandler assertHandler; MyMessageHandler messageHandler; if (argc != 2) { printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n"); printf("usage: nvdecompress 'ddsfile'\n\n"); return 1; } // Load surface. nv::DirectDrawSurface dds(argv[1]); if (!dds.isValid()) { printf("The file '%s' is not a valid DDS file.\n", argv[1]); return 1; } nv::Path name(argv[1]); name.stripExtension(); name.append(".tga"); nv::StdOutputStream stream(name.str()); if (stream.isError()) { printf("Error opening '%s' for writting\n", name.str()); return 1; } // @@ TODO: Add command line options to output mipmaps, cubemap faces, etc. nv::Image img; dds.mipmap(&img, 0, 0); // get first image nv::ImageIO::saveTGA(stream, &img); return 0; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/imgdiff.cpp000066400000000000000000000146721173441656100237610ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include #include #include #include "cmdline.h" static bool loadImage(nv::Image & image, const char * fileName) { if (nv::strCaseCmp(nv::Path::extension(fileName), ".dds") == 0) { nv::DirectDrawSurface dds(fileName); if (!dds.isValid()) { printf("The file '%s' is not a valid DDS file.\n", fileName); return false; } dds.mipmap(&image, 0, 0); // get first image } else { // Regular image. if (!image.load(fileName)) { printf("The file '%s' is not a supported image type.\n", fileName); return false; } } return true; } // @@ Compute per-tile errors. struct Error { Error() { samples = 0; mabse = 0.0f; maxabse = 0.0f; mse = 0.0f; } void addSample(float e) { samples++; mabse += fabsf(e); maxabse = nv::max(maxabse, fabsf(e)); mse += e * e; } void done() { mabse /= samples; mse /= samples; rmse = sqrtf(mse); psnr = (rmse == 0) ? 999.0f : 20.0f * log10(255.0f / rmse); } void print() { printf(" Mean absolute error: %f\n", mabse); printf(" Max absolute error: %f\n", maxabse); printf(" Root mean squared error: %f\n", rmse); printf(" Peak signal to noise ratio in dB: %f\n", psnr); } int samples; float mabse; float maxabse; float mse; float rmse; float psnr; }; struct NormalError { NormalError() { samples = 0; ade = 0.0f; mse = 0.0f; } void addSample(nv::Color32 o, nv::Color32 c) { nv::Vector3 vo = nv::Vector3(o.r, o.g, o.b); nv::Vector3 vc = nv::Vector3(c.r, c.g, c.b); // Unpack and normalize. vo = nv::normalize(2.0f * (vo / 255.0f) - 1.0f); vc = nv::normalize(2.0f * (vc / 255.0f) - 1.0f); ade += acosf(nv::clamp(dot(vo, vc), -1.0f, 1.0f)); mse += length_squared((vo - vc) * (255 / 2.0f)); samples++; } void done() { if (samples) { ade /= samples; mse /= samples * 3; rmse = sqrtf(mse); psnr = (rmse == 0) ? 999.0f : 20.0f * log10(255.0f / rmse); } } void print() { printf(" Angular deviation error: %f\n", ade); printf(" Root mean squared error: %f\n", rmse); printf(" Peak signal to noise ratio in dB: %f\n", psnr); } int samples; float ade; float mse; float rmse; float psnr; }; int main(int argc, char *argv[]) { MyAssertHandler assertHandler; MyMessageHandler messageHandler; bool compareNormal = false; bool compareAlpha = false; nv::Path input0; nv::Path input1; nv::Path output; // Parse arguments. for (int i = 1; i < argc; i++) { // Input options. if (strcmp("-normal", argv[i]) == 0) { compareNormal = true; } if (strcmp("-alpha", argv[i]) == 0) { compareAlpha = true; } else if (argv[i][0] != '-') { input0 = argv[i]; if (i+1 < argc && argv[i+1][0] != '-') { input1 = argv[i+1]; } break; } } if (input0.isNull() || input1.isNull()) { printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n"); printf("usage: nvimgdiff [options] original_file updated_file [output]\n\n"); printf("Diff options:\n"); printf(" -normal \tCompare images as if they were normal maps.\n"); printf(" -alpha \tCompare alpha weighted images.\n"); return 1; } nv::Image image0, image1; if (!loadImage(image0, input0)) return 0; if (!loadImage(image1, input1)) return 0; const uint w0 = image0.width(); const uint h0 = image0.height(); const uint w1 = image1.width(); const uint h1 = image1.height(); const uint w = nv::min(w0, w1); const uint h = nv::min(h0, h1); // Compute errors. Error error_r; Error error_g; Error error_b; Error error_a; Error error_total; NormalError error_normal; for (uint i = 0; i < h; i++) { for (uint e = 0; e < w; e++) { const nv::Color32 c0(image0.pixel(e, i)); const nv::Color32 c1(image1.pixel(e, i)); float r = float(c0.r - c1.r); float g = float(c0.g - c1.g); float b = float(c0.b - c1.b); float a = float(c0.a - c1.a); error_r.addSample(r); error_g.addSample(g); error_b.addSample(b); error_a.addSample(a); if (compareNormal) { error_normal.addSample(c0, c1); } if (compareAlpha) { error_total.addSample(r * c0.a / 255.0f); error_total.addSample(g * c0.a / 255.0f); error_total.addSample(b * c0.a / 255.0f); } else { error_total.addSample(r); error_total.addSample(g); error_total.addSample(b); } } } error_r.done(); error_g.done(); error_b.done(); error_a.done(); error_total.done(); error_normal.done(); printf("Image size compared: %dx%d\n", w, h); if (w != w0 || w != w1 || h != h0 || h != h1) { printf("--- NOTE: only the overlap between the 2 images (%d,%d) and (%d,%d) was compared\n", w0, h0, w1, h1); } printf("Total pixels: %d\n", w*h); printf("Color:\n"); error_total.print(); if (compareNormal) { printf("Normal:\n"); error_normal.print(); } if (compareAlpha) { printf("Alpha:\n"); error_a.print(); } // @@ Write image difference. return 0; } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/main.cpp000066400000000000000000000024721173441656100232730ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include "configdialog.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); ConfigDialog dialog; return dialog.exec(); } nvidia-texture-tools-2.0.8-1+dfsg/src/nvtt/tools/resize.cpp000066400000000000000000000126551173441656100236540ustar00rootroot00000000000000// Copyright NVIDIA Corporation 2007 -- Ignacio Castano // // 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 #include #include #include #include #include #include #include #include #include #include #include #include "cmdline.h" static bool loadImage(nv::Image & image, const char * fileName) { if (nv::strCaseCmp(nv::Path::extension(fileName), ".dds") == 0) { nv::DirectDrawSurface dds(fileName); if (!dds.isValid()) { printf("The file '%s' is not a valid DDS file.\n", fileName); return false; } dds.mipmap(&image, 0, 0); // get first image } else { // Regular image. if (!image.load(fileName)) { printf("The file '%s' is not a supported image type.\n", fileName); return false; } } return true; } int main(int argc, char *argv[]) { //MyAssertHandler assertHandler; MyMessageHandler messageHandler; float scale = 0.5f; float gamma = 2.2f; nv::AutoPtr filter; nv::Path input; nv::Path output; nv::FloatImage::WrapMode wrapMode = nv::FloatImage::WrapMode_Mirror; // Parse arguments. for (int i = 1; i < argc; i++) { // Input options. if (strcmp("-s", argv[i]) == 0) { if (i+1 < argc && argv[i+1][0] != '-') { scale = (float)atof(argv[i+1]); i++; } } else if (strcmp("-g", argv[i]) == 0) { if (i+1 < argc && argv[i+1][0] != '-') { gamma = (float)atof(argv[i+1]); i++; } } else if (strcmp("-f", argv[i]) == 0) { if (i+1 == argc) break; i++; if (strcmp("box", argv[i]) == 0) filter = new nv::BoxFilter(); else if (strcmp("triangle", argv[i]) == 0) filter = new nv::TriangleFilter(); else if (strcmp("quadratic", argv[i]) == 0) filter = new nv::QuadraticFilter(); else if (strcmp("bspline", argv[i]) == 0) filter = new nv::BSplineFilter(); else if (strcmp("mitchell", argv[i]) == 0) filter = new nv::MitchellFilter(); else if (strcmp("lanczos", argv[i]) == 0) filter = new nv::LanczosFilter(); else if (strcmp("kaiser", argv[i]) == 0) { filter = new nv::KaiserFilter(3); ((nv::KaiserFilter *)filter.ptr())->setParameters(4.0f, 1.0f); } } else if (strcmp("-w", argv[i]) == 0) { if (i+1 == argc) break; i++; if (strcmp("mirror", argv[i]) == 0) wrapMode = nv::FloatImage::WrapMode_Mirror; else if (strcmp("repeat", argv[i]) == 0) wrapMode = nv::FloatImage::WrapMode_Repeat; else if (strcmp("clamp", argv[i]) == 0) wrapMode = nv::FloatImage::WrapMode_Clamp; } else if (argv[i][0] != '-') { input = argv[i]; if (i+1 < argc && argv[i+1][0] != '-') { output = argv[i+1]; } break; } } if (input.isNull() || output.isNull()) { printf("NVIDIA Texture Tools - Copyright NVIDIA Corporation 2007\n\n"); printf("usage: nvzoom [options] input [output]\n\n"); printf("Options:\n"); printf(" -s scale Scale factor (default = 0.5)\n"); printf(" -g gamma Gamma correction (default = 2.2)\n"); printf(" -f filter One of the following: (default = 'box')\n"); printf(" * box\n"); printf(" * triangle\n"); printf(" * quadratic\n"); printf(" * bspline\n"); printf(" * mitchell\n"); printf(" * lanczos\n"); printf(" * kaiser\n"); printf(" -w mode One of the following: (default = 'mirror')\n"); printf(" * mirror\n"); printf(" * repeat\n"); printf(" * clamp\n"); return 1; } if (filter == NULL) { filter = new nv::BoxFilter(); } nv::Image image; if (!loadImage(image, input)) return 0; nv::FloatImage fimage(&image); fimage.toLinear(0, 3, gamma); nv::AutoPtr fresult(fimage.resize(*filter, uint(image.width() * scale), uint(image.height() * scale), wrapMode)); nv::AutoPtr result(fresult->createImageGammaCorrect(gamma)); result->setFormat(nv::Image::Format_ARGB); nv::StdOutputStream stream(output); nv::ImageIO::saveTGA(stream, result.ptr()); // @@ Add generic save function. Add support for png too. return 0; }